Skip to content

Commit a833dcc

Browse files
esm: add import.meta.require
1 parent 58a7b00 commit a833dcc

File tree

5 files changed

+80
-1
lines changed

5 files changed

+80
-1
lines changed

doc/api/esm.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,22 @@ import { readFileSync } from 'node:fs';
384384
const buffer = readFileSync(new URL('./data.proto', import.meta.url));
385385
```
386386
387+
### `import.meta.require(filename)`
388+
389+
<!-- YAML
390+
added:
391+
- REPLACEME
392+
-->
393+
394+
> Stability: 1.1 - Active development
395+
396+
* `filename` {string|URL} Filename to be used to construct the require
397+
function. Must be a file URL object, file URL string, or absolute path
398+
string.
399+
* Returns: {any} The module exports.
400+
401+
Alias for [`module.createRequire(import.meta.url)(specifier)`][].
402+
387403
### `import.meta.resolve(specifier)`
388404
389405
<!-- YAML
@@ -1118,6 +1134,7 @@ resolution for ESM specifiers is [commonjs-extension-resolution-loader][].
11181134
[`import.meta.url`]: #importmetaurl
11191135
[`import`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
11201136
[`module.createRequire()`]: module.md#modulecreaterequirefilename
1137+
[`module.createRequire(import.meta.url)(specifier)`]: module.md#modulecreaterequirefilename
11211138
[`module.syncBuiltinESMExports()`]: module.md#modulesyncbuiltinesmexports
11221139
[`package.json`]: packages.md#nodejs-packagejson-field-definitions
11231140
[`path.dirname()`]: path.md#pathdirnamepath

lib/internal/modules/esm/initialize_import_meta.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const {
4+
ObjectDefineProperty,
45
StringPrototypeStartsWith,
56
} = primordials;
67

@@ -9,6 +10,13 @@ const { fileURLToPath } = require('internal/url');
910
const { dirname } = require('path');
1011
const experimentalImportMetaResolve = getOptionValue('--experimental-import-meta-resolve');
1112

13+
// Lazy load module.createRequire
14+
let createRequire;
15+
function loadCreateRequireLazy() {
16+
createRequire ??= require('internal/modules/cjs/loader').Module.createRequire;
17+
return createRequire;
18+
}
19+
1220
/**
1321
* Generate a function to be used as import.meta.resolve for a particular module.
1422
* @param {string} defaultParentURL The default base to use for resolution
@@ -71,6 +79,15 @@ function initializeImportMeta(meta, context, loader) {
7179

7280
meta.url = url;
7381

82+
ObjectDefineProperty(meta, 'require', {
83+
__proto__: null,
84+
enumerable: true,
85+
configurable: true,
86+
get() {
87+
return loadCreateRequireLazy()(url);
88+
},
89+
});
90+
7491
return meta;
7592
}
7693

test/es-module/test-esm-import-meta.mjs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@ import assert from 'assert';
33

44
assert.strictEqual(Object.getPrototypeOf(import.meta), null);
55

6-
const keys = ['dirname', 'filename', 'resolve', 'url'];
6+
const keys = ['dirname', 'filename', 'resolve', 'url', 'require'];
77
assert.deepStrictEqual(Reflect.ownKeys(import.meta), keys);
88

9+
{
10+
const requireDescriptor = Object.getOwnPropertyDescriptor(import.meta, 'require');
11+
assert.strictEqual(requireDescriptor.value, undefined);
12+
assert.strictEqual(requireDescriptor.set, undefined);
13+
assert.strictEqual(requireDescriptor.enumerable, true);
14+
assert.strictEqual(requireDescriptor.writable, undefined);
15+
assert.strictEqual(requireDescriptor.configurable, true);
16+
}
17+
18+
delete import.meta.require; // Verified above.
19+
920
const descriptors = Object.getOwnPropertyDescriptors(import.meta);
1021
for (const descriptor of Object.values(descriptors)) {
1122
delete descriptor.value; // Values are verified below.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import '../common/index.mjs';
2+
import assert from 'node:assert';
3+
4+
{
5+
try {
6+
import.meta.require('does-not-exist');
7+
assert.fail();
8+
} catch (e) {
9+
assert.strictEqual(e.code, 'MODULE_NOT_FOUND');
10+
}
11+
}
12+
13+
{
14+
// Require a built-in module
15+
const requiredAssert = import.meta.require('node:assert');
16+
assert.deepStrictEqual(assert, requiredAssert);
17+
}
18+
19+
{
20+
// Require a esm module
21+
const { foo, bar } = import.meta.require('../fixtures/es-module-loaders/module-named-exports.mjs');
22+
assert.strictEqual(foo, 'foo');
23+
assert.strictEqual(bar, 'bar');
24+
}
25+
26+
{
27+
const { foo, bar } = import.meta.require('../fixtures/es-modules/cjs-module-exports.js');
28+
assert.strictEqual(foo, 'foo');
29+
assert.strictEqual(bar, 'bar');
30+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
foo: 'foo',
3+
bar: 'bar'
4+
}

0 commit comments

Comments
 (0)