GeezerVison is showing github.com — esm: use import attributes instead of import assertions · nodejs/node@ee65e44
File treeExpand file treeCollapse file tree Open diff view settings node_modules/eslint/node_modules plugin-syntax-import-assertions/lib plugin-syntax-import-attributes
Some content is hiddenLarge Commits have some content hidden by default. Use the searchbox below for content that may be hidden. Dismiss bannerExpand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: .eslintignore +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -9,5 +9,7 @@ tools/github_reporter | 9 | 9 | benchmark/tmp | 10 | 10 | benchmark/fixtures | 11 | 11 | doc/**/*.js | | 12 | +doc/changelogs/CHANGELOG_v1*.md | | 13 | +!doc/changelogs/CHANGELOG_v18.md | 12 | 14 | !doc/api_assets/*.js | 13 | 15 | !.eslintrc.js |
Collapse file Copy file name to clipboardExpand all lines: .eslintrc.js +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -18,7 +18,7 @@ const hacks = [ | 18 | 18 | 'eslint-plugin-jsdoc', | 19 | 19 | 'eslint-plugin-markdown', | 20 | 20 | '@babel/eslint-parser', | 21 | | - '@babel/plugin-syntax-import-assertions', | | 21 | + '@babel/plugin-syntax-import-attributes', | 22 | 22 | ]; | 23 | 23 | Module._findPath = (request, paths, isMain) => { | 24 | 24 | const r = ModuleFindPath(request, paths, isMain); | @@ -44,7 +44,7 @@ module.exports = { | 44 | 44 | parserOptions: { | 45 | 45 | babelOptions: { | 46 | 46 | plugins: [ | 47 | | - Module._findPath('@babel/plugin-syntax-import-assertions'), | | 47 | + Module._findPath('@babel/plugin-syntax-import-attributes'), | 48 | 48 | ], | 49 | 49 | }, | 50 | 50 | requireConfigFile: false, | |
Collapse file 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 number | Diff line number | Diff line change |
|---|
@@ -1759,7 +1759,8 @@ added: | 1759 | 1759 | - v16.14.0 | 1760 | 1760 | --> | 1761 | 1761 |
| 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. | 1763 | 1764 |
| 1764 | 1765 | <a id="ERR_IMPORT_ASSERTION_TYPE_MISSING"></a> | 1765 | 1766 |
| @@ -1771,7 +1772,7 @@ added: | 1771 | 1772 | - v16.14.0 | 1772 | 1773 | --> | 1773 | 1774 |
| 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. | 1775 | 1776 |
| 1776 | 1777 | <a id="ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED"></a> | 1777 | 1778 |
| @@ -1783,7 +1784,17 @@ added: | 1783 | 1784 | - v16.14.0 | 1784 | 1785 | --> | 1785 | 1786 |
| 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. | 1787 | 1798 |
| 1788 | 1799 | <a id="ERR_INCOMPATIBLE_OPTION_PAIR"></a> | 1789 | 1800 |
| |
Collapse file 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 number | Diff line number | Diff line change |
|---|
| 7 | 7 | <!-- YAML | 8 | 8 | added: v8.5.0 | 9 | 9 | changes: | | 10 | + - version: REPLACEME | | 11 | + pr-url: https://github.com/nodejs/node/pull/50140 | | 12 | + description: Add experimental support for import attributes. | 10 | 13 | - version: v20.0.0 | 11 | 14 | pr-url: https://github.com/nodejs/node/pull/44710 | 12 | 15 | description: Module customization hooks are executed off the main thread. | @@ -19,7 +22,7 @@ changes: | 19 | 22 | - v17.1.0 | 20 | 23 | - v16.14.0 | 21 | 24 | pr-url: https://github.com/nodejs/node/pull/40250 | 22 | | - description: Add support for import assertions. | | 25 | + description: Add experimental support for import assertions. | 23 | 26 | - version: | 24 | 27 | - v17.0.0 | 25 | 28 | - v16.12.0 | @@ -203,7 +206,7 @@ added: v12.10.0 | 203 | 206 |
| 204 | 207 | ```js | 205 | 208 | 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' }; | 207 | 210 | ``` | 208 | 211 |
| 209 | 212 | `data:` URLs only resolve [bare specifiers][Terminology] for builtin modules | @@ -235,30 +238,40 @@ absolute URL strings. | 235 | 238 | import fs from 'node:fs/promises'; | 236 | 239 | ``` | 237 | 240 |
| 238 | | -## Import assertions | | 241 | +<a id="import-assertions"></a> | | 242 | + | | 243 | +## Import attributes | 239 | 244 |
| 240 | 245 | <!-- YAML | 241 | 246 | added: | 242 | 247 | - v17.1.0 | 243 | 248 | - 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. | 244 | 253 | --> | 245 | 254 |
| 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. | 247 | 260 |
| 248 | | -The [Import Assertions proposal][] adds an inline syntax for module import | | 261 | +The [Import Attributes proposal][] adds an inline syntax for module import | 249 | 262 | statements to pass on more information alongside the module specifier. | 250 | 263 |
| 251 | 264 | ```js | 252 | | -import fooData from './foo.json' assert { type: 'json' }; | | 265 | +import fooData from './foo.json' with { type: 'json' }; | 253 | 266 |
| 254 | 267 | const { default: barData } = | 255 | | - await import('./bar.json', { assert: { type: 'json' } }); | | 268 | + await import('./bar.json', { with: { type: 'json' } }); | 256 | 269 | ``` | 257 | 270 |
| 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 | 259 | 272 | mandatory: | 260 | 273 |
| 261 | | -| Assertion `type` | Needed for | | | 274 | +| Attribute `type` | Needed for | | 262 | 275 | | ---------------- | ---------------- | | 263 | 276 | | `'json'` | [JSON modules][] | | 264 | 277 |
| @@ -545,10 +558,10 @@ separate cache. | 545 | 558 | JSON files can be referenced by `import`: | 546 | 559 |
| 547 | 560 | ```js | 548 | | -import packageConfig from './package.json' assert { type: 'json' }; | | 561 | +import packageConfig from './package.json' with { type: 'json' }; | 549 | 562 | ``` | 550 | 563 |
| 551 | | -The `assert { type: 'json' }` syntax is mandatory; see [Import Assertions][]. | | 564 | +The `with { type: 'json' }` syntax is mandatory; see [Import Attributes][]. | 552 | 565 |
| 553 | 566 | The imported JSON only exposes a `default` export. There is no support for named | 554 | 567 | 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][]. | 1055 | 1068 | [Determining module system]: packages.md#determining-module-system | 1056 | 1069 | [Dynamic `import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import | 1057 | 1070 | [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 | 1060 | 1073 | [JSON modules]: #json-modules | 1061 | 1074 | [Module customization hooks]: module.md#customization-hooks | 1062 | 1075 | [Node.js Module Resolution And Loading Algorithm]: #resolution-algorithm-specification | |
Collapse file 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 number | Diff line number | Diff line change |
|---|
@@ -458,6 +458,11 @@ register('./path-to-my-hooks.js', { | 458 | 458 |
| 459 | 459 | <!-- YAML | 460 | 460 | 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. | 461 | 466 | - version: | 462 | 467 | - v18.6.0 | 463 | 468 | - v16.17.0 | @@ -477,8 +482,8 @@ changes: | 477 | 482 | * `specifier` {string} | 478 | 483 | * `context` {Object} | 479 | 484 | * `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 | 482 | 487 | * `parentURL` {string|undefined} The module importing this one, or undefined | 483 | 488 | if this is the Node.js entry point | 484 | 489 | * `nextResolve` {Function} The subsequent `resolve` hook in the chain, or the | @@ -489,7 +494,7 @@ changes: | 489 | 494 | * `format` {string|null|undefined} A hint to the load hook (it might be | 490 | 495 | ignored) | 491 | 496 | `'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 | 493 | 498 | caching the module (optional; if excluded the input will be used) | 494 | 499 | * `shortCircuit` {undefined|boolean} A signal that this hook intends to | 495 | 500 | 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 | 506 | 511 | `resolve`); if `resolve` provides a `format`, a custom `load` hook is required | 507 | 512 | even if only to pass the value to the Node.js default `load` hook. | 508 | 513 |
| 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 | 510 | 515 | 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. | 513 | 518 |
| 514 | 519 | The `conditions` property in `context` is an array of conditions for | 515 | 520 | [package exports conditions][Conditional exports] that apply to this resolution | @@ -575,7 +580,7 @@ changes: | 575 | 580 | * `conditions` {string\[]} Export conditions of the relevant `package.json` | 576 | 581 | * `format` {string|null|undefined} The format optionally supplied by the | 577 | 582 | `resolve` hook chain | 578 | | - * `importAssertions` {Object} | | 583 | + * `importAttributes` {Object} | 579 | 584 | * `nextLoad` {Function} The subsequent `load` hook in the chain, or the | 580 | 585 | Node.js default `load` hook after the last user-supplied `load` hook | 581 | 586 | * `specifier` {string} | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/errors.js +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1280,12 +1280,17 @@ E('ERR_HTTP_SOCKET_ENCODING', | 1280 | 1280 | E('ERR_HTTP_TRAILER_INVALID', | 1281 | 1281 | 'Trailers are invalid with this transfer encoding', Error); | 1282 | 1282 | E('ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor', TypeError); | | 1283 | +// TODO(aduh95): change the error to mention import attributes instead of import assertions. | 1283 | 1284 | E('ERR_IMPORT_ASSERTION_TYPE_FAILED', | 1284 | 1285 | 'Module "%s" is not of type "%s"', TypeError); | | 1286 | +// TODO(aduh95): change the error to mention import attributes instead of import assertions. | 1285 | 1287 | 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. | 1287 | 1290 | 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); | 1289 | 1294 | E('ERR_INCOMPATIBLE_OPTION_PAIR', | 1290 | 1295 | 'Option "%s" cannot be used in combination with option "%s"', TypeError); | 1291 | 1296 | E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' + | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js +4-4Lines changed: 4 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1258,10 +1258,10 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) { | 1258 | 1258 | const script = new Script(wrapper, { | 1259 | 1259 | filename, | 1260 | 1260 | lineOffset: 0, | 1261 | | - importModuleDynamically: async (specifier, _, importAssertions) => { | | 1261 | + importModuleDynamically: async (specifier, _, importAttributes) => { | 1262 | 1262 | const cascadedLoader = getCascadedLoader(); | 1263 | 1263 | return cascadedLoader.import(specifier, normalizeReferrerURL(filename), | 1264 | | - importAssertions); | | 1264 | + importAttributes); | 1265 | 1265 | }, | 1266 | 1266 | }); | 1267 | 1267 |
| @@ -1285,10 +1285,10 @@ function wrapSafe(filename, content, cjsModuleInstance, codeCache) { | 1285 | 1285 | ], { | 1286 | 1286 | filename, | 1287 | 1287 | cachedData: codeCache, | 1288 | | - importModuleDynamically(specifier, _, importAssertions) { | | 1288 | + importModuleDynamically(specifier, _, importAttributes) { | 1289 | 1289 | const cascadedLoader = getCascadedLoader(); | 1290 | 1290 | return cascadedLoader.import(specifier, normalizeReferrerURL(filename), | 1291 | | - importAssertions); | | 1291 | + importAttributes); | 1292 | 1292 | }, | 1293 | 1293 | }); | 1294 | 1294 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/assert.js +24-29Lines changed: 24 additions & 29 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -13,16 +13,15 @@ const { | 13 | 13 | ERR_IMPORT_ASSERTION_TYPE_FAILED, | 14 | 14 | ERR_IMPORT_ASSERTION_TYPE_MISSING, | 15 | 15 | ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED, | | 16 | + ERR_IMPORT_ATTRIBUTE_UNSUPPORTED, | 16 | 17 | } = require('internal/errors').codes; | 17 | 18 |
| 18 | 19 | // The HTML spec has an implied default type of `'javascript'`. | 19 | 20 | const kImplicitAssertType = 'javascript'; | 20 | 21 |
| 21 | | -let alreadyWarned = false; | 22 | | - | 23 | 22 | /** | 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' }`). | 26 | 25 | * @type {Map<string, string>} | 27 | 26 | */ | 28 | 27 | const formatTypeMap = { | @@ -31,13 +30,13 @@ const formatTypeMap = { | 31 | 30 | 'commonjs': kImplicitAssertType, | 32 | 31 | 'json': 'json', | 33 | 32 | '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 | 35 | 34 | }; | 36 | 35 |
| 37 | 36 | /** | 38 | 37 | * The HTML spec disallows the default type to be explicitly specified | 39 | 38 | * (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. | 41 | 40 | * @type {Array<string, string>} | 42 | 41 | */ | 43 | 42 | const supportedAssertionTypes = ArrayPrototypeFilter( | @@ -46,54 +45,50 @@ const supportedAssertionTypes = ArrayPrototypeFilter( | 46 | 45 |
| 47 | 46 |
| 48 | 47 | /** | 49 | | - * Test a module's import assertions. | | 48 | + * Test a module's import attributes. | 50 | 49 | * @param {string} url The URL of the imported module, for error reporting. | 51 | 50 | * @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 | 53 | 52 | * module import. | 54 | 53 | * @returns {true} | 55 | 54 | * @throws {TypeError} If the format and assertion type are incompatible. | 56 | 55 | */ | 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 | + } | 69 | 63 | } | | 64 | + const validType = formatTypeMap[format]; | 70 | 65 |
| 71 | 66 | switch (validType) { | 72 | 67 | 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 | 74 | 69 | // formats in the future. | 75 | 70 | return true; | 76 | 71 |
| 77 | 72 | case kImplicitAssertType: | 78 | 73 | // 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')) { | 81 | 76 | return true; | 82 | 77 | } | 83 | | - return handleInvalidType(url, importAssertions.type); | | 78 | + return handleInvalidType(url, importAttributes.type); | 84 | 79 |
| 85 | | - case importAssertions.type: | | 80 | + case importAttributes.type: | 86 | 81 | // The asserted type is the valid type for this format. | 87 | 82 | return true; | 88 | 83 |
| 89 | 84 | default: | 90 | 85 | // 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')) { | 93 | 88 | // `type` wasn't specified at all. | 94 | 89 | throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType); | 95 | 90 | } | 96 | | - return handleInvalidType(url, importAssertions.type); | | 91 | + return handleInvalidType(url, importAttributes.type); | 97 | 92 | } | 98 | 93 | } | 99 | 94 |
| @@ -118,5 +113,5 @@ function handleInvalidType(url, type) { | 118 | 113 |
| 119 | 114 | module.exports = { | 120 | 115 | kImplicitAssertType, | 121 | | - validateAssertions, | | 116 | + validateAttributes, | 122 | 117 | }; |
|