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 d1ef6aa

Browse filesBrowse files
authored
esm: use import attributes instead of import assertions
The old import assertions proposal has been renamed to "import attributes" with the follwing major changes: 1. The keyword is now `with` instead of `assert`. 2. Unknown assertions cause an error rather than being ignored, This commit updates the documentation to encourage folks to use the new syntax, and add aliases for module customization hooks. PR-URL: #50140 Fixes: #50134 Refs: v8/v8@159c82c Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent f447a46 commit d1ef6aa
Copy full SHA for d1ef6aa

File tree

Expand file treeCollapse file tree

60 files changed

+472
-353
lines changed
Open diff view settings
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

60 files changed

+472
-353
lines changed
Open diff view settings
Collapse file

‎.eslintignore‎

Copy file name to clipboardExpand all lines: .eslintignore
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ tools/github_reporter
99
benchmark/tmp
1010
benchmark/fixtures
1111
doc/**/*.js
12+
doc/changelogs/CHANGELOG_v1*.md
13+
!doc/changelogs/CHANGELOG_v18.md
1214
!doc/api_assets/*.js
1315
!.eslintrc.js
Collapse file

‎.eslintrc.js‎

Copy file name to clipboardExpand all lines: .eslintrc.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const hacks = [
1818
'eslint-plugin-jsdoc',
1919
'eslint-plugin-markdown',
2020
'@babel/eslint-parser',
21-
'@babel/plugin-syntax-import-assertions',
21+
'@babel/plugin-syntax-import-attributes',
2222
];
2323
Module._findPath = (request, paths, isMain) => {
2424
const r = ModuleFindPath(request, paths, isMain);
@@ -44,7 +44,7 @@ module.exports = {
4444
parserOptions: {
4545
babelOptions: {
4646
plugins: [
47-
Module._findPath('@babel/plugin-syntax-import-assertions'),
47+
Module._findPath('@babel/plugin-syntax-import-attributes'),
4848
],
4949
},
5050
requireConfigFile: false,
Collapse file

‎doc/api/errors.md‎

Copy file name to clipboardExpand all lines: doc/api/errors.md
+14-3Lines changed: 14 additions & 3 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,8 @@ added:
17591759
- v16.14.0
17601760
-->
17611761

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

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

@@ -1771,7 +1772,7 @@ added:
17711772
- v16.14.0
17721773
-->
17731774

1774-
An import assertion is missing, preventing the specified module to be imported.
1775+
An import attribute is missing, preventing the specified module to be imported.
17751776

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

@@ -1783,7 +1784,17 @@ added:
17831784
- v16.14.0
17841785
-->
17851786

1786-
An import assertion is not supported by this version of Node.js.
1787+
An import attribute is not supported by this version of Node.js.
1788+
1789+
<a id="ERR_IMPORT_ATTRIBUTE_UNSUPPORTED"></a>
1790+
1791+
### `ERR_IMPORT_ATTRIBUTE_UNSUPPORTED`
1792+
1793+
<!-- YAML
1794+
added: REPLACEME
1795+
-->
1796+
1797+
An import attribute is not supported by this version of Node.js.
17871798

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

Collapse file

‎doc/api/esm.md‎

Copy file name to clipboardExpand all lines: doc/api/esm.md
+26-13Lines changed: 26 additions & 13 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
<!-- YAML
88
added: v8.5.0
99
changes:
10+
- version: REPLACEME
11+
pr-url: https://github.com/nodejs/node/pull/50140
12+
description: Add experimental support for import attributes.
1013
- version: v20.0.0
1114
pr-url: https://github.com/nodejs/node/pull/44710
1215
description: Module customization hooks are executed off the main thread.
@@ -19,7 +22,7 @@ changes:
1922
- v17.1.0
2023
- v16.14.0
2124
pr-url: https://github.com/nodejs/node/pull/40250
22-
description: Add support for import assertions.
25+
description: Add experimental support for import assertions.
2326
- version:
2427
- v17.0.0
2528
- v16.12.0
@@ -203,7 +206,7 @@ added: v12.10.0
203206

204207
```js
205208
import 'data:text/javascript,console.log("hello!");';
206-
import _ from 'data:application/json,"world!"' assert { type: 'json' };
209+
import _ from 'data:application/json,"world!"' with { type: 'json' };
207210
```
208211

209212
`data:` URLs only resolve [bare specifiers][Terminology] for builtin modules
@@ -235,30 +238,40 @@ absolute URL strings.
235238
import fs from 'node:fs/promises';
236239
```
237240

238-
## Import assertions
241+
<a id="import-assertions"></a>
242+
243+
## Import attributes
239244

240245
<!-- YAML
241246
added:
242247
- v17.1.0
243248
- v16.14.0
249+
changes:
250+
- version: REPLACEME
251+
pr-url: https://github.com/nodejs/node/pull/50140
252+
description: Switch from Import Assertions to Import Attributes.
244253
-->
245254

246-
> Stability: 1 - Experimental
255+
> Stability: 1.1 - Active development
256+
257+
> This feature was previously named "Import assertions", and using the `assert`
258+
> keyword instead of `with`. Any uses in code of the prior `assert` keyword
259+
> should be updated to use `with` instead.
247260
248-
The [Import Assertions proposal][] adds an inline syntax for module import
261+
The [Import Attributes proposal][] adds an inline syntax for module import
249262
statements to pass on more information alongside the module specifier.
250263

251264
```js
252-
import fooData from './foo.json' assert { type: 'json' };
265+
import fooData from './foo.json' with { type: 'json' };
253266

254267
const { default: barData } =
255-
await import('./bar.json', { assert: { type: 'json' } });
268+
await import('./bar.json', { with: { type: 'json' } });
256269
```
257270

258-
Node.js supports the following `type` values, for which the assertion is
271+
Node.js supports the following `type` values, for which the attribute is
259272
mandatory:
260273

261-
| Assertion `type` | Needed for |
274+
| Attribute `type` | Needed for |
262275
| ---------------- | ---------------- |
263276
| `'json'` | [JSON modules][] |
264277

@@ -545,10 +558,10 @@ separate cache.
545558
JSON files can be referenced by `import`:
546559

547560
```js
548-
import packageConfig from './package.json' assert { type: 'json' };
561+
import packageConfig from './package.json' with { type: 'json' };
549562
```
550563
551-
The `assert { type: 'json' }` syntax is mandatory; see [Import Assertions][].
564+
The `with { type: 'json' }` syntax is mandatory; see [Import Attributes][].
552565
553566
The imported JSON only exposes a `default` export. There is no support for named
554567
exports. A cache entry is created in the CommonJS cache to avoid duplication.
@@ -1055,8 +1068,8 @@ resolution for ESM specifiers is [commonjs-extension-resolution-loader][].
10551068
[Determining module system]: packages.md#determining-module-system
10561069
[Dynamic `import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
10571070
[ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
1058-
[Import Assertions]: #import-assertions
1059-
[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
1071+
[Import Attributes]: #import-attributes
1072+
[Import Attributes proposal]: https://github.com/tc39/proposal-import-attributes
10601073
[JSON modules]: #json-modules
10611074
[Module customization hooks]: module.md#customization-hooks
10621075
[Node.js Module Resolution And Loading Algorithm]: #resolution-algorithm-specification
Collapse file

‎doc/api/module.md‎

Copy file name to clipboardExpand all lines: doc/api/module.md
+12-7Lines changed: 12 additions & 7 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,11 @@ register('./path-to-my-hooks.js', {
458458
459459
<!-- YAML
460460
changes:
461+
- version: REPLACEME
462+
pr-url: https://github.com/nodejs/node/pull/50140
463+
description: The property `context.importAssertions` is replaced with
464+
`context.importAttributes`. Using the old name is still
465+
supported and will emit an experimental warning.
461466
- version:
462467
- v18.6.0
463468
- v16.17.0
@@ -477,8 +482,8 @@ changes:
477482
* `specifier` {string}
478483
* `context` {Object}
479484
* `conditions` {string\[]} Export conditions of the relevant `package.json`
480-
* `importAssertions` {Object} An object whose key-value pairs represent the
481-
assertions for the module to import
485+
* `importAttributes` {Object} An object whose key-value pairs represent the
486+
attributes for the module to import
482487
* `parentURL` {string|undefined} The module importing this one, or undefined
483488
if this is the Node.js entry point
484489
* `nextResolve` {Function} The subsequent `resolve` hook in the chain, or the
@@ -489,7 +494,7 @@ changes:
489494
* `format` {string|null|undefined} A hint to the load hook (it might be
490495
ignored)
491496
`'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'`
492-
* `importAssertions` {Object|undefined} The import assertions to use when
497+
* `importAttributes` {Object|undefined} The import attributes to use when
493498
caching the module (optional; if excluded the input will be used)
494499
* `shortCircuit` {undefined|boolean} A signal that this hook intends to
495500
terminate the chain of `resolve` hooks. **Default:** `false`
@@ -506,10 +511,10 @@ the final `format` value (and it is free to ignore the hint provided by
506511
`resolve`); if `resolve` provides a `format`, a custom `load` hook is required
507512
even if only to pass the value to the Node.js default `load` hook.
508513
509-
Import type assertions are part of the cache key for saving loaded modules into
514+
Import type attributes are part of the cache key for saving loaded modules into
510515
the internal module cache. The `resolve` hook is responsible for returning an
511-
`importAssertions` object if the module should be cached with different
512-
assertions than were present in the source code.
516+
`importAttributes` object if the module should be cached with different
517+
attributes than were present in the source code.
513518
514519
The `conditions` property in `context` is an array of conditions for
515520
[package exports conditions][Conditional exports] that apply to this resolution
@@ -575,7 +580,7 @@ changes:
575580
* `conditions` {string\[]} Export conditions of the relevant `package.json`
576581
* `format` {string|null|undefined} The format optionally supplied by the
577582
`resolve` hook chain
578-
* `importAssertions` {Object}
583+
* `importAttributes` {Object}
579584
* `nextLoad` {Function} The subsequent `load` hook in the chain, or the
580585
Node.js default `load` hook after the last user-supplied `load` hook
581586
* `specifier` {string}
Collapse file

‎lib/internal/errors.js‎

Copy file name to clipboardExpand all lines: lib/internal/errors.js
+7-2Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,12 +1280,17 @@ E('ERR_HTTP_SOCKET_ENCODING',
12801280
E('ERR_HTTP_TRAILER_INVALID',
12811281
'Trailers are invalid with this transfer encoding', Error);
12821282
E('ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor', TypeError);
1283+
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
12831284
E('ERR_IMPORT_ASSERTION_TYPE_FAILED',
12841285
'Module "%s" is not of type "%s"', TypeError);
1286+
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
12851287
E('ERR_IMPORT_ASSERTION_TYPE_MISSING',
1286-
'Module "%s" needs an import assertion of type "%s"', TypeError);
1288+
'Module "%s" needs an import attribute of type "%s"', TypeError);
1289+
// TODO(aduh95): change the error to mention import attributes instead of import assertions.
12871290
E('ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED',
1288-
'Import assertion type "%s" is unsupported', TypeError);
1291+
'Import attribute type "%s" is unsupported', TypeError);
1292+
E('ERR_IMPORT_ATTRIBUTE_UNSUPPORTED',
1293+
'Import attribute "%s" with value "%s" is not supported', TypeError);
12891294
E('ERR_INCOMPATIBLE_OPTION_PAIR',
12901295
'Option "%s" cannot be used in combination with option "%s"', TypeError);
12911296
E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' +
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,10 +1258,10 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
12581258
const script = new Script(wrapper, {
12591259
filename,
12601260
lineOffset: 0,
1261-
importModuleDynamically: async (specifier, _, importAssertions) => {
1261+
importModuleDynamically: async (specifier, _, importAttributes) => {
12621262
const cascadedLoader = getCascadedLoader();
12631263
return cascadedLoader.import(specifier, normalizeReferrerURL(filename),
1264-
importAssertions);
1264+
importAttributes);
12651265
},
12661266
});
12671267

@@ -1285,10 +1285,10 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) {
12851285
], {
12861286
filename,
12871287
cachedData: codeCache,
1288-
importModuleDynamically(specifier, _, importAssertions) {
1288+
importModuleDynamically(specifier, _, importAttributes) {
12891289
const cascadedLoader = getCascadedLoader();
12901290
return cascadedLoader.import(specifier, normalizeReferrerURL(filename),
1291-
importAssertions);
1291+
importAttributes);
12921292
},
12931293
});
12941294

Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/assert.js
+24-29Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@ const {
1313
ERR_IMPORT_ASSERTION_TYPE_FAILED,
1414
ERR_IMPORT_ASSERTION_TYPE_MISSING,
1515
ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED,
16+
ERR_IMPORT_ATTRIBUTE_UNSUPPORTED,
1617
} = require('internal/errors').codes;
1718

1819
// The HTML spec has an implied default type of `'javascript'`.
1920
const kImplicitAssertType = 'javascript';
2021

21-
let alreadyWarned = false;
22-
2322
/**
24-
* Define a map of module formats to import assertion types (the value of
25-
* `type` in `assert { type: 'json' }`).
23+
* Define a map of module formats to import attributes types (the value of
24+
* `type` in `with { type: 'json' }`).
2625
* @type {Map<string, string>}
2726
*/
2827
const formatTypeMap = {
@@ -31,13 +30,13 @@ const formatTypeMap = {
3130
'commonjs': kImplicitAssertType,
3231
'json': 'json',
3332
'module': kImplicitAssertType,
34-
'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an assertion type or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42
33+
'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an attribute type or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42
3534
};
3635

3736
/**
3837
* The HTML spec disallows the default type to be explicitly specified
3938
* (for now); so `import './file.js'` is okay but
40-
* `import './file.js' assert { type: 'javascript' }` throws.
39+
* `import './file.js' with { type: 'javascript' }` throws.
4140
* @type {Array<string, string>}
4241
*/
4342
const supportedAssertionTypes = ArrayPrototypeFilter(
@@ -46,54 +45,50 @@ const supportedAssertionTypes = ArrayPrototypeFilter(
4645

4746

4847
/**
49-
* Test a module's import assertions.
48+
* Test a module's import attributes.
5049
* @param {string} url The URL of the imported module, for error reporting.
5150
* @param {string} format One of Node's supported translators
52-
* @param {Record<string, string>} importAssertions Validations for the
51+
* @param {Record<string, string>} importAttributes Validations for the
5352
* module import.
5453
* @returns {true}
5554
* @throws {TypeError} If the format and assertion type are incompatible.
5655
*/
57-
function validateAssertions(url, format,
58-
importAssertions = { __proto__: null }) {
59-
const validType = formatTypeMap[format];
60-
61-
if (!alreadyWarned && ObjectKeys(importAssertions).length !== 0) {
62-
alreadyWarned = true;
63-
process.emitWarning(
64-
'Import assertions are not a stable feature of the JavaScript language. ' +
65-
'Avoid relying on their current behavior and syntax as those might change ' +
66-
'in a future version of Node.js.',
67-
'ExperimentalWarning',
68-
);
56+
function validateAttributes(url, format,
57+
importAttributes = { __proto__: null }) {
58+
const keys = ObjectKeys(importAttributes);
59+
for (let i = 0; i < keys.length; i++) {
60+
if (keys[i] !== 'type') {
61+
throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED(keys[i], importAttributes[keys[i]]);
62+
}
6963
}
64+
const validType = formatTypeMap[format];
7065

7166
switch (validType) {
7267
case undefined:
73-
// Ignore assertions for module formats we don't recognize, to allow new
68+
// Ignore attributes for module formats we don't recognize, to allow new
7469
// formats in the future.
7570
return true;
7671

7772
case kImplicitAssertType:
7873
// This format doesn't allow an import assertion type, so the property
79-
// must not be set on the import assertions object.
80-
if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) {
74+
// must not be set on the import attributes object.
75+
if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
8176
return true;
8277
}
83-
return handleInvalidType(url, importAssertions.type);
78+
return handleInvalidType(url, importAttributes.type);
8479

85-
case importAssertions.type:
80+
case importAttributes.type:
8681
// The asserted type is the valid type for this format.
8782
return true;
8883

8984
default:
9085
// There is an expected type for this format, but the value of
91-
// `importAssertions.type` might not have been it.
92-
if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) {
86+
// `importAttributes.type` might not have been it.
87+
if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) {
9388
// `type` wasn't specified at all.
9489
throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType);
9590
}
96-
return handleInvalidType(url, importAssertions.type);
91+
return handleInvalidType(url, importAttributes.type);
9792
}
9893
}
9994

@@ -118,5 +113,5 @@ function handleInvalidType(url, type) {
118113

119114
module.exports = {
120115
kImplicitAssertType,
121-
validateAssertions,
116+
validateAttributes,
122117
};

0 commit comments

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