Skip to content

Commit

Permalink
module: remove --experimental-default-type
Browse files Browse the repository at this point in the history
PR-URL: nodejs#56092
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Jacob Smith <jacob@frende.me>
GeoffreyBooth authored and targos committed Dec 3, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 30d6041 commit b8ab533
Showing 29 changed files with 86 additions and 869 deletions.
49 changes: 6 additions & 43 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
@@ -25,16 +25,14 @@ For more info about `node inspect`, see the [debugger][] documentation.

The program entry point is a specifier-like string. If the string is not an
absolute path, it's resolved as a relative path from the current working
directory. That path is then resolved by [CommonJS][] module loader, or by the
[ES module loader][Modules loaders] if [`--experimental-default-type=module`][]
is passed. If no corresponding file is found, an error is thrown.
directory. That path is then resolved by [CommonJS][] module loader. If no
corresponding file is found, an error is thrown.

If a file is found, its path will be passed to the
[ES module loader][Modules loaders] under any of the following conditions:

* The program was started with a command-line flag that forces the entry
point to be loaded with ECMAScript module loader, such as `--import` or
[`--experimental-default-type=module`][].
point to be loaded with ECMAScript module loader, such as `--import`.
* The file has an `.mjs` extension.
* The file does not have a `.cjs` extension, and the nearest parent
`package.json` file contains a top-level [`"type"`][] field with a value of
@@ -47,9 +45,8 @@ Otherwise, the file is loaded using the CommonJS module loader. See

When loading, the [ES module loader][Modules loaders] loads the program
entry point, the `node` command will accept as input only files with `.js`,
`.mjs`, or `.cjs` extensions; with `.wasm` extensions when
[`--experimental-wasm-modules`][] is enabled; and with no extension when
[`--experimental-default-type=module`][] is passed.
`.mjs`, or `.cjs` extensions; and with `.wasm` extensions when
[`--experimental-wasm-modules`][] is enabled.

## Options

@@ -910,38 +907,6 @@ flows within the application. As such, it is presently recommended to be sure
your application behaviour is unaffected by this change before using it in
production.

### `--experimental-default-type=type`

<!-- YAML
added:
- v21.0.0
- v20.10.0
- v18.19.0
-->

> Stability: 1.0 - Early development
Define which module system, `module` or `commonjs`, to use for the following:

* String input provided via `--eval` or STDIN, if `--input-type` is unspecified.

* Files ending in `.js` or with no extension, if there is no `package.json` file
present in the same folder or any parent folder.

* Files ending in `.js` or with no extension, if the nearest parent
`package.json` field lacks a `"type"` field; unless the `package.json` folder
or any parent folder is inside a `node_modules` folder.

In other words, `--experimental-default-type=module` flips all the places where
Node.js currently defaults to CommonJS to instead default to ECMAScript modules,
with the exception of folders and subfolders below `node_modules`, for backward
compatibility.

Under `--experimental-default-type=module` and `--experimental-wasm-modules`,
files with no extension will be treated as WebAssembly if they begin with the
WebAssembly magic number (`\0asm`); otherwise they will be treated as ES module
JavaScript.

### `--experimental-transform-types`

<!-- YAML
@@ -1418,7 +1383,7 @@ added: v12.0.0

This configures Node.js to interpret `--eval` or `STDIN` input as CommonJS or
as an ES module. Valid values are `"commonjs"` or `"module"`. The default is
`"commonjs"` unless [`--experimental-default-type=module`][] is used.
`"commonjs"`.

The REPL does not support this option. Usage of `--input-type=module` with
[`--print`][] will throw an error, as `--print` does not support ES module
@@ -3059,7 +3024,6 @@ one is included in the list below.
* `--entry-url`
* `--experimental-abortcontroller`
* `--experimental-async-context-frame`
* `--experimental-default-type`
* `--experimental-detect-module`
* `--experimental-eventsource`
* `--experimental-import-meta-resolve`
@@ -3621,7 +3585,6 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[`--diagnostic-dir`]: #--diagnostic-dirdirectory
[`--env-file-if-exists`]: #--env-file-if-existsconfig
[`--env-file`]: #--env-fileconfig
[`--experimental-default-type=module`]: #--experimental-default-typetype
[`--experimental-sea-config`]: single-executable-applications.md#generating-single-executable-preparation-blobs
[`--experimental-strip-types`]: #--experimental-strip-types
[`--experimental-wasm-modules`]: #--experimental-wasm-modules
14 changes: 6 additions & 8 deletions doc/api/esm.md
Original file line number Diff line number Diff line change
@@ -122,14 +122,13 @@ Node.js has two module systems: [CommonJS][] modules and ECMAScript modules.

Authors can tell Node.js to interpret JavaScript as an ES module via the `.mjs`
file extension, the `package.json` [`"type"`][] field with a value `"module"`,
the [`--input-type`][] flag with a value of `"module"`, or the
[`--experimental-default-type`][] flag with a value of `"module"`. These are
explicit markers of code being intended to run as an ES module.
or the [`--input-type`][] flag with a value of `"module"`. These are explicit
markers of code being intended to run as an ES module.

Inversely, authors can tell Node.js to interpret JavaScript as CommonJS via the
`.cjs` file extension, the `package.json` [`"type"`][] field with a value
`"commonjs"`, the [`--input-type`][] flag with a value of `"commonjs"`, or the
[`--experimental-default-type`][] flag with a value of `"commonjs"`.
Inversely, authors can explicitly tell Node.js to interpret JavaScript as
CommonJS via the `.cjs` file extension, the `package.json` [`"type"`][] field
with a value `"commonjs"`, or the [`--input-type`][] flag with a value of
`"commonjs"`.

When code lacks explicit markers for either module system, Node.js will inspect
the source code of a module to look for ES module syntax. If such syntax is
@@ -1120,7 +1119,6 @@ resolution for ESM specifiers is [commonjs-extension-resolution-loader][].
[URL]: https://url.spec.whatwg.org/
[`"exports"`]: packages.md#exports
[`"type"`]: packages.md#type
[`--experimental-default-type`]: cli.md#--experimental-default-typetype
[`--input-type`]: cli.md#--input-typetype
[`data:` URLs]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
[`export`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
3 changes: 1 addition & 2 deletions doc/api/module.md
Original file line number Diff line number Diff line change
@@ -980,8 +980,7 @@ Omitting vs providing a `source` for `'commonjs'` has very different effects:
registered hooks. This behavior for nullish `source` is temporary — in the
future, nullish `source` will not be supported.
When `node` is run with `--experimental-default-type=commonjs`, the Node.js
internal `load` implementation, which is the value of `next` for the
The Node.js internal `load` implementation, which is the value of `next` for the
last hook in the `load` chain, returns `null` for `source` when `format` is
`'commonjs'` for backward compatibility. Here is an example hook that would
opt-in to using the non-default behavior:
53 changes: 20 additions & 33 deletions doc/api/packages.md
Original file line number Diff line number Diff line change
@@ -73,10 +73,9 @@ expressions:
`import` or `export` statements or `import.meta`, with no explicit marker of
how it should be interpreted. Explicit markers are `.mjs` or `.cjs`
extensions, `package.json` `"type"` fields with either `"module"` or
`"commonjs"` values, or `--input-type` or `--experimental-default-type` flags.
Dynamic `import()` expressions are supported in either CommonJS or ES modules
and would not force a file to be treated as an ES module. See
[Syntax detection][].
`"commonjs"` values, or the `--input-type` flag. Dynamic `import()`
expressions are supported in either CommonJS or ES modules and would not force
a file to be treated as an ES module. See [Syntax detection][].

Node.js will treat the following as [CommonJS][] when passed to `node` as the
initial input, or when referenced by `import` statements or `import()`
@@ -90,30 +89,21 @@ expressions:
* Strings passed in as an argument to `--eval` or `--print`, or piped to `node`
via `STDIN`, with the flag `--input-type=commonjs`.

Aside from these explicit cases, there are other cases where Node.js defaults to
one module system or the other based on the value of the
[`--experimental-default-type`][] flag:

* Files ending in `.js` or with no extension, if there is no `package.json` file
present in the same folder or any parent folder.

* Files ending in `.js` or with no extension, if the nearest parent
`package.json` field lacks a `"type"` field; unless the folder is inside a
`node_modules` folder. (Package scopes under `node_modules` are always treated
as CommonJS when the `package.json` file lacks a `"type"` field, regardless
of `--experimental-default-type`, for backward compatibility.)

* Strings passed in as an argument to `--eval` or piped to `node` via `STDIN`,
when `--input-type` is unspecified.

This flag currently defaults to `"commonjs"`, but it may change in the future to
default to `"module"`. For this reason it is best to be explicit wherever
possible; in particular, package authors should always include the [`"type"`][]
field in their `package.json` files, even in packages where all sources are
CommonJS. Being explicit about the `type` of the package will future-proof the
package in case the default type of Node.js ever changes, and it will also make
things easier for build tools and loaders to determine how the files in the
package should be interpreted.
* Files with a `.js` extension with no parent `package.json` file or where the
nearest parent `package.json` file lacks a `type` field, and where the code
can evaluate successfully as CommonJS. In other words, Node.js tries to run
such "ambiguous" files as CommonJS first, and will retry evaluating them as ES
modules if the evaluation as CommonJS fails because the parser found ES module
syntax.

Writing ES module syntax in "ambiguous" files incurs a performance cost, and
therefore it is encouraged that authors be explicit wherever possible. In
particular, package authors should always include the [`"type"`][] field in
their `package.json` files, even in packages where all sources are CommonJS.
Being explicit about the `type` of the package will future-proof the package in
case the default type of Node.js ever changes, and it will also make things
easier for build tools and loaders to determine how the files in the package
should be interpreted.

### Syntax detection

@@ -137,10 +127,8 @@ as an ES module.
Ambiguous input is defined as:

* Files with a `.js` extension or no extension; and either no controlling
`package.json` file or one that lacks a `type` field; and
`--experimental-default-type` is not specified.
* String input (`--eval` or STDIN) when neither `--input-type` nor
`--experimental-default-type` are specified.
`package.json` file or one that lacks a `type` field.
* String input (`--eval` or `STDIN`) when `--input-type`is not specified.

ES module syntax is defined as syntax that would throw when evaluated as
CommonJS. This includes the following:
@@ -1162,7 +1150,6 @@ This field defines [subpath imports][] for the current package.
[`"packageManager"`]: #packagemanager
[`"type"`]: #type
[`--conditions` / `-C` flag]: #resolving-user-conditions
[`--experimental-default-type`]: cli.md#--experimental-default-typetype
[`--no-addons` flag]: cli.md#--no-addons
[`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.md#err_package_path_not_exported
[`package.json`]: #nodejs-packagejson-field-definitions
5 changes: 0 additions & 5 deletions doc/node.1
Original file line number Diff line number Diff line change
@@ -163,11 +163,6 @@ Enable Source Map V3 support for stack traces.
.It Fl -entry-url
Interpret the entry point as a URL.
.
.It Fl -experimental-default-type Ns = Ns Ar type
Interpret as either ES modules or CommonJS modules input via --eval or STDIN, when --input-type is unspecified;
.js or extensionless files with no sibling or parent package.json;
.js or extensionless files whose nearest parent package.json lacks a "type" field, unless under node_modules.
.
.It Fl -experimental-import-meta-resolve
Enable experimental ES modules support for import.meta.resolve().
.
4 changes: 1 addition & 3 deletions lib/internal/main/check_syntax.js
Original file line number Diff line number Diff line change
@@ -59,9 +59,7 @@ function loadESMIfNeeded(cb) {
async function checkSyntax(source, filename) {
let format;
if (filename === '[stdin]' || filename === '[eval]') {
format = (getOptionValue('--input-type') === 'module' ||
(getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) ?
'module' : 'commonjs';
format = (getOptionValue('--input-type') === 'module') ? 'module' : 'commonjs';
} else {
const { defaultResolve } = require('internal/modules/esm/resolve');
const { defaultGetFormat } = require('internal/modules/esm/get_format');
3 changes: 1 addition & 2 deletions lib/internal/main/eval_stdin.js
Original file line number Diff line number Diff line change
@@ -25,8 +25,7 @@ readStdin((code) => {

const print = getOptionValue('--print');
const shouldLoadESM = getOptionValue('--import').length > 0;
if (getOptionValue('--input-type') === 'module' ||
(getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) {
if (getOptionValue('--input-type') === 'module') {
evalModuleEntryPoint(code, print);
} else {
evalScript('[stdin]',
3 changes: 1 addition & 2 deletions lib/internal/main/eval_string.js
Original file line number Diff line number Diff line change
@@ -29,8 +29,7 @@ const source = getOptionValue('--experimental-strip-types') ?

const print = getOptionValue('--print');
const shouldLoadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0;
if (getOptionValue('--input-type') === 'module' ||
(getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) {
if (getOptionValue('--input-type') === 'module') {
evalModuleEntryPoint(source, print);
} else {
// For backward compatibility, we want the identifier crypto to be the
20 changes: 8 additions & 12 deletions lib/internal/main/run_main_module.js
Original file line number Diff line number Diff line change
@@ -23,15 +23,11 @@ if (isEntryURL) {
emitExperimentalWarning('--entry-url');
}

if (getOptionValue('--experimental-default-type') === 'module') {
require('internal/modules/run_main').executeUserEntryPoint(mainEntry);
} else {
/**
* To support legacy monkey-patching of `Module.runMain`, we call `runMain` here to have the CommonJS loader begin
* the execution of the main entry point, even if the ESM loader immediately takes over because the main entry is an
* ES module or one of the other opt-in conditions (such as the use of `--import`) are met. Users can monkey-patch
* before the main entry point is loaded by doing so via scripts loaded through `--require`. This monkey-patchability
* is undesirable and is removed in `--experimental-default-type=module` mode.
*/
require('internal/modules/cjs/loader').Module.runMain(mainEntry);
}
/**
* To support legacy monkey-patching of `Module.runMain`, we call `runMain` here to have the CommonJS loader begin the
* execution of the main entry point, even if the ESM loader immediately takes over because the main entry is an ES
* module or one of the other opt-in conditions (such as the use of `--import`) are met. Users can monkey-patch before
* the main entry point is loaded by doing so via scripts loaded through `--require`. This monkey-patchability is
* undesirable and should be removed once the module customization hooks provide equivalent functionality.
*/
require('internal/modules/cjs/loader').Module.runMain(mainEntry);
4 changes: 2 additions & 2 deletions lib/internal/modules/esm/formats.js
Original file line number Diff line number Diff line change
@@ -46,8 +46,8 @@ function mimeToFormat(mime) {
}

/**
* For extensionless files in a `module` package scope, or a default `module` scope enabled by the
* `--experimental-default-type` flag, we check the file contents to disambiguate between ES module JavaScript and Wasm.
* For extensionless files in a `module` package scope, we check the file contents to disambiguate between ES module
* JavaScript and Wasm.
* We do this by taking advantage of the fact that all Wasm files start with the header `0x00 0x61 0x73 0x6d` (`_asm`).
* @param {URL} url
*/
Loading

0 comments on commit b8ab533

Please sign in to comment.