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] esm: use import attributes instead of import assertions #50329

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
36 changes: 24 additions & 12 deletions doc/api/esm.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ changes:
- v17.1.0
- v16.14.0
pr-url: https://github.com/nodejs/node/pull/40250
description: Add support for import assertions.
description: Add experimental support for import assertions.
- version:
- v17.0.0
- v16.12.0
Expand Down Expand Up @@ -230,17 +230,24 @@ absolute URL strings.
import fs from 'node:fs/promises';
```

## Import assertions
<a id="import-assertions"></a>

## Import attributes

<!-- YAML
added:
- v17.1.0
- v16.14.0
-->

> Stability: 1 - Experimental
> Stability: 1.1 - Active development

> This feature was previously named "Import assertions", and using the `assert`
> keyword instead of `with`. Because the version of V8 on this release line does
> not support the `with` keyword, you need to keep using `assert` to support
> this version of Node.js.

The [Import Assertions proposal][] adds an inline syntax for module import
The [Import Attributes proposal][] adds an inline syntax for module import
statements to pass on more information alongside the module specifier.

```js
Expand All @@ -250,10 +257,10 @@ const { default: barData } =
await import('./bar.json', { assert: { type: 'json' } });
```

Node.js supports the following `type` values, for which the assertion is
Node.js supports the following `type` values, for which the attribute is
mandatory:

| Assertion `type` | Needed for |
| Attribute `type` | Needed for |
| ---------------- | ---------------- |
| `'json'` | [JSON modules][] |

Expand Down Expand Up @@ -529,7 +536,7 @@ JSON files can be referenced by `import`:
import packageConfig from './package.json' assert { type: 'json' };
```

The `assert { type: 'json' }` syntax is mandatory; see [Import Assertions][].
The `assert { type: 'json' }` syntax is mandatory; see [Import Attributes][].

The imported JSON only exposes a `default` export. There is no support for named
exports. A cache entry is created in the CommonJS cache to avoid duplication.
Expand Down Expand Up @@ -732,6 +739,11 @@ prevent unintentional breaks in the chain.

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/50140
description: The property `context.importAssertions` is replaced with
`context.importAttributes`. Using the old name is still
supported and will emit an experimental warning.
- version: v18.6.0
pr-url: https://github.com/nodejs/node/pull/42623
description: Add support for chaining resolve hooks. Each hook must either
Expand All @@ -750,7 +762,7 @@ changes:
* `specifier` {string}
* `context` {Object}
* `conditions` {string\[]} Export conditions of the relevant `package.json`
* `importAssertions` {Object}
* `importAttributes` {Object}
* `parentURL` {string|undefined} The module importing this one, or undefined
if this is the Node.js entry point
* `nextResolve` {Function} The subsequent `resolve` hook in the chain, or the
Expand Down Expand Up @@ -842,7 +854,7 @@ changes:
* `conditions` {string\[]} Export conditions of the relevant `package.json`
* `format` {string|null|undefined} The format optionally supplied by the
`resolve` hook chain
* `importAssertions` {Object}
* `importAttributes` {Object}
* `nextLoad` {Function} The subsequent `load` hook in the chain, or the
Node.js default `load` hook after the last user-supplied `load` hook
* `specifier` {string}
Expand All @@ -855,7 +867,7 @@ changes:

The `load` hook provides a way to define a custom method of determining how
a URL should be interpreted, retrieved, and parsed. It is also in charge of
validating the import assertion.
validating the import attributes.

The final value of `format` must be one of the following:

Expand Down Expand Up @@ -1578,8 +1590,8 @@ success!
[Dynamic `import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
[ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
[HTTPS and HTTP imports]: #https-and-http-imports
[Import Assertions]: #import-assertions
[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
[Import Attributes]: #import-attributes
[Import Attributes proposal]: https://github.com/tc39/proposal-import-attributes
[JSON modules]: #json-modules
[Loaders API]: #loaders
[Node.js Module Resolution And Loading Algorithm]: #resolution-algorithm-specification
Expand Down
45 changes: 26 additions & 19 deletions doc/api/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
- version: v10.6.0
pr-url: https://github.com/nodejs/node/pull/20300
Expand Down Expand Up @@ -101,7 +101,7 @@ changes:
using it in a production environment.
* `specifier` {string} specifier passed to `import()`
* `script` {vm.Script}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -613,6 +613,14 @@ The identifier of the current module, as set in the constructor.

### `module.link(linker)`

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/50141
description: The option `extra.assert` is renamed to `extra.attributes`. The
former name is still provided for backward compatibility.
-->

* `linker` {Function}
* `specifier` {string} The specifier of the requested module:
```mjs
Expand All @@ -623,15 +631,14 @@ The identifier of the current module, as set in the constructor.
* `referencingModule` {vm.Module} The `Module` object `link()` is called on.

* `extra` {Object}
* `assert` {Object} The data from the assertion:
<!-- eslint-skip -->
```js
* `attributes` {Object} The data from the attribute:
```mjs
import foo from 'foo' assert { name: 'value' };
// ^^^^^^^^^^^^^^^^^ the assertion
// ^^^^^^^^^^^^^^^^^ the attribute
```
Per ECMA-262, hosts are expected to ignore assertions that they do not
support, as opposed to, for example, triggering an error if an
unsupported assertion is present.
Per ECMA-262, hosts are expected to trigger an error if an
unsupported attribute is present.
* `assert` {Object} Alias for `extra.attributes`.

* Returns: {vm.Module|Promise}
* Returns: {Promise}
Expand Down Expand Up @@ -730,7 +737,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
-->

Expand Down Expand Up @@ -760,7 +767,7 @@ changes:
`import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][].
* `specifier` {string} specifier passed to `import()`
* `module` {vm.Module}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -974,7 +981,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
- version: v15.9.0
pr-url: https://github.com/nodejs/node/pull/35431
Expand Down Expand Up @@ -1018,7 +1025,7 @@ changes:
considered stable.
* `specifier` {string} specifier passed to `import()`
* `function` {Function}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -1204,7 +1211,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
- version: v6.3.0
pr-url: https://github.com/nodejs/node/pull/6635
Expand Down Expand Up @@ -1242,7 +1249,7 @@ changes:
using it in a production environment.
* `specifier` {string} specifier passed to `import()`
* `script` {vm.Script}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -1282,7 +1289,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
- version: v14.6.0
pr-url: https://github.com/nodejs/node/pull/34023
Expand Down Expand Up @@ -1341,7 +1348,7 @@ changes:
using it in a production environment.
* `specifier` {string} specifier passed to `import()`
* `script` {vm.Script}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down Expand Up @@ -1385,7 +1392,7 @@ changes:
- v17.0.0
- v16.12.0
pr-url: https://github.com/nodejs/node/pull/40249
description: Added support for import assertions to the
description: Added support for import attributes to the
`importModuleDynamically` parameter.
- version: v6.3.0
pr-url: https://github.com/nodejs/node/pull/6635
Expand Down Expand Up @@ -1421,7 +1428,7 @@ changes:
using it in a production environment.
* `specifier` {string} specifier passed to `import()`
* `script` {vm.Script}
* `importAssertions` {Object} The `"assert"` value passed to the
* `importAttributes` {Object} The `"assert"` value passed to the
[`optionsExpression`][] optional parameter, or an empty object if no value
was provided.
* Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is
Expand Down
9 changes: 7 additions & 2 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1177,12 +1177,17 @@ E('ERR_HTTP_SOCKET_ENCODING',
E('ERR_HTTP_TRAILER_INVALID',
'Trailers are invalid with this transfer encoding', Error);
E('ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor', TypeError);
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
E('ERR_IMPORT_ASSERTION_TYPE_FAILED',
'Module "%s" is not of type "%s"', TypeError);
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
E('ERR_IMPORT_ASSERTION_TYPE_MISSING',
'Module "%s" needs an import assertion of type "%s"', TypeError);
'Module "%s" needs an import attribute of type "%s"', TypeError);
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
E('ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED',
'Import assertion type "%s" is unsupported', TypeError);
'Import attribute type "%s" is unsupported', TypeError);
E('ERR_IMPORT_ATTRIBUTE_UNSUPPORTED',
'Import attribute "%s" with value "%s" is not supported', TypeError);
E('ERR_INCOMPATIBLE_OPTION_PAIR',
'Option "%s" cannot be used in combination with option "%s"', TypeError);
E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' +
Expand Down
8 changes: 4 additions & 4 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1157,10 +1157,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
const script = new Script(wrapper, {
filename,
lineOffset: 0,
importModuleDynamically: async (specifier, _, importAssertions) => {
importModuleDynamically: async (specifier, _, importAttributes) => {
const loader = asyncESM.esmLoader;
return loader.import(specifier, normalizeReferrerURL(filename),
importAssertions);
importAttributes);
},
});

Expand All @@ -1183,10 +1183,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
'__dirname',
], {
filename,
importModuleDynamically(specifier, _, importAssertions) {
importModuleDynamically(specifier, _, importAttributes) {
const loader = asyncESM.esmLoader;
return loader.import(specifier, normalizeReferrerURL(filename),
importAssertions);
importAttributes);
},
});

Expand Down
Loading