Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esm: Unflag --experimental-modules #29866

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions doc/api/cli.md
Expand Up @@ -161,8 +161,8 @@ Currently, overriding `Error.prepareStackTrace` is ignored when the
added: v12.0.0
-->

To be used in conjunction with `--experimental-modules`. Sets the resolution
algorithm for resolving specifiers. Valid options are `explicit` and `node`.
Sets the resolution algorithm for resolving ES module specifiers. Valid options
are `explicit` and `node`.

The default is `explicit`, which requires providing the full path to a
module. The `node` mode will enable support for optional file extensions and
Expand Down Expand Up @@ -191,7 +191,8 @@ Enable experimental JSON support for the ES Module loader.
added: v8.5.0
-->

Enable experimental ES module support and caching modules.
Enable latest experimental modules features (currently
`--experimental-conditional-exports` and `--experimental-self-resolve`).

### `--experimental-policy`
<!-- YAML
Expand Down Expand Up @@ -342,9 +343,8 @@ Specify ICU data load path. (Overrides `NODE_ICU_DATA`.)
added: v12.0.0
-->

Used with `--experimental-modules`, this configures Node.js to interpret string
input as CommonJS or as an ES module. String input is input via `--eval`,
`--print`, or `STDIN`.
This configures Node.js to interpret string input as CommonJS or as an ES
module. String input is input via `--eval`, `--print`, or `STDIN`.

Valid values are `"commonjs"` and `"module"`. The default is `"commonjs"`.

Expand Down Expand Up @@ -409,7 +409,7 @@ endpoint on `http://host:port/json/list`.
added: v9.0.0
-->

Specify the `module` of a custom [experimental ECMAScript Module][] loader.
Specify the `module` of a custom [experimental ECMAScript Module loader][].
`module` may be either a path to a file, or an ECMAScript Module name.

### `--max-http-header-size=size`
Expand Down Expand Up @@ -1330,7 +1330,7 @@ greater than `4` (its current default value). For more information, see the
[debugger]: debugger.html
[debugging security implications]: https://nodejs.org/en/docs/guides/debugging-getting-started/#security-implications
[emit_warning]: process.html#process_process_emitwarning_warning_type_code_ctor
[experimental ECMAScript Module]: esm.html#esm_resolve_hook
[experimental ECMAScript Module loader]: esm.html#esm_resolve_hook
[libuv threadpool documentation]: http://docs.libuv.org/en/latest/threadpool.html
[remote code execution]: https://www.owasp.org/index.php/Code_Injection
[context-aware]: addons.html#addons_context_aware_addons
Expand Down
36 changes: 15 additions & 21 deletions doc/api/esm.md
Expand Up @@ -27,12 +27,9 @@ specifier resolution, and default behavior.

<!-- type=misc -->

The `--experimental-modules` flag can be used to enable support for
ECMAScript modules (ES modules).

Once enabled, Node.js will treat the following as ES modules when passed to
`node` as the initial input, or when referenced by `import` statements within
ES module code:
Experimental support for ECMAScript modules is enabled by default.
Node.js will treat the following as ES modules when passed to `node` as the
initial input, or when referenced by `import` statements within ES module code:

* Files ending in `.mjs`.

Expand Down Expand Up @@ -80,7 +77,7 @@ until the root of the volume is reached.

```sh
# In same folder as above package.json
node --experimental-modules my-app.js # Runs as ES module
node my-app.js # Runs as ES module
```

If the nearest parent `package.json` lacks a `"type"` field, or contains
Expand Down Expand Up @@ -114,9 +111,8 @@ own `package.json` file, so each project’s dependencies have their own package
scopes. A `package.json` lacking a `"type"` field is treated as if it contained
`"type": "commonjs"`.

The package scope applies not only to initial entry points (`node
--experimental-modules my-app.js`) but also to files referenced by `import`
statements and `import()` expressions.
The package scope applies not only to initial entry points (`node my-app.js`)
but also to files referenced by `import` statements and `import()` expressions.

```js
// my-app.js, in an ES module package scope because there is a package.json
Expand Down Expand Up @@ -169,11 +165,9 @@ piped to `node` via `STDIN`, will be treated as ES modules when the
`--input-type=module` flag is set.

```sh
node --experimental-modules --input-type=module --eval \
"import { sep } from 'path'; console.log(sep);"
node --input-type=module --eval "import { sep } from 'path'; console.log(sep);"

echo "import { sep } from 'path'; console.log(sep);" | \
node --experimental-modules --input-type=module
echo "import { sep } from 'path'; console.log(sep);" | node --input-type=module
```

For completeness there is also `--input-type=commonjs`, for explicitly running
Expand Down Expand Up @@ -927,8 +921,8 @@ The `--experimental-json-modules` flag is needed for the module
to work.

```bash
node --experimental-modules index.mjs # fails
node --experimental-modules --experimental-json-modules index.mjs # works
node index.mjs # fails
node --experimental-json-modules index.mjs # works
```

## Experimental Wasm Modules
Expand All @@ -950,7 +944,7 @@ console.log(M);
executed under:

```bash
node --experimental-modules --experimental-wasm-modules index.mjs
node --experimental-wasm-modules index.mjs
```

would provide the exports interface for the instantiation of `module.wasm`.
Expand Down Expand Up @@ -1061,7 +1055,7 @@ export async function resolve(specifier,
With this loader, running:

```console
NODE_OPTIONS='--experimental-modules --experimental-loader ./custom-loader.mjs' node x.js
NODE_OPTIONS='--experimental-loader ./custom-loader.mjs' node x.js
```

would load the module `x.js` as an ES module with relative resolution support
Expand Down Expand Up @@ -1352,11 +1346,11 @@ automatic extension resolution and importing from directories that include an
index file use the `node` mode.

```bash
$ node --experimental-modules index.mjs
$ node index.mjs
success!
$ node --experimental-modules index #Failure!
$ node index # Failure!
Error: Cannot find module
$ node --experimental-modules --es-module-specifier-resolution=node index
$ node --es-module-specifier-resolution=node index
success!
```

Expand Down
16 changes: 8 additions & 8 deletions doc/api/vm.md
Expand Up @@ -88,8 +88,8 @@ changes:
* `importModuleDynamically` {Function} Called during evaluation of this module
when `import()` is called. If this option is not specified, calls to
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
This option is part of the experimental API for the `--experimental-modules`
flag, and should not be considered stable.
This option is part of the experimental modules API, and should not be
considered stable.
* `specifier` {string} specifier passed to `import()`
* `module` {vm.Module}
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -854,8 +854,8 @@ changes:
* `importModuleDynamically` {Function} Called during evaluation of this module
when `import()` is called. If this option is not specified, calls to
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
This option is part of the experimental API for the `--experimental-modules`
flag, and should not be considered stable.
This option is part of the experimental modules API, and should not be
considered stable.
* `specifier` {string} specifier passed to `import()`
* `module` {vm.Module}
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -951,8 +951,8 @@ changes:
* `importModuleDynamically` {Function} Called during evaluation of this module
when `import()` is called. If this option is not specified, calls to
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
This option is part of the experimental API for the `--experimental-modules`
flag, and should not be considered stable.
This option is part of the experimental modules API, and should not be
considered stable.
* `specifier` {string} specifier passed to `import()`
* `module` {vm.Module}
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -1028,8 +1028,8 @@ changes:
* `importModuleDynamically` {Function} Called during evaluation of this module
when `import()` is called. If this option is not specified, calls to
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
This option is part of the experimental API for the `--experimental-modules`
flag, and should not be considered stable.
This option is part of the experimental modules API, and should not be
considered stable.
* `specifier` {string} specifier passed to `import()`
* `module` {vm.Module}
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down
5 changes: 2 additions & 3 deletions doc/node.1
Expand Up @@ -120,7 +120,7 @@ Enable experimental support for "require" and "node" conditional export targets.
Enable experimental JSON interop support for the ES Module loader.
.
.It Fl -experimental-modules
Enable experimental ES module support and caching modules.
Enable experimental latest experimental modules features.
.
.It Fl -experimental-resolve-self
Enable experimental support for a package to load itself.
Expand Down Expand Up @@ -208,8 +208,7 @@ It uses the Chrome DevTools Protocol.
.It Fl -experimental-loader Ns = Ns Ar module
Specify the
.Ar module
as a custom loader, to load
.Fl -experimental-modules .
to use as a custom module loader.
.
.It Fl -max-http-header-size Ns = Ns Ar size
Specify the maximum size of HTTP headers in bytes. Defaults to 8KB.
Expand Down
18 changes: 8 additions & 10 deletions lib/internal/bootstrap/loaders.js
Expand Up @@ -211,23 +211,21 @@ function requireWithFallbackInDeps(request) {
}

// This is exposed for public loaders
NativeModule.prototype.compileForPublicLoader = function(needToSyncExports) {
NativeModule.prototype.compileForPublicLoader = function() {
if (!this.canBeRequiredByUsers) {
// No code because this is an assertion against bugs
// eslint-disable-next-line no-restricted-syntax
throw new Error(`Should not compile ${this.id} for public use`);
}
this.compile();
if (needToSyncExports) {
if (!this.exportKeys) {
// When using --expose-internals, we do not want to reflect the named
// exports from core modules as this can trigger unnecessary getters.
const internal = this.id.startsWith('internal/');
this.exportKeys = internal ? [] : Object.keys(this.exports);
}
this.getESMFacade();
this.syncExports();
if (!this.exportKeys) {
// When using --expose-internals, we do not want to reflect the named
// exports from core modules as this can trigger unnecessary getters.
const internal = this.id.startsWith('internal/');
this.exportKeys = internal ? [] : Object.keys(this.exports);
}
this.getESMFacade();
this.syncExports();
return this.exports;
};

Expand Down
30 changes: 9 additions & 21 deletions lib/internal/bootstrap/pre_execution.js
Expand Up @@ -401,24 +401,15 @@ function initializeESMLoader() {
// Create this WeakMap in js-land because V8 has no C++ API for WeakMap.
internalBinding('module_wrap').callbackMap = new SafeWeakMap();

const experimentalModules = getOptionValue('--experimental-modules');
const experimentalVMModules = getOptionValue('--experimental-vm-modules');
if (experimentalModules || experimentalVMModules) {
if (experimentalModules) {
process.emitWarning(
'The ESM module loader is experimental.',
'ExperimentalWarning', undefined);
}
const {
setImportModuleDynamicallyCallback,
setInitializeImportMetaObjectCallback
} = internalBinding('module_wrap');
const esm = require('internal/process/esm_loader');
// Setup per-isolate callbacks that locate data or callbacks that we keep
// track of for different ESM modules.
setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject);
setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback);
}
const {
setImportModuleDynamicallyCallback,
setInitializeImportMetaObjectCallback
} = internalBinding('module_wrap');
const esm = require('internal/process/esm_loader');
// Setup per-isolate callbacks that locate data or callbacks that we keep
// track of for different ESM modules.
setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject);
setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback);
}

function initializeFrozenIntrinsics() {
Expand Down Expand Up @@ -460,9 +451,6 @@ function resolveMainPath(main) {
}

function shouldUseESMLoader(mainPath) {
const experimentalModules = getOptionValue('--experimental-modules');
if (!experimentalModules)
return false;
const userLoader = getOptionValue('--experimental-loader');
if (userLoader)
return true;
Expand Down
27 changes: 12 additions & 15 deletions lib/internal/main/check_syntax.js
Expand Up @@ -47,21 +47,18 @@ if (process.argv[1] && process.argv[1] !== '-') {

function checkSyntax(source, filename) {
const { getOptionValue } = require('internal/options');
const experimentalModules = getOptionValue('--experimental-modules');
if (experimentalModules) {
let isModule = false;
if (filename === '[stdin]' || filename === '[eval]') {
isModule = getOptionValue('--input-type') === 'module';
} else {
const resolve = require('internal/modules/esm/default_resolve');
const { format } = resolve(pathToFileURL(filename).toString());
isModule = format === 'module';
}
if (isModule) {
const { ModuleWrap } = internalBinding('module_wrap');
new ModuleWrap(filename, undefined, source, 0, 0);
return;
}
let isModule = false;
if (filename === '[stdin]' || filename === '[eval]') {
isModule = getOptionValue('--input-type') === 'module';
} else {
const resolve = require('internal/modules/esm/default_resolve');
const { format } = resolve(pathToFileURL(filename).toString());
isModule = format === 'module';
}
if (isModule) {
const { ModuleWrap } = internalBinding('module_wrap');
new ModuleWrap(filename, undefined, source, 0, 0);
return;
}

wrapSafe(filename, source);
Expand Down
5 changes: 2 additions & 3 deletions lib/internal/main/run_main_module.js
Expand Up @@ -10,7 +10,6 @@ const CJSModule = require('internal/modules/cjs/loader').Module;

markBootstrapComplete();

// Note: this loads the module through the ESM loader if
// --experimental-loader is provided or --experimental-modules is on
// and the module is determined to be an ES module
// Note: this loads the module through the ESM loader if the module is
// determined to be an ES module
CJSModule.runMain(process.argv[1]);
11 changes: 3 additions & 8 deletions lib/internal/modules/cjs/helpers.js
Expand Up @@ -6,8 +6,6 @@ const {
ERR_UNKNOWN_BUILTIN_MODULE
} = require('internal/errors').codes;
const { NativeModule } = require('internal/bootstrap/loaders');
const { getOptionValue } = require('internal/options');
const experimentalModules = getOptionValue('--experimental-modules');

const { validateString } = require('internal/validators');
const path = require('path');
Expand All @@ -16,11 +14,11 @@ const { URL } = require('url');

const debug = require('internal/util/debuglog').debuglog('module');

function loadNativeModule(filename, request, experimentalModules) {
function loadNativeModule(filename, request) {
const mod = NativeModule.map.get(filename);
if (mod) {
debug('load native module %s', request);
mod.compileForPublicLoader(experimentalModules);
mod.compileForPublicLoader();
return mod;
}
}
Expand All @@ -45,10 +43,7 @@ function makeRequireFunction(mod, redirects) {
const href = destination.href;
if (destination.protocol === 'node:') {
const specifier = destination.pathname;
const mod = loadNativeModule(
specifier,
href,
experimentalModules);
const mod = loadNativeModule(specifier, href);
if (mod && mod.canBeRequiredByUsers) {
return mod.exports;
}
Expand Down