Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v18.x] Backport most ESM and customization hook changes #50669

Closed
wants to merge 75 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
5a0ae4d
esm: move hook execution to separate thread
JakobJingleheimer Nov 10, 2023
7c878ef
esm: avoid try/catch when validating urls
anonrig Apr 15, 2023
4990269
esm: propagate `process.exit` from the loader thread to the main thread
aduh95 Apr 19, 2023
40fa6e4
esm: initialize `import.meta` on eval
aduh95 Apr 19, 2023
d8687c4
esm: remove support for deprecated hooks
aduh95 Apr 19, 2023
ee9cef2
loader: use default loader as cascaded loader in the in loader worker
joyeecheung Apr 21, 2023
d63f4c4
esm: rename `URLCanParse` to be consistent
aduh95 Apr 22, 2023
a31ca4e
esm: do not use `'beforeExit'` on the main thread
aduh95 May 14, 2023
2bb6dfb
esm: handle more error types thrown from the loader thread
aduh95 Jun 1, 2023
09c986e
esm: handle `globalPreload` hook returning a nullish value
aduh95 May 30, 2023
96edd85
esm: remove support for arrays in `import` internal method
aduh95 Jun 5, 2023
a0c10aa
typings: fix JSDoc in ESM loader modules
aduh95 Jun 11, 2023
1964e25
module: implement `register` utility
jlenon7 Jun 12, 2023
002a084
esm: add back `globalPreload` tests and fix failing ones
aduh95 Jul 17, 2023
afa2562
esm: unflag `Module.register` and allow nested loader `import()`
izaakschroeder Jul 19, 2023
5de6683
module: ensure successful import returns the same result
aduh95 Jul 26, 2023
0a9e81e
test: fix `es-module/test-esm-initialization`
aduh95 Jul 29, 2023
4ffa98f
fs: make `mkdtemp` accept buffers and URL
LiviaMedeiros Jul 18, 2023
17ba928
test: fix some assumptions in tests
aduh95 Jul 31, 2023
9d44275
test: order `common.mjs` in ASCII order
aduh95 Jul 31, 2023
ce1d396
test: fix snapshot tests when cwd contains spaces or backslashes
aduh95 Jul 31, 2023
f5661b0
esm: fix typo `parentUrl` -> `parentURL`
aduh95 Aug 2, 2023
c34870e
esm: add `initialize` hook, integrate with `register`
izaakschroeder Aug 3, 2023
3d58e49
test: use `fixtures.fileURL` when appropriate
aduh95 Aug 3, 2023
61aa405
esm: protect `ERR_UNSUPPORTED_DIR_IMPORT` against prototype pollution
aduh95 Aug 11, 2023
0bfcddc
test: reduce flakiness of `test-esm-loader-hooks`
aduh95 Aug 12, 2023
a256f11
esm: import.meta.resolve exact module not found errors should return
guybedford Aug 13, 2023
73809e2
esm: unflag import.meta.resolve
guybedford Aug 13, 2023
8ec3953
esm: fix `globalPreload` warning
aduh95 Aug 13, 2023
586bb8f
doc: fix name of the flag in `initialize()` docs
aduh95 Aug 14, 2023
1c020cc
test: refactor `test-esm-loader-hooks` for easier debugging
aduh95 Aug 15, 2023
222a378
doc: caveat unavailability of `import.meta.resolve` in custom loaders
JakobJingleheimer Aug 19, 2023
cf02160
test: reduce flakiness of `test-esm-loader-hooks`
aduh95 Aug 20, 2023
0b72534
doc: add signature for `module.register`
GeoffreyBooth Aug 20, 2023
3c9111e
esm: refactor mocking test
GeoffreyBooth Sep 5, 2023
f86933b
doc: move and rename loaders section
GeoffreyBooth Aug 22, 2023
dcf909c
doc: update module hooks docs
GeoffreyBooth Aug 24, 2023
16580a4
doc: edit `import.meta.resolve` documentation
aduh95 Sep 5, 2023
abedad7
test: add `tmpdir.fileURL()`
LiviaMedeiros Aug 10, 2023
d785f83
esm: refactor test-esm-named-exports
GeoffreyBooth Sep 4, 2023
9a7a8c5
esm: refactor test-esm-loader-resolve-type
GeoffreyBooth Sep 4, 2023
fbc7c3e
esm: remove return value for `Module.register`
aduh95 Sep 9, 2023
71c4ae3
typings: fix missing property in `ExportedHooks`
aduh95 Sep 9, 2023
a23a4c9
test: isolate `globalPreload` tests
GeoffreyBooth Sep 9, 2023
89dce06
test: increase coverage of `Module.register` and `initialize` hook
aduh95 Sep 10, 2023
40ffd28
esm: clarify ERR_REQUIRE_ESM errors
danielcompton Sep 15, 2023
1a2443a
esm: fix support for `URL` instances in `register`
aduh95 Sep 17, 2023
a29ddb3
esm: update loaders warning
GeoffreyBooth Sep 19, 2023
44b345c
esm: fix return type of `import.meta.resolve`
aduh95 Sep 20, 2023
aadc39f
doc: add missing history info for `import.meta.resolve`
aduh95 Sep 20, 2023
efd4e8c
esm: identify parent importing a url with invalid host
JakobJingleheimer Sep 23, 2023
f85e62f
esm: fix cache collision on JSON files using file: URL
aduh95 Sep 29, 2023
a600822
lib: merge cjs and esm package json reader caches
anonrig Jun 29, 2023
c262d3b
esm: require braces for modules code
GeoffreyBooth Sep 15, 2023
bd4eda0
module, esm: jsdoc for modules files
GeoffreyBooth Sep 19, 2023
7c5b7f3
module: move helpers out of cjs loader
GeoffreyBooth Sep 30, 2023
2f26771
esm: improve JSDoc annotation of internal functions
aduh95 Oct 1, 2023
ce76ac2
esm: --experimental-default-type flag to flip module defaults
GeoffreyBooth Sep 29, 2023
823adc8
esm: unflag extensionless javascript and wasm in module scope
GeoffreyBooth Sep 30, 2023
08201aa
util: add `getCwdSafe` internal util fn
jlenon7 Sep 22, 2023
151e812
esm: bypass CommonJS loader under --default-type
GeoffreyBooth Oct 5, 2023
9ed022b
tools: update eslint to 8.45.0
nodejs-github-bot Jul 18, 2023
5c4057a
tools: update eslint to 8.46.0
nodejs-github-bot Aug 1, 2023
9509884
tools: update eslint to 8.47.0
nodejs-github-bot Aug 15, 2023
2208832
tools: update eslint to 8.48.0
nodejs-github-bot Aug 29, 2023
96dea39
tools: update eslint to 8.49.0
nodejs-github-bot Sep 12, 2023
669e3d7
tools: update eslint to 8.50.0
nodejs-github-bot Oct 3, 2023
83f680f
tools: update eslint to 8.51.0
nodejs-github-bot Oct 8, 2023
5699370
esm: use import attributes instead of import assertions
aduh95 Oct 14, 2023
52901a7
test: deflake `test-esm-loader-resolve-type`
aduh95 Oct 21, 2023
bd6512e
test: deflake `test-loaders-workers-spawned`
aduh95 Oct 18, 2023
b0829b7
vm: use import attributes instead of import assertions
aduh95 Oct 23, 2023
8f9645d
test: refactor `test-node-output-errors`
aduh95 Aug 3, 2023
85b21a8
test: fix edge snapshot stack traces
GeoffreyBooth Sep 17, 2023
3bf8c02
tools: skip ruff on tools/node_modules
MoLow Sep 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ tools/lint-md/lint-md.mjs
benchmark/tmp
benchmark/fixtures
doc/**/*.js
doc/changelogs/CHANGELOG_v1*.md
!doc/changelogs/CHANGELOG_v18.md
!doc/api_assets/*.js
!.eslintrc.js
19 changes: 15 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const hacks = [
'eslint-plugin-jsdoc',
'eslint-plugin-markdown',
'@babel/eslint-parser',
'@babel/plugin-syntax-import-assertions',
'@babel/plugin-syntax-import-attributes',
];
Module._findPath = (request, paths, isMain) => {
const r = ModuleFindPath(request, paths, isMain);
Expand All @@ -44,7 +44,10 @@ module.exports = {
parserOptions: {
babelOptions: {
plugins: [
Module._findPath('@babel/plugin-syntax-import-assertions'),
[
Module._findPath('@babel/plugin-syntax-import-attributes'),
{ deprecatedAssertSyntax: true },
],
],
},
requireConfigFile: false,
Expand All @@ -53,10 +56,10 @@ module.exports = {
overrides: [
{
files: [
'test/es-module/test-esm-type-flag.js',
'test/es-module/test-esm-type-flag-alias.js',
'*.mjs',
'test/es-module/test-esm-example-loader.js',
'test/es-module/test-esm-type-flag.js',
'test/es-module/test-esm-type-flag-alias.js',
],
parserOptions: { sourceType: 'module' },
},
Expand Down Expand Up @@ -111,6 +114,14 @@ module.exports = {
},
] },
},
{
files: [
'lib/internal/modules/**/*.js',
],
rules: {
'curly': 'error',
},
},
],
rules: {
// ESLint built-in rules
Expand Down
45 changes: 45 additions & 0 deletions benchmark/esm/esm-loader-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Tests the impact on eager operations required for policies affecting
// general startup, does not test lazy operations
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const common = require('../common.js');

const tmpdir = require('../../test/common/tmpdir.js');
const { pathToFileURL } = require('node:url');

const benchmarkDirectory = pathToFileURL(path.resolve(tmpdir.path, 'benchmark-import'));

const configs = {
n: [1e3],
specifier: [
'data:text/javascript,{i}',
'./relative-existing.js',
'./relative-nonexistent.js',
'node:prefixed-nonexistent',
'node:os',
],
};

const options = {
flags: ['--expose-internals'],
};

const bench = common.createBenchmark(main, configs, options);

async function main(conf) {
tmpdir.refresh();

fs.mkdirSync(benchmarkDirectory, { recursive: true });
fs.writeFileSync(new URL('./relative-existing.js', benchmarkDirectory), '\n');

bench.start();

for (let i = 0; i < conf.n; i++) {
try {
await import(new URL(conf.specifier.replace('{i}', i), benchmarkDirectory));
} catch { /* empty */ }
}

bench.end(conf.n);
}
73 changes: 61 additions & 12 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@

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. If no
corresponding file is found, an error is thrown.
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.

If a file is found, its path will be passed to the [ECMAScript module loader][]
under any of the following conditions:
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.
point to be loaded with ECMAScript module loader, such as `--import` or
[`--experimental-default-type=module`][].
* 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
Expand All @@ -43,10 +45,11 @@

### ECMAScript modules loader entry point caveat

When loading [ECMAScript module loader][] loads the program entry point, the `node`
command will only accept as input only files with `.js`, `.mjs`, or `.cjs`
extensions; and with `.wasm` extensions when
[`--experimental-wasm-modules`][] is enabled.
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.

## Options

Expand Down Expand Up @@ -366,15 +369,54 @@

Expose the [Web Crypto API][] on the global scope.

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

<!-- YAML
added:
- REPLACEME
-->

> 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-import-meta-resolve`

<!-- YAML
added:
- v13.9.0
- v12.16.2
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/49028

Check warning on line 410 in doc/api/cli.md

View workflow job for this annotation

GitHub Actions / lint-pr-url

pr-url doesn't match the URL of the current PR.
description: synchronous import.meta.resolve made available by default, with
the flag retained for enabling the experimental second argument
as previously supported.
-->

Enable experimental `import.meta.resolve()` support.
Enable experimental `import.meta.resolve()` parent URL support, which allows
passing a second `parentURL` argument for contextual resolution.

Previously gated the entire `import.meta.resolve` feature.

### `--experimental-loader=module`

Expand All @@ -387,7 +429,11 @@
`--experimental-loader`.
-->

Specify the `module` of a custom experimental [ECMAScript module loader][].
> This flag is discouraged and may be removed in a future version of Node.js.
> Please use
> [`--import` with `register()`][module customization hooks: enabling] instead.

Specify the `module` containing exported [module customization hooks][].
`module` may be any string accepted as an [`import` specifier][].

### `--experimental-network-imports`
Expand Down Expand Up @@ -1910,6 +1956,7 @@
* `--enable-network-family-autoselection`
* `--enable-source-maps`
* `--experimental-abortcontroller`
* `--experimental-default-type`
* `--experimental-global-customevent`
* `--experimental-global-webcrypto`
* `--experimental-import-meta-resolve`
Expand Down Expand Up @@ -2357,8 +2404,9 @@
[CommonJS module]: modules.md
[CustomEvent Web API]: https://dom.spec.whatwg.org/#customevent
[ECMAScript module]: esm.md#modules-ecmascript-modules
[ECMAScript module loader]: esm.md#loaders
[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[Module customization hooks]: module.md#customization-hooks
[Module customization hooks: enabling]: module.md#enabling
[Modules loaders]: packages.md#modules-loaders
[Node.js issue tracker]: https://github.com/nodejs/node/issues
[OSSL_PROVIDER-legacy]: https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
Expand All @@ -2372,6 +2420,7 @@
[`"type"`]: packages.md#type
[`--cpu-prof-dir`]: #--cpu-prof-dir
[`--diagnostic-dir`]: #--diagnostic-dirdirectory
[`--experimental-default-type=module`]: #--experimental-default-typetype
[`--experimental-wasm-modules`]: #--experimental-wasm-modules
[`--heap-prof-dir`]: #--heap-prof-dir
[`--import`]: #--importmodule
Expand Down
17 changes: 14 additions & 3 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1762,7 +1762,8 @@ added:
- v16.14.0
-->

An import assertion has failed, preventing the specified module to be imported.
An import `type` attribute was provided, but the specified module is of a
different type.

<a id="ERR_IMPORT_ASSERTION_TYPE_MISSING"></a>

Expand All @@ -1774,7 +1775,7 @@ added:
- v16.14.0
-->

An import assertion is missing, preventing the specified module to be imported.
An import attribute is missing, preventing the specified module to be imported.

<a id="ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED"></a>

Expand All @@ -1786,7 +1787,17 @@ added:
- v16.14.0
-->

An import assertion is not supported by this version of Node.js.
An import attribute is not supported by this version of Node.js.

<a id="ERR_IMPORT_ATTRIBUTE_UNSUPPORTED"></a>

### `ERR_IMPORT_ATTRIBUTE_UNSUPPORTED`

<!-- YAML
added: REPLACEME
-->

An import attribute is not supported by this version of Node.js.

<a id="ERR_INCOMPATIBLE_OPTION_PAIR"></a>

Expand Down
Loading