Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f594cc8

Browse filesBrowse files
esm: remove specifier resolution flag
PR-URL: #44859 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
1 parent 417458d commit f594cc8
Copy full SHA for f594cc8

File tree

Expand file treeCollapse file tree

26 files changed

+24
-374
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

26 files changed

+24
-374
lines changed
Open diff view settings
Collapse file

‎doc/api/cli.md‎

Copy file name to clipboardExpand all lines: doc/api/cli.md
-18Lines changed: 0 additions & 18 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -427,23 +427,6 @@ added: REPLACEME
427427

428428
Use this flag to enable [ShadowRealm][] support.
429429

430-
### `--experimental-specifier-resolution=mode`
431-
432-
<!-- YAML
433-
added:
434-
- v13.4.0
435-
- v12.16.0
436-
-->
437-
438-
Sets the resolution algorithm for resolving ES module specifiers. Valid options
439-
are `explicit` and `node`.
440-
441-
The default is `explicit`, which requires providing the full path to a
442-
module. The `node` mode enables support for optional file extensions and
443-
the ability to import a directory that has an index file.
444-
445-
See [customizing ESM specifier resolution][] for example usage.
446-
447430
### `--experimental-vm-modules`
448431

449432
<!-- YAML
@@ -2312,7 +2295,6 @@ done
23122295
[`worker_threads.threadId`]: worker_threads.md#workerthreadid
23132296
[conditional exports]: packages.md#conditional-exports
23142297
[context-aware]: addons.md#context-aware-addons
2315-
[customizing ESM specifier resolution]: esm.md#customizing-esm-specifier-resolution-algorithm
23162298
[debugger]: debugger.md
23172299
[debugging security implications]: https://nodejs.org/en/docs/guides/debugging-getting-started/#security-implications
23182300
[emit_warning]: process.md#processemitwarningwarning-options
Collapse file

‎doc/api/esm.md‎

Copy file name to clipboardExpand all lines: doc/api/esm.md
+4-25Lines changed: 4 additions & 25 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1518,31 +1518,9 @@ _isImports_, _conditions_)
15181518
15191519
### Customizing ESM specifier resolution algorithm
15201520
1521-
> Stability: 1 - Experimental
1522-
1523-
> Do not rely on this flag. We plan to remove it once the
1524-
> [Loaders API][] has advanced to the point that equivalent functionality can
1525-
> be achieved via custom loaders.
1526-
1527-
The current specifier resolution does not support all default behavior of
1528-
the CommonJS loader. One of the behavior differences is automatic resolution
1529-
of file extensions and the ability to import directories that have an index
1530-
file.
1531-
1532-
The `--experimental-specifier-resolution=[mode]` flag can be used to customize
1533-
the extension resolution algorithm. The default mode is `explicit`, which
1534-
requires the full path to a module be provided to the loader. To enable the
1535-
automatic extension resolution and importing from directories that include an
1536-
index file use the `node` mode.
1537-
1538-
```console
1539-
$ node index.mjs
1540-
success!
1541-
$ node index # Failure!
1542-
Error: Cannot find module
1543-
$ node --experimental-specifier-resolution=node index
1544-
success!
1545-
```
1521+
The [Loaders API][] provides a mechanism for customizing the ESM specifier
1522+
resolution algorithm. An example loader that provides CommonJS-style resolution
1523+
for ESM specifiers is [commonjs-extension-resolution-loader][].
15461524
15471525
<!-- Note: The cjs-module-lexer link should be kept in-sync with the deps version -->
15481526
@@ -1583,6 +1561,7 @@ success!
15831561
[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
15841562
[`util.TextDecoder`]: util.md#class-utiltextdecoder
15851563
[cjs-module-lexer]: https://github.com/nodejs/cjs-module-lexer/tree/1.2.2
1564+
[commonjs-extension-resolution-loader]: https://github.com/nodejs/loaders-test/tree/main/commonjs-extension-resolution-loader
15861565
[custom https loader]: #https-loader
15871566
[load hook]: #loadurl-context-nextload
15881567
[percent-encoded]: url.md#percent-encoding-in-urls
Collapse file

‎doc/node.1‎

Copy file name to clipboardExpand all lines: doc/node.1
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ Disable exposition of the Web Crypto API on the global scope.
171171
.It Fl -no-experimental-repl-await
172172
Disable top-level await keyword support in REPL.
173173
.
174-
.It Fl -experimental-specifier-resolution
175-
Select extension resolution algorithm for ES Modules; either 'explicit' (default) or 'node'.
176-
.
177174
.It Fl -experimental-vm-modules
178175
Enable experimental ES module support in VM module.
179176
.
Collapse file

‎lib/internal/modules/esm/formats.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/formats.js
+1-17Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const {
55
} = primordials;
66
const { getOptionValue } = require('internal/options');
77

8-
98
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
109

1110
const extensionFormatMap = {
@@ -16,17 +15,8 @@ const extensionFormatMap = {
1615
'.mjs': 'module',
1716
};
1817

19-
const legacyExtensionFormatMap = {
20-
'__proto__': null,
21-
'.cjs': 'commonjs',
22-
'.js': 'commonjs',
23-
'.json': 'commonjs',
24-
'.mjs': 'module',
25-
'.node': 'commonjs',
26-
};
27-
2818
if (experimentalWasmModules) {
29-
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
19+
extensionFormatMap['.wasm'] = 'wasm';
3020
}
3121

3222
/**
@@ -45,13 +35,7 @@ function mimeToFormat(mime) {
4535
return null;
4636
}
4737

48-
function getLegacyExtensionFormat(ext) {
49-
return legacyExtensionFormatMap[ext];
50-
}
51-
5238
module.exports = {
5339
extensionFormatMap,
54-
getLegacyExtensionFormat,
55-
legacyExtensionFormatMap,
5640
mimeToFormat,
5741
};
Collapse file

‎lib/internal/modules/esm/get_format.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/get_format.js
+14-21Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@ const { getOptionValue } = require('internal/options');
1111
const { fetchModule } = require('internal/modules/esm/fetch_module');
1212
const {
1313
extensionFormatMap,
14-
getLegacyExtensionFormat,
1514
mimeToFormat,
1615
} = require('internal/modules/esm/formats');
1716

1817
const experimentalNetworkImports =
1918
getOptionValue('--experimental-network-imports');
20-
const experimentalSpecifierResolution =
21-
getOptionValue('--experimental-specifier-resolution');
2219
const { getPackageType, getPackageScopeConfig } = require('internal/modules/esm/resolve');
2320
const { URL, fileURLToPath } = require('internal/url');
2421
const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
@@ -61,25 +58,21 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) {
6158
const format = extensionFormatMap[ext];
6259
if (format) return format;
6360

64-
if (experimentalSpecifierResolution !== 'node') {
65-
// Explicit undefined return indicates load hook should rerun format check
66-
if (ignoreErrors) return undefined;
67-
let suggestion = '';
68-
if (getPackageType(url) === 'module' && ext === '') {
69-
const config = getPackageScopeConfig(url);
70-
const fileBasename = basename(filepath);
71-
const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1);
72-
suggestion = 'Loading extensionless files is not supported inside of ' +
73-
'"type":"module" package.json contexts. The package.json file ' +
74-
`${config.pjsonPath} caused this "type":"module" context. Try ` +
75-
`changing ${filepath} to have a file extension. Note the "bin" ` +
76-
'field of package.json can point to a file with an extension, for example ' +
77-
`{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`;
78-
}
79-
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion);
61+
// Explicit undefined return indicates load hook should rerun format check
62+
if (ignoreErrors) { return undefined; }
63+
let suggestion = '';
64+
if (getPackageType(url) === 'module' && ext === '') {
65+
const config = getPackageScopeConfig(url);
66+
const fileBasename = basename(filepath);
67+
const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1);
68+
suggestion = 'Loading extensionless files is not supported inside of ' +
69+
'"type":"module" package.json contexts. The package.json file ' +
70+
`${config.pjsonPath} caused this "type":"module" context. Try ` +
71+
`changing ${filepath} to have a file extension. Note the "bin" ` +
72+
'field of package.json can point to a file with an extension, for example ' +
73+
`{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`;
8074
}
81-
82-
return getLegacyExtensionFormat(ext) ?? null;
75+
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion);
8376
}
8477

8578
/**
Collapse file

‎lib/internal/modules/esm/loader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js
-12Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ const { getOptionValue } = require('internal/options');
8989

9090
// [2] `validate...()`s throw the wrong error
9191

92-
let emittedSpecifierResolutionWarning = false;
93-
9492
/**
9593
* A utility function to iterate through a hook chain, track advancement in the
9694
* chain, and generate and supply the `next<HookName>` argument to the custom
@@ -241,16 +239,6 @@ class ESMLoader {
241239
if (getOptionValue('--experimental-network-imports')) {
242240
emitExperimentalWarning('Network Imports');
243241
}
244-
if (
245-
!emittedSpecifierResolutionWarning &&
246-
getOptionValue('--experimental-specifier-resolution') === 'node'
247-
) {
248-
process.emitWarning(
249-
'The Node.js specifier resolution flag is experimental. It could change or be removed at any time.',
250-
'ExperimentalWarning'
251-
);
252-
emittedSpecifierResolutionWarning = true;
253-
}
254242
}
255243

256244
/**
Collapse file

‎lib/internal/modules/esm/resolve.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js
+2-66Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const {
55
ArrayPrototypeConcat,
66
ArrayPrototypeJoin,
77
ArrayPrototypeShift,
8-
JSONParse,
98
JSONStringify,
109
ObjectFreeze,
1110
ObjectGetOwnPropertyNames,
@@ -37,7 +36,7 @@ const { getOptionValue } = require('internal/options');
3736
const policy = getOptionValue('--experimental-policy') ?
3837
require('internal/process/policy') :
3938
null;
40-
const { sep, relative, resolve } = require('path');
39+
const { sep, relative } = require('path');
4140
const preserveSymlinks = getOptionValue('--preserve-symlinks');
4241
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
4342
const experimentalNetworkImports =
@@ -60,7 +59,6 @@ const {
6059
} = require('internal/errors').codes;
6160

6261
const { Module: CJSModule } = require('internal/modules/cjs/loader');
63-
const packageJsonReader = require('internal/modules/package_json_reader');
6462
const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config');
6563

6664
/**
@@ -234,50 +232,6 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
234232
fileURLToPath(new URL('.', packageJSONUrl)), fileURLToPath(base));
235233
}
236234

237-
/**
238-
* @param {URL} search
239-
* @returns {URL | undefined}
240-
*/
241-
function resolveExtensionsWithTryExactName(search) {
242-
if (fileExists(search)) return search;
243-
return resolveExtensions(search);
244-
}
245-
246-
const extensions = ['.js', '.json', '.node', '.mjs'];
247-
248-
/**
249-
* @param {URL} search
250-
* @returns {URL | undefined}
251-
*/
252-
function resolveExtensions(search) {
253-
for (let i = 0; i < extensions.length; i++) {
254-
const extension = extensions[i];
255-
const guess = new URL(`${search.pathname}${extension}`, search);
256-
if (fileExists(guess)) return guess;
257-
}
258-
return undefined;
259-
}
260-
261-
/**
262-
* @param {URL} search
263-
* @returns {URL | undefined}
264-
*/
265-
function resolveDirectoryEntry(search) {
266-
const dirPath = fileURLToPath(search);
267-
const pkgJsonPath = resolve(dirPath, 'package.json');
268-
if (fileExists(pkgJsonPath)) {
269-
const pkgJson = packageJsonReader.read(pkgJsonPath);
270-
if (pkgJson.containsKeys) {
271-
const { main } = JSONParse(pkgJson.string);
272-
if (main != null) {
273-
const mainUrl = pathToFileURL(resolve(dirPath, main));
274-
return resolveExtensionsWithTryExactName(mainUrl);
275-
}
276-
}
277-
}
278-
return resolveExtensions(new URL('index', search));
279-
}
280-
281235
const encodedSepRegEx = /%2F|%5C/i;
282236
/**
283237
* @param {URL} resolved
@@ -291,25 +245,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
291245
resolved.pathname, 'must not include encoded "/" or "\\" characters',
292246
fileURLToPath(base));
293247

294-
let path = fileURLToPath(resolved);
295-
if (getOptionValue('--experimental-specifier-resolution') === 'node') {
296-
let file = resolveExtensionsWithTryExactName(resolved);
297-
298-
// Directory
299-
if (file === undefined) {
300-
file = StringPrototypeEndsWith(path, '/') ?
301-
(resolveDirectoryEntry(resolved) || resolved) : resolveDirectoryEntry(new URL(`${resolved}/`));
302-
303-
if (file === resolved) return file;
304-
305-
if (file === undefined) {
306-
throw new ERR_MODULE_NOT_FOUND(
307-
resolved.pathname, fileURLToPath(base), 'module');
308-
}
309-
}
310-
311-
path = file;
312-
}
248+
const path = fileURLToPath(resolved);
313249

314250
const stats = tryStatSync(StringPrototypeEndsWith(path, '/') ?
315251
StringPrototypeSlice(path, -1) : path);
Collapse file

‎lib/internal/modules/run_main.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/run_main.js
-4Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ function shouldUseESMLoader(mainPath) {
4040
const userImports = getOptionValue('--import');
4141
if (userLoaders.length > 0 || userImports.length > 0)
4242
return true;
43-
const esModuleSpecifierResolution =
44-
getOptionValue('--experimental-specifier-resolution');
45-
if (esModuleSpecifierResolution === 'node')
46-
return true;
4743
// Determine the module format of the main
4844
if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs'))
4945
return true;
Collapse file

‎lib/repl.js‎

Copy file name to clipboardExpand all lines: lib/repl.js
+1-5Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ const {
180180
const history = require('internal/repl/history');
181181
const {
182182
extensionFormatMap,
183-
legacyExtensionFormatMap,
184183
} = require('internal/modules/esm/formats');
185184

186185
let nextREPLResourceNumber = 1;
@@ -1377,10 +1376,7 @@ function complete(line, callback) {
13771376
if (this.allowBlockingCompletions) {
13781377
const subdir = match[2] || '';
13791378
// File extensions that can be imported:
1380-
const extensions = ObjectKeys(
1381-
getOptionValue('--experimental-specifier-resolution') === 'node' ?
1382-
legacyExtensionFormatMap :
1383-
extensionFormatMap);
1379+
const extensions = ObjectKeys(extensionFormatMap);
13841380

13851381
// Only used when loading bare module specifiers from `node_modules`:
13861382
const indexes = ArrayPrototypeMap(extensions, (ext) => `index${ext}`);
Collapse file

‎src/node_options.cc‎

Copy file name to clipboardExpand all lines: src/node_options.cc
+2-13Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,6 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors) {
113113
}
114114
}
115115

116-
if (!experimental_specifier_resolution.empty()) {
117-
if (experimental_specifier_resolution != "node" &&
118-
experimental_specifier_resolution != "explicit") {
119-
errors->push_back(
120-
"invalid value for --experimental-specifier-resolution");
121-
}
122-
}
123-
124116
if (syntax_check_only && has_eval_string) {
125117
errors->push_back("either --check or --eval can be used, not both");
126118
}
@@ -444,11 +436,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
444436
"set module type for string input",
445437
&EnvironmentOptions::module_type,
446438
kAllowedInEnvironment);
447-
AddOption("--experimental-specifier-resolution",
448-
"Select extension resolution algorithm for es modules; "
449-
"either 'explicit' (default) or 'node'",
450-
&EnvironmentOptions::experimental_specifier_resolution,
451-
kAllowedInEnvironment);
439+
AddOption(
440+
"--experimental-specifier-resolution", "", NoOp{}, kAllowedInEnvironment);
452441
AddAlias("--es-module-specifier-resolution",
453442
"--experimental-specifier-resolution");
454443
AddOption("--deprecation",

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.