Skip to content

Commit 381d23f

Browse files
aduh95GeoffreyBooth
andcommitted
module: unflag import assertions
Unflag import assertions and remove possibility of importing JSON modules without using an assertion. Refs: nodejs#37375 (comment) Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent c0a7020 commit 381d23f

41 files changed

Lines changed: 517 additions & 65 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

doc/api/errors.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,14 @@ The JS execution context is not associated with a Node.js environment.
11111111
This may occur when Node.js is used as an embedded library and some hooks
11121112
for the JS engine are not set up properly.
11131113

1114+
<a id="ERR_FAILED_IMPORT_ASSERTION"></a>
1115+
### `ERR_FAILED_IMPORT_ASSERTION`
1116+
<!-- YAML
1117+
added: REPLACEME
1118+
-->
1119+
1120+
An import assertion has failed, preventing the specified module to be imported.
1121+
11141122
<a id="ERR_FALSY_VALUE_REJECTION"></a>
11151123
### `ERR_FALSY_VALUE_REJECTION`
11161124

@@ -1662,6 +1670,14 @@ for more information.
16621670

16631671
An invalid HTTP token was supplied.
16641672

1673+
<a id="ERR_INVALID_IMPORT_ASSERTION"></a>
1674+
### `ERR_INVALID_IMPORT_ASSERTION`
1675+
<!-- YAML
1676+
added: REPLACEME
1677+
-->
1678+
1679+
An import assertion is not supported by this version of Node.js.
1680+
16651681
<a id="ERR_INVALID_IP_ADDRESS"></a>
16661682
### `ERR_INVALID_IP_ADDRESS`
16671683

@@ -1913,6 +1929,15 @@ strict compliance with the API specification (which in some cases may accept
19131929
`func(undefined)` and `func()` are treated identically, and the
19141930
[`ERR_INVALID_ARG_TYPE`][] error code may be used instead.
19151931

1932+
<a id="ERR_MISSING_IMPORT_ASSERTION"></a>
1933+
### `ERR_MISSING_IMPORT_ASSERTION`
1934+
<!-- YAML
1935+
added: REPLACEME
1936+
-->
1937+
1938+
An attempt was made to import a module without an assertion that requires
1939+
a specific import assertion to be loaded.
1940+
19161941
<a id="ERR_MISSING_OPTION"></a>
19171942
### `ERR_MISSING_OPTION`
19181943

doc/api/esm.md

Lines changed: 33 additions & 2 deletions
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/39921
12+
description: Add support for import assertions.
1013
- version:
1114
- REPLACEME
1215
pr-url: https://github.com/nodejs/node/pull/37468
@@ -232,6 +235,25 @@ absolute URL strings.
232235
import fs from 'node:fs/promises';
233236
```
234237

238+
## Import assertions
239+
<!-- YAML
240+
added: REPLACEME
241+
-->
242+
243+
The [Import Assertions proposal][] adds an inline syntax for module import
244+
statements to pass on more information alongside the module specifier.
245+
246+
```js
247+
import json from './foo.json' assert { type: "json" };
248+
await import('foo.json', { assert: { type: "json" } });
249+
```
250+
251+
Node.js supports the following `type` values:
252+
253+
| `type` | Resolves to |
254+
| -------- | ---------------- |
255+
| `"json"` | [JSON modules][] |
256+
235257
## Builtin modules
236258

237259
[Core modules][] provide named exports of their public API. A
@@ -522,9 +544,8 @@ same path.
522544
523545
Assuming an `index.mjs` with
524546
525-
<!-- eslint-skip -->
526547
```js
527-
import packageConfig from './package.json';
548+
import packageConfig from './package.json' assert { type: 'json' };
528549
```
529550
530551
The `--experimental-json-modules` flag is needed for the module
@@ -610,18 +631,26 @@ CommonJS modules loaded.
610631
### Hooks
611632
612633
#### `resolve(specifier, context, defaultResolve)`
634+
<!-- YAML
635+
changes:
636+
- version: REPLACEME
637+
pr-url: TBD
638+
description: Add support for import assertions.
639+
-->
613640
614641
> Note: The loaders API is being redesigned. This hook may disappear or its
615642
> signature may change. Do not rely on the API described below.
616643
617644
* `specifier` {string}
618645
* `context` {Object}
619646
* `conditions` {string[]}
647+
* `importAssertions` {Object}
620648
* `parentURL` {string|undefined}
621649
* `defaultResolve` {Function} The Node.js default resolver.
622650
* Returns: {Object}
623651
* `format` {string|null|undefined}
624652
`'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'`
653+
* `importAssertions` {Object}
625654
* `url` {string} The absolute url to the import target (such as `file://…`)
626655

627656
The `resolve` hook returns the resolved file URL for a given module specifier
@@ -1350,6 +1379,8 @@ success!
13501379
[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
13511380
[ECMAScript Top-Level `await` proposal]: https://github.com/tc39/proposal-top-level-await/
13521381
[ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration
1382+
[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
1383+
[JSON modules]: #json-modules
13531384
[Node.js Module Resolution Algorithm]: #resolver-algorithm-specification
13541385
[Terminology]: #terminology
13551386
[URL]: https://url.spec.whatwg.org/

lib/internal/errors.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,9 @@ E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported',
953953
RangeError);
954954
E('ERR_EVAL_ESM_CANNOT_PRINT', '--print cannot be used with ESM input', Error);
955955
E('ERR_EVENT_RECURSION', 'The event "%s" is already being dispatched', Error);
956+
E('ERR_FAILED_IMPORT_ASSERTION', (request, key, expectedValue, actualValue) => {
957+
return `Failed to load module "${request}", expected ${key} to be ${JSONStringify(expectedValue)}, got ${JSONStringify(actualValue)} instead`;
958+
}, TypeError);
956959
E('ERR_FALSY_VALUE_REJECTION', function(reason) {
957960
this.reason = reason;
958961
return 'Promise was rejected with falsy value';
@@ -1250,6 +1253,9 @@ E('ERR_INVALID_FILE_URL_HOST',
12501253
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError);
12511254
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError);
12521255
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError);
1256+
E('ERR_INVALID_IMPORT_ASSERTION',
1257+
(type, value) => `Invalid ${JSONStringify(type)} import assertion: ${JSONStringify(value)}`,
1258+
TypeError);
12531259
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError);
12541260
E('ERR_INVALID_MODULE_SPECIFIER', (request, reason, base = undefined) => {
12551261
return `Invalid module "${request}" ${reason}${base ?
@@ -1394,6 +1400,9 @@ E('ERR_MISSING_ARGS',
13941400
}
13951401
return `${msg} must be specified`;
13961402
}, TypeError);
1403+
E('ERR_MISSING_IMPORT_ASSERTION',
1404+
'Failed to load %s: Node.js requires modules of format "%s" to be loaded ' +
1405+
'using an assertion "%s" with value "%s"', TypeError);
13971406
E('ERR_MISSING_OPTION', '%s is required', TypeError);
13981407
E('ERR_MODULE_NOT_FOUND', (path, base, type = 'package') => {
13991408
return `Cannot find ${type} '${path}' imported from ${base}`;

lib/internal/modules/cjs/loader.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,9 +1015,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10151015
filename,
10161016
lineOffset: 0,
10171017
displayErrors: true,
1018-
importModuleDynamically: async (specifier) => {
1018+
importModuleDynamically: async (specifier, _, importAssertions) => {
10191019
const loader = asyncESM.esmLoader;
1020-
return loader.import(specifier, normalizeReferrerURL(filename));
1020+
return loader.import(specifier, normalizeReferrerURL(filename),
1021+
importAssertions);
10211022
},
10221023
});
10231024
}
@@ -1030,9 +1031,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10301031
'__dirname',
10311032
], {
10321033
filename,
1033-
importModuleDynamically(specifier) {
1034+
importModuleDynamically(specifier, _, importAssertions) {
10341035
const loader = asyncESM.esmLoader;
1035-
return loader.import(specifier, normalizeReferrerURL(filename));
1036+
return loader.import(specifier, normalizeReferrerURL(filename),
1037+
importAssertions);
10361038
},
10371039
});
10381040
} catch (err) {

0 commit comments

Comments
 (0)