Skip to content

Commit 46a5325

Browse files
GeoffreyBoothjoyeecheung
authored andcommitted
module: unflag detect-module
PR-URL: nodejs#53619 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent ffe1543 commit 46a5325

20 files changed

+126
-131
lines changed

doc/api/cli.md

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -887,38 +887,6 @@ files with no extension will be treated as WebAssembly if they begin with the
887887
WebAssembly magic number (`\0asm`); otherwise they will be treated as ES module
888888
JavaScript.
889889

890-
### `--experimental-detect-module`
891-
892-
<!-- YAML
893-
added:
894-
- v20.10.0
895-
-->
896-
897-
> Stability: 1.1 - Active development
898-
899-
Node.js will inspect the source code of ambiguous input to determine whether it
900-
contains ES module syntax; if such syntax is detected, the input will be treated
901-
as an ES module.
902-
903-
Ambiguous input is defined as:
904-
905-
* Files with a `.js` extension or no extension; and either no controlling
906-
`package.json` file or one that lacks a `type` field; and
907-
`--experimental-default-type` is not specified.
908-
* String input (`--eval` or STDIN) when neither `--input-type` nor
909-
`--experimental-default-type` are specified.
910-
911-
ES module syntax is defined as syntax that would throw when evaluated as
912-
CommonJS. This includes the following:
913-
914-
* `import` statements (but _not_ `import()` expressions, which are valid in
915-
CommonJS).
916-
* `export` statements.
917-
* `import.meta` references.
918-
* `await` at the top level of a module.
919-
* Lexical redeclarations of the CommonJS wrapper variables (`require`, `module`,
920-
`exports`, `__dirname`, `__filename`).
921-
922890
### `--experimental-eventsource`
923891

924892
<!-- YAML
@@ -1527,6 +1495,21 @@ added: v0.8.0
15271495

15281496
Silence deprecation warnings.
15291497

1498+
### `--no-experimental-detect-module`
1499+
1500+
<!-- YAML
1501+
added:
1502+
- v21.1.0
1503+
- v20.10.0
1504+
changes:
1505+
- version:
1506+
- REPLACEME
1507+
pr-url: https://github.com/nodejs/node/pull/53619
1508+
description: Syntax detection is enabled by default.
1509+
-->
1510+
1511+
Disable using [syntax detection][] to determine module type.
1512+
15301513
### `--no-experimental-fetch`
15311514

15321515
<!-- YAML
@@ -3361,6 +3344,11 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
33613344
[security warning]: #warning-binding-inspector-to-a-public-ipport-combination-is-insecure
33623345
[semi-space]: https://www.memorymanagement.org/glossary/s.html#semi.space
33633346
[single executable application]: single-executable-applications.md
3347+
<<<<<<< HEAD
3348+
=======
3349+
[snapshot testing]: test.md#snapshot-testing
3350+
[syntax detection]: packages.md#syntax-detection
3351+
>>>>>>> 604ce4cc66 (module: unflag detect-module)
33643352
[test reporters]: test.md#test-reporters
33653353
[timezone IDs]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
33663354
[tracking issue for user-land snapshots]: https://github.com/nodejs/node/issues/44014

doc/api/esm.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,8 +1064,7 @@ _isImports_, _conditions_)
10641064
> 10. If _url_ ends in _".js"_, then
10651065
> 1. If _packageType_ is not **null**, then
10661066
> 1. Return _packageType_.
1067-
> 2. If `--experimental-detect-module` is enabled and the result of
1068-
> **DETECT\_MODULE\_SYNTAX**(_source_) is true, then
1067+
> 2. If the result of **DETECT\_MODULE\_SYNTAX**(_source_) is true, then
10691068
> 1. Return _"module"_.
10701069
> 3. Return _"commonjs"_.
10711070
> 11. If _url_ does not have any extension, then
@@ -1075,8 +1074,7 @@ _isImports_, _conditions_)
10751074
> 1. Return _"wasm"_.
10761075
> 2. If _packageType_ is not **null**, then
10771076
> 1. Return _packageType_.
1078-
> 3. If `--experimental-detect-module` is enabled and the source of
1079-
> module contains static import or export syntax, then
1077+
> 3. If the result of **DETECT\_MODULE\_SYNTAX**(_source_) is true, then
10801078
> 1. Return _"module"_.
10811079
> 4. Return _"commonjs"_.
10821080
> 12. Return **undefined** (will throw during load phase).

doc/api/modules.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ loaded by `require()` meets the following requirements:
192192
1. The file has a `.mjs` extension.
193193
2. The file has a `.js` extension, and the closest `package.json` contains `"type": "module"`
194194
3. The file has a `.js` extension, the closest `package.json` does not contain
195-
`"type": "commonjs"`, and `--experimental-detect-module` is enabled.
195+
`"type": "commonjs"`, and the module contains ES module syntax.
196196

197197
`require()` will load the requested module as an ES Module, and return
198198
the module namespace object. In this case it is similar to dynamic
@@ -279,7 +279,7 @@ require(X) from module at path Y
279279
280280
MAYBE_DETECT_AND_LOAD(X)
281281
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
282-
2. Else, if `--experimental-require-module` and `--experimental-detect-module` are
282+
2. Else, if `--experimental-require-module` is
283283
enabled, and the source code of X can be parsed as ECMAScript module using
284284
<a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in
285285
the ESM resolver</a>,

doc/api/packages.md

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ expressions:
6969
* Strings passed in as an argument to `--eval`, or piped to `node` via `STDIN`,
7070
with the flag `--input-type=module`.
7171

72-
* When using [`--experimental-detect-module`][], code containing syntax only
73-
successfully parsed as [ES modules][], such as `import` or `export`
74-
statements or `import.meta`, having no explicit marker of how it should be
75-
interpreted. Explicit markers are `.mjs` or `.cjs` extensions, `package.json`
76-
`"type"` fields with either `"module"` or `"commonjs"` values, or
77-
`--input-type` or `--experimental-default-type` flags. Dynamic `import()`
78-
expressions are supported in either CommonJS or ES modules and would not
79-
cause a file to be treated as an ES module.
72+
* Code containing syntax only successfully parsed as [ES modules][], such as
73+
`import` or `export` statements or `import.meta`, with no explicit marker of
74+
how it should be interpreted. Explicit markers are `.mjs` or `.cjs`
75+
extensions, `package.json` `"type"` fields with either `"module"` or
76+
`"commonjs"` values, or `--input-type` or `--experimental-default-type` flags.
77+
Dynamic `import()` expressions are supported in either CommonJS or ES modules
78+
and would not force a file to be treated as an ES module. See
79+
[Syntax detection][].
8080

8181
Node.js will treat the following as [CommonJS][] when passed to `node` as the
8282
initial input, or when referenced by `import` statements or `import()`
@@ -115,6 +115,44 @@ package in case the default type of Node.js ever changes, and it will also make
115115
things easier for build tools and loaders to determine how the files in the
116116
package should be interpreted.
117117

118+
### Syntax detection
119+
120+
<!-- YAML
121+
added:
122+
- v21.1.0
123+
- v20.10.0
124+
changes:
125+
- version:
126+
- REPLACEME
127+
pr-url: https://github.com/nodejs/node/pull/53619
128+
description: Syntax detection is enabled by default.
129+
-->
130+
131+
> Stability: 1.2 - Release candidate
132+
133+
Node.js will inspect the source code of ambiguous input to determine whether it
134+
contains ES module syntax; if such syntax is detected, the input will be treated
135+
as an ES module.
136+
137+
Ambiguous input is defined as:
138+
139+
* Files with a `.js` extension or no extension; and either no controlling
140+
`package.json` file or one that lacks a `type` field; and
141+
`--experimental-default-type` is not specified.
142+
* String input (`--eval` or STDIN) when neither `--input-type` nor
143+
`--experimental-default-type` are specified.
144+
145+
ES module syntax is defined as syntax that would throw when evaluated as
146+
CommonJS. This includes the following:
147+
148+
* `import` statements (but _not_ `import()` expressions, which are valid in
149+
CommonJS).
150+
* `export` statements.
151+
* `import.meta` references.
152+
* `await` at the top level of a module.
153+
* Lexical redeclarations of the CommonJS wrapper variables (`require`, `module`,
154+
`exports`, `__dirname`, `__filename`).
155+
118156
### Modules loaders
119157

120158
Node.js has two systems for resolving a specifier and loading modules.
@@ -1355,6 +1393,7 @@ This field defines [subpath imports][] for the current package.
13551393
[ES modules]: esm.md
13561394
[Node.js documentation for this section]: https://github.com/nodejs/node/blob/HEAD/doc/api/packages.md#conditions-definitions
13571395
[Runtime Keys]: https://runtime-keys.proposal.wintercg.org/
1396+
[Syntax detection]: #syntax-detection
13581397
[WinterCG]: https://wintercg.org/
13591398
[`"exports"`]: #exports
13601399
[`"imports"`]: #imports
@@ -1364,7 +1403,6 @@ This field defines [subpath imports][] for the current package.
13641403
[`"type"`]: #type
13651404
[`--conditions` / `-C` flag]: #resolving-user-conditions
13661405
[`--experimental-default-type`]: cli.md#--experimental-default-typetype
1367-
[`--experimental-detect-module`]: cli.md#--experimental-detect-module
13681406
[`--no-addons` flag]: cli.md#--no-addons
13691407
[`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.md#err_package_path_not_exported
13701408
[`esm`]: https://github.com/standard-things/esm#readme

lib/internal/main/check_syntax.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,23 @@ function loadESMIfNeeded(cb) {
5757
}
5858

5959
async function checkSyntax(source, filename) {
60-
let isModule = true;
60+
let format;
6161
if (filename === '[stdin]' || filename === '[eval]') {
62-
isModule = getOptionValue('--input-type') === 'module' ||
63-
(getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs');
62+
format = (getOptionValue('--input-type') === 'module' ||
63+
(getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) ?
64+
'module' : 'commonjs';
6465
} else {
6566
const { defaultResolve } = require('internal/modules/esm/resolve');
6667
const { defaultGetFormat } = require('internal/modules/esm/get_format');
6768
const { url } = await defaultResolve(pathToFileURL(filename).toString());
68-
const format = await defaultGetFormat(new URL(url));
69-
isModule = format === 'module';
69+
format = await defaultGetFormat(new URL(url));
7070
}
7171

72-
if (isModule) {
72+
if (format === 'module') {
7373
const { ModuleWrap } = internalBinding('module_wrap');
7474
new ModuleWrap(filename, undefined, source, 0, 0);
7575
return;
7676
}
7777

78-
wrapSafe(filename, source, undefined, 'commonjs');
78+
wrapSafe(filename, source, undefined, format);
7979
}

lib/internal/modules/run_main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ function runEntryPointWithESMLoader(callback) {
149149
* by `require('module')`) even when the entry point is ESM.
150150
* This monkey-patchable code is bypassed under `--experimental-default-type=module`.
151151
* Because of backwards compatibility, this function is exposed publicly via `import { runMain } from 'node:module'`.
152-
* When `--experimental-detect-module` is passed, this function will attempt to run ambiguous (no explicit extension, no
152+
* Because of module detection, this function will attempt to run ambiguous (no explicit extension, no
153153
* `package.json` type field) entry points as CommonJS first; under certain conditions, it will retry running as ESM.
154154
* @param {string} main - First positional CLI argument, such as `'entry.js'` from `node entry.js`
155155
*/

src/node_options.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
364364
"when ambiguous modules fail to evaluate because they contain "
365365
"ES module syntax, try again to evaluate them as ES modules",
366366
&EnvironmentOptions::detect_module,
367-
kAllowedInEnvvar);
367+
kAllowedInEnvvar,
368+
true);
368369
AddOption("--experimental-print-required-tla",
369370
"Print pending top-level await. If --experimental-require-module "
370371
"is true, evaluate asynchronous graphs loaded by `require()` but "

src/node_options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class EnvironmentOptions : public Options {
115115
public:
116116
bool abort_on_uncaught_exception = false;
117117
std::vector<std::string> conditions;
118-
bool detect_module = false;
118+
bool detect_module = true;
119119
bool print_required_tla = false;
120120
bool require_module = false;
121121
std::string dns_result_order;

test/es-module/test-esm-cjs-exports.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ describe('ESM: importing CJS', { concurrency: true }, () => {
2121
const invalidEntry = fixtures.path('/es-modules/cjs-exports-invalid.mjs');
2222
const { code, signal, stderr } = await spawnPromisified(execPath, [invalidEntry]);
2323

24+
assert.match(stderr, /SyntaxError: The requested module '\.\/invalid-cjs\.js' does not provide an export named 'default'/);
2425
assert.strictEqual(code, 1);
2526
assert.strictEqual(signal, null);
26-
assert.ok(stderr.includes('Warning: To load an ES module'));
27-
assert.ok(stderr.includes('Unexpected token \'export\''));
2827
});
2928
});

0 commit comments

Comments
 (0)