Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa26662

Browse files
GeoffreyBoothcodebytere
authored andcommitted
module: drop support for extensionless main entry points in esm
PR-URL: #31415 Reviewed-By: Guy Bedford <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Bradley Farias <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent ca81af7 commit aa26662

File tree

7 files changed

+66
-60
lines changed

7 files changed

+66
-60
lines changed

β€Ždoc/api/esm.mdβ€Ž

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ initial input, or when referenced by `import` statements within ES module code:
3333

3434
* Files ending in `.mjs`.
3535

36-
* Files ending in `.js`, or extensionless files when run as main entry points on
37-
the command line, when the nearest parent `package.json` file contains a
36+
* Files ending in `.js` when the nearest parent `package.json` file contains a
3837
top-level field `"type"` with a value of `"module"`.
3938

4039
* Strings passed in as an argument to `--eval` or `--print`, or piped to
@@ -50,18 +49,17 @@ or when referenced by `import` statements within ES module code:
5049

5150
* Files ending in `.cjs`.
5251

53-
* Files ending in `.js`, or extensionless files when run as main entry points on
54-
the command line, when the nearest parent `package.json` file contains a
52+
* Files ending in `.js` when the nearest parent `package.json` file contains a
5553
top-level field `"type"` with a value of `"commonjs"`.
5654

5755
* Strings passed in as an argument to `--eval` or `--print`, or piped to
5856
`node` via `STDIN`, with the flag `--input-type=commonjs`.
5957

6058
### `package.json` `"type"` field
6159

62-
Files ending with `.js` or lacking any extension will be loaded as ES modules
63-
when the nearest parent `package.json` file contains a top-level field `"type"`
64-
with a value of `"module"`.
60+
Files ending with `.js` will be loaded as ES modules when the nearest parent
61+
`package.json` file contains a top-level field `"type"` with a value of
62+
`"module"`.
6563

6664
The nearest parent `package.json` is defined as the first `package.json` found
6765
when searching in the current folder, that folder’s parent, and so on up
@@ -81,14 +79,12 @@ node my-app.js # Runs as ES module
8179
```
8280

8381
If the nearest parent `package.json` lacks a `"type"` field, or contains
84-
`"type": "commonjs"`, extensionless and `.js` files are treated as CommonJS.
85-
If the volume root is reached and no `package.json` is found,
86-
Node.js defers to the default, a `package.json` with no `"type"`
87-
field. "Extensionless" refers to file paths which do not contain
88-
an extension as opposed to optionally dropping a file extension in a specifier.
82+
`"type": "commonjs"`, `.js` files are treated as CommonJS. If the volume root is
83+
reached and no `package.json` is found, Node.js defers to the default, a
84+
`package.json` with no `"type"` field.
8985

90-
`import` statements of `.js` and extensionless files are treated as ES modules
91-
if the nearest parent `package.json` contains `"type": "module"`.
86+
`import` statements of `.js` files are treated as ES modules if the nearest
87+
parent `package.json` contains `"type": "module"`.
9288

9389
```js
9490
// my-app.js, part of the same example as above
@@ -106,14 +102,13 @@ as ES modules and `.cjs` files are always treated as CommonJS.
106102

107103
### Package Scope and File Extensions
108104

109-
A folder containing a `package.json` file, and all subfolders below that
110-
folder down until the next folder containing another `package.json`, is
111-
considered a _package scope_. The `"type"` field defines how `.js` and
112-
extensionless files should be treated within a particular `package.json` file’s
113-
package scope. Every package in a project’s `node_modules` folder contains its
114-
own `package.json` file, so each project’s dependencies have their own package
115-
scopes. A `package.json` lacking a `"type"` field is treated as if it contained
116-
`"type": "commonjs"`.
105+
A folder containing a `package.json` file, and all subfolders below that folder
106+
down until the next folder containing another `package.json`, is considered a
107+
_package scope_. The `"type"` field defines how `.js` files should be treated
108+
within a particular `package.json` file’s package scope. Every package in a
109+
project’s `node_modules` folder contains its own `package.json` file, so each
110+
project’s dependencies have their own package scopes. A `package.json` lacking a
111+
`"type"` field is treated as if it contained `"type": "commonjs"`.
117112

118113
The package scope applies not only to initial entry points (`node my-app.js`)
119114
but also to files referenced by `import` statements and `import()` expressions.
@@ -1042,8 +1037,7 @@ a URL should be interpreted. This can be one of the following:
10421037
```js
10431038
/**
10441039
* @param {string} url
1045-
* @param {object} context
1046-
* @param {string} context.parentURL
1040+
* @param {object} context (currently empty)
10471041
* @param {function} defaultGetFormat
10481042
* @returns {object} response
10491043
* @returns {string} response.format
@@ -1367,15 +1361,13 @@ updates.
13671361
In the following algorithms, all subroutine errors are propagated as errors
13681362
of these top-level routines unless stated otherwise.
13691363
1370-
_isMain_ is **true** when resolving the Node.js application entry point.
1371-
13721364
_defaultEnv_ is the conditional environment name priority array,
13731365
`["node", "import"]`.
13741366
13751367
<details>
13761368
<summary>Resolver algorithm specification</summary>
13771369
1378-
**ESM_RESOLVE**(_specifier_, _parentURL_, _isMain_)
1370+
**ESM_RESOLVE**(_specifier_, _parentURL_)
13791371
13801372
> 1. Let _resolvedURL_ be **undefined**.
13811373
> 1. If _specifier_ is a valid URL, then
@@ -1396,7 +1388,7 @@ _defaultEnv_ is the conditional environment name priority array,
13961388
> 1. If the file at _resolvedURL_ does not exist, then
13971389
> 1. Throw a _Module Not Found_ error.
13981390
> 1. Set _resolvedURL_ to the real path of _resolvedURL_.
1399-
> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_, _isMain_).
1391+
> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_).
14001392
> 1. Load _resolvedURL_ as module format, _format_.
14011393
14021394
**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
@@ -1549,7 +1541,7 @@ _defaultEnv_ is the conditional environment name priority array,
15491541
> 1. Return _resolved_.
15501542
> 1. Throw a _Module Not Found_ error.
15511543
1552-
**ESM_FORMAT**(_url_, _isMain_)
1544+
**ESM_FORMAT**(_url_)
15531545
15541546
> 1. Assert: _url_ corresponds to an existing file.
15551547
> 1. Let _pjson_ be the result of **READ_PACKAGE_SCOPE**(_url_).
@@ -1558,12 +1550,10 @@ _defaultEnv_ is the conditional environment name priority array,
15581550
> 1. If _url_ ends in _".cjs"_, then
15591551
> 1. Return _"commonjs"_.
15601552
> 1. If _pjson?.type_ exists and is _"module"_, then
1561-
> 1. If _isMain_ is **true** or _url_ ends in _".js"_, then
1553+
> 1. If _url_ ends in _".js"_, then
15621554
> 1. Return _"module"_.
15631555
> 1. Throw an _Unsupported File Extension_ error.
15641556
> 1. Otherwise,
1565-
> 1. If _isMain_ is **true**, then
1566-
> 1. Return _"commonjs"_.
15671557
> 1. Throw an _Unsupported File Extension_ error.
15681558
15691559
**READ_PACKAGE_SCOPE**(_url_)

β€Žlib/internal/modules/esm/get_format.jsβ€Ž

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ function defaultGetFormat(url, context, defaultGetFormat) {
5454
return { format };
5555
} else if (parsed.protocol === 'file:') {
5656
const ext = extname(parsed.pathname);
57-
let format = extensionFormatMap[ext];
58-
const isMain = context.parentURL === undefined;
59-
if (ext === '.js' || (!format && isMain))
57+
let format;
58+
if (ext === '.js') {
6059
format = getPackageType(parsed.href) === TYPE_MODULE ?
6160
'module' : 'commonjs';
61+
} else {
62+
format = extensionFormatMap[ext];
63+
}
6264
if (!format) {
6365
if (experimentalSpeciferResolution === 'node') {
6466
process.emitWarning(

β€Žlib/internal/modules/esm/loader.jsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class Loader {
9696
}
9797

9898
const getFormatResponse = await this._getFormat(
99-
url, { parentURL }, defaultGetFormat);
99+
url, {}, defaultGetFormat);
100100
if (typeof getFormatResponse !== 'object') {
101101
throw new ERR_INVALID_RETURN_VALUE(
102102
'object', 'loader getFormat', getFormatResponse);

β€Žtest/es-module/test-esm-no-extension.jsβ€Ž

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fixtures = require('../common/fixtures');
5+
const { spawn } = require('child_process');
6+
const assert = require('assert');
7+
8+
// In a "type": "module" package scope, files with unknown extensions or no
9+
// extensions should throw; both when used as a main entry point and also when
10+
// referenced via `import`.
11+
12+
[
13+
'/es-modules/package-type-module/noext-esm',
14+
'/es-modules/package-type-module/imports-noext.mjs',
15+
'/es-modules/package-type-module/extension.unknown',
16+
'/es-modules/package-type-module/imports-unknownext.mjs',
17+
].forEach((fixturePath) => {
18+
const entry = fixtures.path(fixturePath);
19+
const child = spawn(process.execPath, [entry]);
20+
let stdout = '';
21+
let stderr = '';
22+
child.stderr.setEncoding('utf8');
23+
child.stdout.setEncoding('utf8');
24+
child.stdout.on('data', (data) => {
25+
stdout += data;
26+
});
27+
child.stderr.on('data', (data) => {
28+
stderr += data;
29+
});
30+
child.on('close', common.mustCall((code, signal) => {
31+
assert.strictEqual(code, 1);
32+
assert.strictEqual(signal, null);
33+
assert.strictEqual(stdout, '');
34+
assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1);
35+
}));
36+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './noext-esm';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './extension.unknown';

0 commit comments

Comments
Β (0)