-
-
Notifications
You must be signed in to change notification settings - Fork 33.3k
Description
While working on #40250, the PR that added support for the import assertions syntax in general and required it for JSON imports, @aduh95 and I discussed a follow-up PR that added support for other formats. There are two in particular that we think should be added:
-
webassembly
: Animport
of a WebAssembly module would need the assertion just like JSON modules do:import './file.wasm' assert { type: 'webassembly' }
. This follows the examples in the import assertions proposal. (WebAssembly imports are currently flagged behind--experimental-wasm-modules
and I think this flag should remain, at least until it becomes clear how browsers will handle WebAssembly imports.) -
javascript
: Per the HTML spec, animport
statement with no type assertion impliesassert { type: 'javascript' }
. The explicit version should also be supported, though, because there are cases likeimport(url, { assert: { type: dynamicType } })
where it is useful for Node to accept an explicit assertion type for modules that don’t necessarily need one.
The ES module loader has five formats defined internally (builtin
, commonjs
, module
, json
, wasm
), each of which is mapped to either an assertion type (currently only 'json'
, for the json
format) or the “implicit type,” which currently means that an import assertion type isn’t allowed for that format. I propose that we map wasm
to 'webassembly'
; and that we map builtin
, commonjs
and module
to 'javascript'
. The 'javascript'
type could either be explicitly specified (import './file.js' assert { type: 'javascript' }
) or implied (import './file.js'
).
These changes will align Node with the HTML spec, which is more detailed than the TC39 import assertions proposal. While Node of course doesn’t need to follow both the TC39 and HTML specs, it would be risky to not do so; any ways in which we deviate from the HTML spec could lead to cases where users can’t write code that can run without modification in both platforms. One potential example is if we disallow type: 'webassembly'
and browsers require it, or vice versa. At least for the time being, until it becomes clear how import assertions shake out across the ecosystem, it seems prudent for Node’s default behavior to adhere to the most restrictive spec and for us to wait to relax our requirements until it’s clearly safe to do so. (I’m referring to the Node’s default ESM loader; user loaders can modify Node as they wish and violate the spec as they please.)
Another more-strict part of the HTML spec is that the assertion type is part of the module cache key. The TC39 spec proposal allows different ways to handle multiple imports of the same module with different assertions; the HTML spec team settled on this solution, and I think that Node should align with the HTML spec in order to have consistent behavior across platforms. What this means in practice is that assertion types cannot be optional, in the sense that an import without a declared type is treated as if it had included assert { type: 'javascript' }
; no other type can be implied. I wrote more about this in a suggestion for the import assertions proposal.
This also positions Node to support new module types in the future. The only other type that I’m aware of any browsers supporting is 'css'
, which I haven’t read discussion around Node supporting, but currently there is no way to import native (.node
) modules in ESM. This could be remedied by following the example of JSON and Wasm, by creating a new loader format and assertion type for such files. cc @MylesBorins
I’m opening this issue so that this thread can be the place for discussion of this proposal, so that we can limit the chatter on the PR that implements this to technical review of the code in that PR; “product” or “feature” debate should please happen here. cc @nodejs/modules @nodejs/loaders