Skip to content

Commit

Permalink
module: unflag import assertions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
aduh95 and GeoffreyBooth committed Oct 17, 2021
1 parent c0a7020 commit 381d23f
Show file tree
Hide file tree
Showing 41 changed files with 517 additions and 65 deletions.
25 changes: 25 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,14 @@ The JS execution context is not associated with a Node.js environment.
This may occur when Node.js is used as an embedded library and some hooks
for the JS engine are not set up properly.

<a id="ERR_FAILED_IMPORT_ASSERTION"></a>
### `ERR_FAILED_IMPORT_ASSERTION`
<!-- YAML
added: REPLACEME
-->

An import assertion has failed, preventing the specified module to be imported.

<a id="ERR_FALSY_VALUE_REJECTION"></a>
### `ERR_FALSY_VALUE_REJECTION`

Expand Down Expand Up @@ -1662,6 +1670,14 @@ for more information.

An invalid HTTP token was supplied.

<a id="ERR_INVALID_IMPORT_ASSERTION"></a>
### `ERR_INVALID_IMPORT_ASSERTION`
<!-- YAML
added: REPLACEME
-->

An import assertion is not supported by this version of Node.js.

<a id="ERR_INVALID_IP_ADDRESS"></a>
### `ERR_INVALID_IP_ADDRESS`

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

<a id="ERR_MISSING_IMPORT_ASSERTION"></a>
### `ERR_MISSING_IMPORT_ASSERTION`
<!-- YAML
added: REPLACEME
-->

An attempt was made to import a module without an assertion that requires
a specific import assertion to be loaded.

<a id="ERR_MISSING_OPTION"></a>
### `ERR_MISSING_OPTION`

Expand Down
35 changes: 33 additions & 2 deletions doc/api/esm.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<!-- YAML
added: v8.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39921
description: Add support for import assertions.
- version:
- REPLACEME
pr-url: https://github.com/nodejs/node/pull/37468
Expand Down Expand Up @@ -232,6 +235,25 @@ absolute URL strings.
import fs from 'node:fs/promises';
```

## Import assertions
<!-- YAML
added: REPLACEME
-->

The [Import Assertions proposal][] adds an inline syntax for module import
statements to pass on more information alongside the module specifier.

```js
import json from './foo.json' assert { type: "json" };
await import('foo.json', { assert: { type: "json" } });
```

Node.js supports the following `type` values:

| `type` | Resolves to |
| -------- | ---------------- |
| `"json"` | [JSON modules][] |

## Builtin modules

[Core modules][] provide named exports of their public API. A
Expand Down Expand Up @@ -522,9 +544,8 @@ same path.
Assuming an `index.mjs` with
<!-- eslint-skip -->
```js
import packageConfig from './package.json';
import packageConfig from './package.json' assert { type: 'json' };
```
The `--experimental-json-modules` flag is needed for the module
Expand Down Expand Up @@ -610,18 +631,26 @@ CommonJS modules loaded.
### Hooks
#### `resolve(specifier, context, defaultResolve)`
<!-- YAML
changes:
- version: REPLACEME
pr-url: TBD
description: Add support for import assertions.
-->
> Note: The loaders API is being redesigned. This hook may disappear or its
> signature may change. Do not rely on the API described below.
* `specifier` {string}
* `context` {Object}
* `conditions` {string[]}
* `importAssertions` {Object}
* `parentURL` {string|undefined}
* `defaultResolve` {Function} The Node.js default resolver.
* Returns: {Object}
* `format` {string|null|undefined}
`'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'`
* `importAssertions` {Object}
* `url` {string} The absolute url to the import target (such as `file://…`)

The `resolve` hook returns the resolved file URL for a given module specifier
Expand Down Expand Up @@ -1350,6 +1379,8 @@ success!
[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
[ECMAScript Top-Level `await` proposal]: https://github.com/tc39/proposal-top-level-await/
[ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration
[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
[JSON modules]: #json-modules
[Node.js Module Resolution Algorithm]: #resolver-algorithm-specification
[Terminology]: #terminology
[URL]: https://url.spec.whatwg.org/
Expand Down
9 changes: 9 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,9 @@ E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported',
RangeError);
E('ERR_EVAL_ESM_CANNOT_PRINT', '--print cannot be used with ESM input', Error);
E('ERR_EVENT_RECURSION', 'The event "%s" is already being dispatched', Error);
E('ERR_FAILED_IMPORT_ASSERTION', (request, key, expectedValue, actualValue) => {
return `Failed to load module "${request}", expected ${key} to be ${JSONStringify(expectedValue)}, got ${JSONStringify(actualValue)} instead`;
}, TypeError);
E('ERR_FALSY_VALUE_REJECTION', function(reason) {
this.reason = reason;
return 'Promise was rejected with falsy value';
Expand Down Expand Up @@ -1250,6 +1253,9 @@ E('ERR_INVALID_FILE_URL_HOST',
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError);
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError);
E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError);
E('ERR_INVALID_IMPORT_ASSERTION',
(type, value) => `Invalid ${JSONStringify(type)} import assertion: ${JSONStringify(value)}`,
TypeError);
E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError);
E('ERR_INVALID_MODULE_SPECIFIER', (request, reason, base = undefined) => {
return `Invalid module "${request}" ${reason}${base ?
Expand Down Expand Up @@ -1394,6 +1400,9 @@ E('ERR_MISSING_ARGS',
}
return `${msg} must be specified`;
}, TypeError);
E('ERR_MISSING_IMPORT_ASSERTION',
'Failed to load %s: Node.js requires modules of format "%s" to be loaded ' +
'using an assertion "%s" with value "%s"', TypeError);
E('ERR_MISSING_OPTION', '%s is required', TypeError);
E('ERR_MODULE_NOT_FOUND', (path, base, type = 'package') => {
return `Cannot find ${type} '${path}' imported from ${base}`;
Expand Down
10 changes: 6 additions & 4 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1015,9 +1015,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
filename,
lineOffset: 0,
displayErrors: true,
importModuleDynamically: async (specifier) => {
importModuleDynamically: async (specifier, _, importAssertions) => {
const loader = asyncESM.esmLoader;
return loader.import(specifier, normalizeReferrerURL(filename));
return loader.import(specifier, normalizeReferrerURL(filename),
importAssertions);
},
});
}
Expand All @@ -1030,9 +1031,10 @@ function wrapSafe(filename, content, cjsModuleInstance) {
'__dirname',
], {
filename,
importModuleDynamically(specifier) {
importModuleDynamically(specifier, _, importAssertions) {
const loader = asyncESM.esmLoader;
return loader.import(specifier, normalizeReferrerURL(filename));
return loader.import(specifier, normalizeReferrerURL(filename),
importAssertions);
},
});
} catch (err) {
Expand Down

0 comments on commit 381d23f

Please sign in to comment.