Support emitting direct imports in wasm files #1689
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by also
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
The logic in
wasm-bindgen
where it gracefully handles (to somedegree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
Handling imports in the wasm module not registered with
#[wasm_bindgen]
has become more strict. Previously these importswere basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
bundler
- not much has changed here. Previously these ignoredimports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
web
- previously the ignored imports would likely causeinstantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
import
directive. This matches what we want for the direct importfunctionality, and is also largely what we want for modules in
general.
nodejs
- previously ignored imports were handled in thetranslation shim for Node to generate
require
statements, so theywere actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a
require
.no-modules
- this is very similar to theweb
target wherepreviously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from
#[wasm_bindgen]
with theno-modules
output type, because we don't know how to handle the imports.
Note that this touches on Option to specify extra javascript imports required when instantiating WASM Module #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and
wasm-bindgen
is just a polyfill for webstandards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
wasm-bindgen
, but the mainwasm
test suite has many instances ofthis path being taken, for example having imports like: