| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c29658f commit 95e4d29
52 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1689,6 +1689,36 @@ is set for the `Http2Stream`. | |||
| 1689 | 1689 | ||
| 1690 | 1690 | An attempt was made to construct an object using a non-public constructor. | |
| 1691 | 1691 | ||
| 1692 | + <a id="ERR_IMPORT_ASSERTION_TYPE_FAILED"></a> | ||
| 1693 | + | ||
| 1694 | + ### `ERR_IMPORT_ASSERTION_TYPE_FAILED` | ||
| 1695 | + | ||
| 1696 | + <!-- YAML | ||
| 1697 | + added: REPLACEME | ||
| 1698 | + --> | ||
| 1699 | + | ||
| 1700 | + An import assertion has failed, preventing the specified module to be imported. | ||
| 1701 | + | ||
| 1702 | + <a id="ERR_IMPORT_ASSERTION_TYPE_MISSING"></a> | ||
| 1703 | + | ||
| 1704 | + ### `ERR_IMPORT_ASSERTION_TYPE_MISSING` | ||
| 1705 | + | ||
| 1706 | + <!-- YAML | ||
| 1707 | + added: REPLACEME | ||
| 1708 | + --> | ||
| 1709 | + | ||
| 1710 | + An import assertion is missing, preventing the specified module to be imported. | ||
| 1711 | + | ||
| 1712 | + <a id="ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED"></a> | ||
| 1713 | + | ||
| 1714 | + ### `ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED` | ||
| 1715 | + | ||
| 1716 | + <!-- YAML | ||
| 1717 | + added: REPLACEME | ||
| 1718 | + --> | ||
| 1719 | + | ||
| 1720 | + An import assertion is not supported by this version of Node.js. | ||
| 1721 | + | ||
| 1692 | 1722 | <a id="ERR_INCOMPATIBLE_OPTION_PAIR"></a> | |
| 1693 | 1723 | ||
| 1694 | 1724 | ### `ERR_INCOMPATIBLE_OPTION_PAIR` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,9 @@ | |||
| 7 | 7 | <!-- YAML | |
| 8 | 8 | added: v8.5.0 | |
| 9 | 9 | changes: | |
| 10 | + - version: REPLACEME | ||
| 11 | + pr-url: https://github.com/nodejs/node/pull/40250 | ||
| 12 | + description: Add support for import assertions. | ||
| 10 | 13 | - version: | |
| 11 | 14 | - v17.0.0 | |
| 12 | 15 | pr-url: https://github.com/nodejs/node/pull/37468 | |
@@ -219,6 +222,28 @@ absolute URL strings. | |||
| 219 | 222 | import fs from 'node:fs/promises'; | |
| 220 | 223 | ``` | |
| 221 | 224 | ||
| 225 | + ## Import assertions | ||
| 226 | + | ||
| 227 | + <!-- YAML | ||
| 228 | + added: REPLACEME | ||
| 229 | + --> | ||
| 230 | + | ||
| 231 | + The [Import Assertions proposal][] adds an inline syntax for module import | ||
| 232 | + statements to pass on more information alongside the module specifier. | ||
| 233 | + | ||
| 234 | + ```js | ||
| 235 | + import fooData from './foo.json' assert { type: 'json' }; | ||
| 236 | + | ||
| 237 | + const { default: barData } = | ||
| 238 | + await import('./bar.json', { assert: { type: 'json' } }); | ||
| 239 | + ``` | ||
| 240 | + | ||
| 241 | + Node.js supports the following `type` values: | ||
| 242 | + | ||
| 243 | + | `type` | Resolves to | | ||
| 244 | + | -------- | ---------------- | | ||
| 245 | + | `'json'` | [JSON modules][] | | ||
| 246 | + | ||
| 222 | 247 | ## Builtin modules | |
| 223 | 248 | ||
| 224 | 249 | [Core modules][] provide named exports of their public API. A | |
@@ -516,10 +541,8 @@ same path. | |||
| 516 | 541 | ||
| 517 | 542 | Assuming an `index.mjs` with | |
| 518 | 543 | ||
| 519 | - <!-- eslint-skip --> | ||
| 520 | - | ||
| 521 | 544 | ```js | |
| 522 | - import packageConfig from './package.json'; | ||
| 545 | + import packageConfig from './package.json' assert { type: 'json' }; | ||
| 523 | 546 | ``` | |
| 524 | 547 | ||
| 525 | 548 | The `--experimental-json-modules` flag is needed for the module | |
@@ -607,12 +630,20 @@ CommonJS modules loaded. | |||
| 607 | 630 | ||
| 608 | 631 | #### `resolve(specifier, context, defaultResolve)` | |
| 609 | 632 | ||
| 633 | + <!-- YAML | ||
| 634 | + changes: | ||
| 635 | + - version: REPLACEME | ||
| 636 | + pr-url: https://github.com/nodejs/node/pull/40250 | ||
| 637 | + description: Add support for import assertions. | ||
| 638 | + --> | ||
| 639 | + | ||
| 610 | 640 | > Note: The loaders API is being redesigned. This hook may disappear or its | |
| 611 | 641 | > signature may change. Do not rely on the API described below. | |
| 612 | 642 | ||
| 613 | 643 | * `specifier` {string} | |
| 614 | 644 | * `context` {Object} | |
| 615 | 645 | * `conditions` {string\[]} | |
| 646 | + * `importAssertions` {Object} | ||
| 616 | 647 | * `parentURL` {string|undefined} | |
| 617 | 648 | * `defaultResolve` {Function} The Node.js default resolver. | |
| 618 | 649 | * Returns: {Object} | |
@@ -689,13 +720,15 @@ export async function resolve(specifier, context, defaultResolve) { | |||
| 689 | 720 | * `context` {Object} | |
| 690 | 721 | * `format` {string|null|undefined} The format optionally supplied by the | |
| 691 | 722 | `resolve` hook. | |
| 723 | + * `importAssertions` {Object} | ||
| 692 | 724 | * `defaultLoad` {Function} | |
| 693 | 725 | * Returns: {Object} | |
| 694 | 726 | * `format` {string} | |
| 695 | 727 | * `source` {string|ArrayBuffer|TypedArray} | |
| 696 | 728 | ||
| 697 | 729 | The `load` hook provides a way to define a custom method of determining how | |
| 698 | - a URL should be interpreted, retrieved, and parsed. | ||
| 730 | + a URL should be interpreted, retrieved, and parsed. It is also in charge of | ||
| 731 | + validating the import assertion. | ||
| 699 | 732 | ||
| 700 | 733 | The final value of `format` must be one of the following: | |
| 701 | 734 | ||
@@ -1357,6 +1390,8 @@ success! | |||
| 1357 | 1390 | [Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports | |
| 1358 | 1391 | [ECMAScript Top-Level `await` proposal]: https://github.com/tc39/proposal-top-level-await/ | |
| 1359 | 1392 | [ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration | |
| 1393 | + [Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions | ||
| 1394 | + [JSON modules]: #json-modules | ||
| 1360 | 1395 | [Node.js Module Resolution Algorithm]: #resolver-algorithm-specification | |
| 1361 | 1396 | [Terminology]: #terminology | |
| 1362 | 1397 | [URL]: https://url.spec.whatwg.org/ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1083,6 +1083,12 @@ E('ERR_HTTP_SOCKET_ENCODING', | |||
| 1083 | 1083 | E('ERR_HTTP_TRAILER_INVALID', | |
| 1084 | 1084 | 'Trailers are invalid with this transfer encoding', Error); | |
| 1085 | 1085 | E('ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor', TypeError); | |
| 1086 | + E('ERR_IMPORT_ASSERTION_TYPE_FAILED', | ||
| 1087 | + 'Module "%s" is not of type "%s"', TypeError); | ||
| 1088 | + E('ERR_IMPORT_ASSERTION_TYPE_MISSING', | ||
| 1089 | + 'Module "%s" needs an import assertion of type "%s"', TypeError); | ||
| 1090 | + E('ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', | ||
| 1091 | + 'Import assertion type "%s" is unsupported', TypeError); | ||
| 1086 | 1092 | E('ERR_INCOMPATIBLE_OPTION_PAIR', | |
| 1087 | 1093 | 'Option "%s" cannot be used in combination with option "%s"', TypeError); | |
| 1088 | 1094 | E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1015,9 +1015,10 @@ function wrapSafe(filename, content, cjsModuleInstance) { | |||
| 1015 | 1015 | filename, | |
| 1016 | 1016 | lineOffset: 0, | |
| 1017 | 1017 | displayErrors: true, | |
| 1018 | - importModuleDynamically: async (specifier) => { | ||
| 1018 | + importModuleDynamically: async (specifier, _, importAssertions) => { | ||
| 1019 | 1019 | const loader = asyncESM.esmLoader; | |
| 1020 | - return loader.import(specifier, normalizeReferrerURL(filename)); | ||
| 1020 | + return loader.import(specifier, normalizeReferrerURL(filename), | ||
| 1021 | + importAssertions); | ||
| 1021 | 1022 | }, | |
| 1022 | 1023 | }); | |
| 1023 | 1024 | } | |
@@ -1030,9 +1031,10 @@ function wrapSafe(filename, content, cjsModuleInstance) { | |||
| 1030 | 1031 | '__dirname', | |
| 1031 | 1032 | ], { | |
| 1032 | 1033 | filename, | |
| 1033 | - importModuleDynamically(specifier) { | ||
| 1034 | + importModuleDynamically(specifier, _, importAssertions) { | ||
| 1034 | 1035 | const loader = asyncESM.esmLoader; | |
| 1035 | - return loader.import(specifier, normalizeReferrerURL(filename)); | ||
| 1036 | + return loader.import(specifier, normalizeReferrerURL(filename), | ||
| 1037 | + importAssertions); | ||
| 1036 | 1038 | }, | |
| 1037 | 1039 | }); | |
| 1038 | 1040 | } catch (err) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,102 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { | ||
| 4 | + ArrayPrototypeIncludes, | ||
| 5 | + ObjectCreate, | ||
| 6 | + ObjectValues, | ||
| 7 | + ObjectPrototypeHasOwnProperty, | ||
| 8 | + Symbol, | ||
| 9 | + } = primordials; | ||
| 10 | + const { validateString } = require('internal/validators'); | ||
| 11 | + | ||
| 12 | + const { | ||
| 13 | + ERR_IMPORT_ASSERTION_TYPE_FAILED, | ||
| 14 | + ERR_IMPORT_ASSERTION_TYPE_MISSING, | ||
| 15 | + ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED, | ||
| 16 | + } = require('internal/errors').codes; | ||
| 17 | + | ||
| 18 | + const kImplicitAssertType = Symbol('implicit assert type'); | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * Define a map of module formats to import assertion types (the value of `type` | ||
| 22 | + * in `assert { type: 'json' }`). | ||
| 23 | + * @type {Map<string, string | typeof kImplicitAssertType} | ||
| 24 | + */ | ||
| 25 | + const formatTypeMap = { | ||
| 26 | + '__proto__': null, | ||
| 27 | + 'builtin': kImplicitAssertType, | ||
| 28 | + 'commonjs': kImplicitAssertType, | ||
| 29 | + 'json': 'json', | ||
| 30 | + 'module': kImplicitAssertType, | ||
| 31 | + 'wasm': kImplicitAssertType, // Should probably be 'webassembly' per https://github.com/tc39/proposal-import-assertions | ||
| 32 | + }; | ||
| 33 | + | ||
| 34 | + /** @type {Array<string, string | typeof kImplicitAssertType} */ | ||
| 35 | + const supportedAssertionTypes = ObjectValues(formatTypeMap); | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * Test a module's import assertions. | ||
| 40 | + * @param {string} url The URL of the imported module, for error reporting. | ||
| 41 | + * @param {string} format One of Node's supported translators | ||
| 42 | + * @param {Record<string, string>} importAssertions Validations for the | ||
| 43 | + * module import. | ||
| 44 | + * @returns {true} | ||
| 45 | + * @throws {TypeError} If the format and assertion type are incompatible. | ||
| 46 | + */ | ||
| 47 | + function validateAssertions(url, format, | ||
| 48 | + importAssertions = ObjectCreate(null)) { | ||
| 49 | + const validType = formatTypeMap[format]; | ||
| 50 | + | ||
| 51 | + switch (validType) { | ||
| 52 | + case undefined: | ||
| 53 | + // Ignore assertions for module types we don't recognize, to allow new | ||
| 54 | + // formats in the future. | ||
| 55 | + return true; | ||
| 56 | + | ||
| 57 | + case importAssertions.type: | ||
| 58 | + // The asserted type is the valid type for this format. | ||
| 59 | + return true; | ||
| 60 | + | ||
| 61 | + case kImplicitAssertType: | ||
| 62 | + // This format doesn't allow an import assertion type, so the property | ||
| 63 | + // must not be set on the import assertions object. | ||
| 64 | + if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) { | ||
| 65 | + return true; | ||
| 66 | + } | ||
| 67 | + return handleInvalidType(url, importAssertions.type); | ||
| 68 | + | ||
| 69 | + default: | ||
| 70 | + // There is an expected type for this format, but the value of | ||
| 71 | + // `importAssertions.type` was not it. | ||
| 72 | + if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) { | ||
| 73 | + // `type` wasn't specified at all. | ||
| 74 | + throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType); | ||
| 75 | + } | ||
| 76 | + handleInvalidType(url, importAssertions.type); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * Throw the correct error depending on what's wrong with the type assertion. | ||
| 82 | + * @param {string} url The resolved URL for the module to be imported | ||
| 83 | + * @param {string} type The value of the import assertion `type` property | ||
| 84 | + */ | ||
| 85 | + function handleInvalidType(url, type) { | ||
| 86 | + // `type` might have not been a string. | ||
| 87 | + validateString(type, 'type'); | ||
| 88 | + | ||
| 89 | + // `type` was not one of the types we understand. | ||
| 90 | + if (!ArrayPrototypeIncludes(supportedAssertionTypes, type)) { | ||
| 91 | + throw new ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED(type); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + // `type` was the wrong value for this format. | ||
| 95 | + throw new ERR_IMPORT_ASSERTION_TYPE_FAILED(url, type); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + | ||
| 99 | + module.exports = { | ||
| 100 | + kImplicitAssertType, | ||
| 101 | + validateAssertions, | ||
| 102 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,14 +3,26 @@ | |||
| 3 | 3 | const { defaultGetFormat } = require('internal/modules/esm/get_format'); | |
| 4 | 4 | const { defaultGetSource } = require('internal/modules/esm/get_source'); | |
| 5 | 5 | const { translators } = require('internal/modules/esm/translators'); | |
| 6 | + const { validateAssertions } = require('internal/modules/esm/assert'); | ||
| 6 | 7 | ||
| 8 | + /** | ||
| 9 | + * Node.js default load hook. | ||
| 10 | + * @param {string} url | ||
| 11 | + * @param {object} context | ||
| 12 | + * @returns {object} | ||
| 13 | + */ | ||
| 7 | 14 | async function defaultLoad(url, context) { | |
| 8 | 15 | let { | |
| 9 | 16 | format, | |
| 10 | 17 | source, | |
| 11 | 18 | } = context; | |
| 19 | + const { importAssertions } = context; | ||
| 12 | 20 | ||
| 13 | - if (!translators.has(format)) format = defaultGetFormat(url); | ||
| 21 | + if (!format || !translators.has(format)) { | ||
| 22 | + format = defaultGetFormat(url); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + validateAssertions(url, format, importAssertions); | ||
| 14 | 26 | ||
| 15 | 27 | if ( | |
| 16 | 28 | format === 'builtin' || | |
| Back | FazBrowse Home | New Git URL |
0 commit comments