Skip to content

Commit e4a0c81

Browse files
committed
esm: detect ESM syntax in ambiguous JavaScript
1 parent 1836cb2 commit e4a0c81

File tree

3 files changed

+54
-19
lines changed

3 files changed

+54
-19
lines changed

doc/api/esm.md

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,21 @@ provides interoperability between them and its original module format,
109109

110110
Node.js has two module systems: [CommonJS][] modules and ECMAScript modules.
111111

112-
Authors can tell Node.js to use the ECMAScript modules loader via the `.mjs`
113-
file extension, the `package.json` [`"type"`][] field, the [`--input-type`][]
114-
flag, or the [`--experimental-default-type`][] flag. Outside of those cases,
115-
Node.js will use the CommonJS module loader. See [Determining module system][]
116-
for more details.
112+
Authors can tell Node.js to interpret JavaScript as an ES module via the `.mjs`
113+
file extension, the `package.json` [`"type"`][] field with a value `"module"`,
114+
the [`--input-type`][] flag with a value of `"module"`, or the
115+
[`--experimental-default-type`][] flag with a value of `"module"`. These are
116+
explicit markers of code being intended to run as an ES module.
117+
118+
Inversely, authors can tell Node.js to interpret JavaScript as CommonJS via the
119+
`.cjs` file extension, the `package.json` [`"type"`][] field with a value
120+
`"commonjs"`, the [`--input-type`][] flag with a value of `"commonjs"`, or the
121+
[`--experimental-default-type`][] flag with a value of `"commonjs"`.
122+
123+
When code lacks explicit markers for either module system, Node.js will attempt
124+
to run JavaScript as CommonJS; if it errors due to syntax that is only supported
125+
in ES modules, it will try again to run the code as an ES module. See
126+
[Determining module system][] for more details.
117127

118128
<!-- Anchors to make sure old links find a target -->
119129

@@ -1019,18 +1029,33 @@ _isImports_, _conditions_)
10191029
> 1. Return _"commonjs"_.
10201030
> 4. If _url_ ends in _".json"_, then
10211031
> 1. Return _"json"_.
1022-
> 5. Let _packageURL_ be the result of **LOOKUP\_PACKAGE\_SCOPE**(_url_).
1023-
> 6. Let _pjson_ be the result of **READ\_PACKAGE\_JSON**(_packageURL_).
1024-
> 7. If _pjson?.type_ exists and is _"module"_, then
1025-
> 1. If _url_ ends in _".js"_ or has no file extension, then
1026-
> 1. If `--experimental-wasm-modules` is enabled and the file at _url_
1027-
> contains the header for a WebAssembly module, then
1028-
> 1. Return _"wasm"_.
1029-
> 2. Otherwise,
1030-
> 1. Return _"module"_.
1031-
> 2. Return **undefined**.
1032-
> 8. Otherwise,
1033-
> 1. Return **undefined**.
1032+
> 5. If `--experimental-wasm-modules` is enabled and _url_ ends in
1033+
> _".wasm"_, then
1034+
> 1. Return _"wasm"_.
1035+
> 6. Let _packageURL_ be the result of **LOOKUP\_PACKAGE\_SCOPE**(_url_).
1036+
> 7. Let _pjson_ be the result of **READ\_PACKAGE\_JSON**(_packageURL_).
1037+
> 8. Let _packageType_ be **null**.
1038+
> 9. If _pjson?.type_ is _"module"_ or _"commonjs"_, then
1039+
> 1. Set _packageType_ to _pjson.type_.
1040+
> 10. If _url_ ends in _".js"_, then
1041+
> 1. If _packageType_ is not **null**, then
1042+
> 1. Return _packageType_.
1043+
> 2. If `--experimental-detect-module` is enabled and the source of
1044+
> module contains static import or export syntax, then
1045+
> 1. Return _"module"_.
1046+
> 3. Return _"commonjs"_.
1047+
> 11. If _url_ does not have any extension, then
1048+
> 1. If _packageType_ is _"module"_ and `--experimental-wasm-modules` is
1049+
> enabled and the file at _url_ contains the header for a WebAssembly
1050+
> module, then
1051+
> 1. Return _"wasm"_.
1052+
> 2. If _packageType_ is not **null**, then
1053+
> 1. Return _packageType_.
1054+
> 3. If `--experimental-detect-module` is enabled and the source of
1055+
> module contains static import or export syntax, then
1056+
> 1. Return _"module"_.
1057+
> 4. Return _"commonjs"_.
1058+
> 12. Return **undefined** (will throw during load phase).
10341059
10351060
**LOOKUP\_PACKAGE\_SCOPE**(_url_)
10361061

doc/api/modules.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ By default, Node.js will treat the following as CommonJS modules:
8080
* Files with a `.js` extension when the nearest parent `package.json` file
8181
contains a top-level field [`"type"`][] with a value of `"commonjs"`.
8282

83-
* Files with a `.js` extension when the nearest parent `package.json` file
84-
doesn't contain a top-level field [`"type"`][]. Package authors should include
83+
* Files with a `.js` extension or without an extension, when the nearest parent
84+
`package.json` file doesn't contain a top-level field [`"type"`][] or there is
85+
no `package.json` in any parent folder; unless the file contains syntax that
86+
errors unless it is evaluated as an ES module. Package authors should include
8587
the [`"type"`][] field, even in packages where all sources are CommonJS. Being
8688
explicit about the `type` of the package will make things easier for build
8789
tools and loaders to determine how the files in the package should be

doc/api/packages.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +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+
* Code that contains syntax that only parses successfully as [ES modules][],
73+
such as `import` or `export` statements or `import.meta`, when the code has no
74+
explicit marker of how it should be interpreted. Explicit markers are `.mjs`
75+
or `.cjs` 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 cause a file to be treated as an ES module.
79+
7280
Node.js will treat the following as [CommonJS][] when passed to `node` as the
7381
initial input, or when referenced by `import` statements or `import()`
7482
expressions:

0 commit comments

Comments
 (0)