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 3c8aa21

Browse filesBrowse files
GeoffreyBoothtargos
authored andcommitted
module: import assertions improvements
PR-URL: #40785 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent b92416f commit 3c8aa21
Copy full SHA for 3c8aa21

File tree

Expand file treeCollapse file tree

6 files changed

+41
-31
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+41
-31
lines changed
Open diff view settings
Collapse file

‎doc/api/esm.md‎

Copy file name to clipboardExpand all lines: doc/api/esm.md
+10-4Lines changed: 10 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ import fs from 'node:fs/promises';
228228
added: v17.1.0
229229
-->
230230

231+
> Stability: 1 - Experimental
232+
231233
The [Import Assertions proposal][] adds an inline syntax for module import
232234
statements to pass on more information alongside the module specifier.
233235

@@ -238,11 +240,12 @@ const { default: barData } =
238240
await import('./bar.json', { assert: { type: 'json' } });
239241
```
240242

241-
Node.js supports the following `type` values:
243+
Node.js supports the following `type` values, for which the assertion is
244+
mandatory:
242245

243-
| `type` | Resolves to |
244-
| -------- | ---------------- |
245-
| `'json'` | [JSON modules][] |
246+
| Assertion `type` | Needed for |
247+
| ---------------- | ---------------- |
248+
| `'json'` | [JSON modules][] |
246249

247250
## Builtin modules
248251

@@ -553,6 +556,8 @@ node index.mjs # fails
553556
node --experimental-json-modules index.mjs # works
554557
```
555558
559+
The `assert { type: 'json' }` syntax is mandatory; see [Import Assertions][].
560+
556561
<i id="esm_experimental_wasm_modules"></i>
557562
558563
## Wasm modules
@@ -1390,6 +1395,7 @@ success!
13901395
[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
13911396
[ECMAScript Top-Level `await` proposal]: https://github.com/tc39/proposal-top-level-await/
13921397
[ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
1398+
[Import Assertions]: #import-assertions
13931399
[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
13941400
[JSON modules]: #json-modules
13951401
[Node.js Module Resolution Algorithm]: #resolver-algorithm-specification
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/assert.js
+23-15Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
'use strict';
22

33
const {
4+
ArrayPrototypeFilter,
45
ArrayPrototypeIncludes,
56
ObjectCreate,
67
ObjectValues,
78
ObjectPrototypeHasOwnProperty,
8-
Symbol,
99
} = primordials;
1010
const { validateString } = require('internal/validators');
1111

@@ -15,24 +15,32 @@ const {
1515
ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED,
1616
} = require('internal/errors').codes;
1717

18-
const kImplicitAssertType = Symbol('implicit assert type');
18+
// The HTML spec has an implied default type of `'javascript'`.
19+
const kImplicitAssertType = 'javascript';
1920

2021
/**
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}
22+
* Define a map of module formats to import assertion types (the value of
23+
* `type` in `assert { type: 'json' }`).
24+
* @type {Map<string, string>}
2425
*/
2526
const formatTypeMap = {
2627
'__proto__': null,
2728
'builtin': kImplicitAssertType,
2829
'commonjs': kImplicitAssertType,
2930
'json': 'json',
3031
'module': kImplicitAssertType,
31-
'wasm': kImplicitAssertType, // Should probably be 'webassembly' per https://github.com/tc39/proposal-import-assertions
32+
'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
3233
};
3334

34-
/** @type {Array<string, string | typeof kImplicitAssertType} */
35-
const supportedAssertionTypes = ObjectValues(formatTypeMap);
35+
/**
36+
* The HTML spec disallows the default type to be explicitly specified
37+
* (for now); so `import './file.js'` is okay but
38+
* `import './file.js' assert { type: 'javascript' }` throws.
39+
* @type {Array<string, string>}
40+
*/
41+
const supportedAssertionTypes = ArrayPrototypeFilter(
42+
ObjectValues(formatTypeMap),
43+
(type) => type !== kImplicitAssertType);
3644

3745

3846
/**
@@ -50,14 +58,10 @@ function validateAssertions(url, format,
5058

5159
switch (validType) {
5260
case undefined:
53-
// Ignore assertions for module types we don't recognize, to allow new
61+
// Ignore assertions for module formats we don't recognize, to allow new
5462
// formats in the future.
5563
return true;
5664

57-
case importAssertions.type:
58-
// The asserted type is the valid type for this format.
59-
return true;
60-
6165
case kImplicitAssertType:
6266
// This format doesn't allow an import assertion type, so the property
6367
// must not be set on the import assertions object.
@@ -66,9 +70,13 @@ function validateAssertions(url, format,
6670
}
6771
return handleInvalidType(url, importAssertions.type);
6872

73+
case importAssertions.type:
74+
// The asserted type is the valid type for this format.
75+
return true;
76+
6977
default:
7078
// There is an expected type for this format, but the value of
71-
// `importAssertions.type` was not it.
79+
// `importAssertions.type` might not have been it.
7280
if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) {
7381
// `type` wasn't specified at all.
7482
throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType);
@@ -86,7 +94,7 @@ function handleInvalidType(url, type) {
8694
// `type` might have not been a string.
8795
validateString(type, 'type');
8896

89-
// `type` was not one of the types we understand.
97+
// `type` might not have been one of the types we understand.
9098
if (!ArrayPrototypeIncludes(supportedAssertionTypes, type)) {
9199
throw new ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED(type);
92100
}
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/module_map.js
+3-6Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,17 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
1212
const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes;
1313
const { validateString } = require('internal/validators');
1414

15-
const validateAssertType = (type) =>
16-
type === kImplicitAssertType || validateString(type, 'type');
17-
1815
// Tracks the state of the loader-level module cache
1916
class ModuleMap extends SafeMap {
2017
constructor(i) { super(i); } // eslint-disable-line no-useless-constructor
2118
get(url, type = kImplicitAssertType) {
2219
validateString(url, 'url');
23-
validateAssertType(type);
20+
validateString(type, 'type');
2421
return super.get(url)?.[type];
2522
}
2623
set(url, type = kImplicitAssertType, job) {
2724
validateString(url, 'url');
28-
validateAssertType(type);
25+
validateString(type, 'type');
2926
if (job instanceof ModuleJob !== true &&
3027
typeof job !== 'function') {
3128
throw new ERR_INVALID_ARG_TYPE('job', 'ModuleJob', job);
@@ -39,7 +36,7 @@ class ModuleMap extends SafeMap {
3936
}
4037
has(url, type = kImplicitAssertType) {
4138
validateString(url, 'url');
42-
validateAssertType(type);
39+
validateString(type, 'type');
4340
return super.get(url)?.[type] !== undefined;
4441
}
4542
}
Collapse file

‎test/es-module/test-esm-import-assertion-errors.js‎

Copy file name to clipboardExpand all lines: test/es-module/test-esm-import-assertion-errors.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ async function test() {
2525
);
2626

2727
await rejects(
28-
import('data:text/javascript,', { assert: { type: 'unsupported' } }),
28+
import(jsModuleDataUrl, { assert: { type: 'unsupported' } }),
2929
{ code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' }
3030
);
3131

Collapse file

‎test/es-module/test-esm-import-assertion-validation.js‎

Copy file name to clipboardExpand all lines: test/es-module/test-esm-import-assertion-validation.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ assert.throws(() => validateAssertions(url, 'module', { type: 'json' }), {
2222
code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED',
2323
});
2424

25-
// This should be allowed according to HTML spec. Let's keep it disabled
26-
// until WASM module import is sorted out.
25+
// The HTML spec specifically disallows this for now, while Wasm module import
26+
// and whether it will require a type assertion is still an open question.
2727
assert.throws(() => validateAssertions(url, 'module', { type: 'javascript' }), {
2828
code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED',
2929
});
Collapse file

‎test/es-module/test-esm-loader-modulemap.js‎

Copy file name to clipboardExpand all lines: test/es-module/test-esm-loader-modulemap.js
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const { strictEqual, throws } = require('assert');
77
const { ESMLoader } = require('internal/modules/esm/loader');
88
const ModuleMap = require('internal/modules/esm/module_map');
99
const ModuleJob = require('internal/modules/esm/module_job');
10-
const { kImplicitAssertType } = require('internal/modules/esm/assert');
1110
const createDynamicModule = require(
1211
'internal/modules/esm/create_dynamic_module');
1312

@@ -38,14 +37,14 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module,
3837
strictEqual(moduleMap.get(jsonModuleDataUrl, 'json'), jsonModuleJob);
3938

4039
strictEqual(moduleMap.has(jsModuleDataUrl), true);
41-
strictEqual(moduleMap.has(jsModuleDataUrl, kImplicitAssertType), true);
40+
strictEqual(moduleMap.has(jsModuleDataUrl, 'javascript'), true);
4241
strictEqual(moduleMap.has(jsonModuleDataUrl, 'json'), true);
4342

4443
strictEqual(moduleMap.has('unknown'), false);
4544

4645
// The types must match
4746
strictEqual(moduleMap.has(jsModuleDataUrl, 'json'), false);
48-
strictEqual(moduleMap.has(jsonModuleDataUrl, kImplicitAssertType), false);
47+
strictEqual(moduleMap.has(jsonModuleDataUrl, 'javascript'), false);
4948
strictEqual(moduleMap.has(jsonModuleDataUrl), false);
5049
strictEqual(moduleMap.has(jsModuleDataUrl, 'unknown'), false);
5150
strictEqual(moduleMap.has(jsonModuleDataUrl, 'unknown'), false);

0 commit comments

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