2018-07-19 14:57:04 -05:00
|
|
|
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-cli-support/0.2")]
|
|
|
|
|
2019-11-04 11:35:28 -06:00
|
|
|
use anyhow::{bail, Context, Error};
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
2018-08-15 17:52:26 -07:00
|
|
|
use std::env;
|
2018-07-25 16:06:47 -07:00
|
|
|
use std::fs;
|
2018-07-25 15:49:50 -07:00
|
|
|
use std::mem;
|
2017-12-24 15:32:40 -08:00
|
|
|
use std::path::{Path, PathBuf};
|
2018-08-26 15:43:33 -07:00
|
|
|
use std::str;
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
use walrus::Module;
|
2017-12-14 19:31:01 -08:00
|
|
|
|
2019-05-31 10:54:03 -07:00
|
|
|
mod anyref;
|
2018-08-26 15:43:33 -07:00
|
|
|
mod decode;
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
mod descriptor;
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
mod descriptors;
|
2019-06-13 08:30:06 -07:00
|
|
|
mod intrinsic;
|
2018-06-27 22:42:34 -07:00
|
|
|
mod js;
|
2019-12-03 11:16:44 -06:00
|
|
|
mod multivalue;
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
mod throw2unreachable;
|
2018-01-29 21:20:38 -08:00
|
|
|
pub mod wasm2es6js;
|
2019-12-03 11:16:44 -06:00
|
|
|
mod wit;
|
2017-12-18 12:39:14 -08:00
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
pub struct Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
input: Input,
|
2018-12-04 21:35:05 -05:00
|
|
|
out_name: Option<String>,
|
2019-02-25 11:11:30 -08:00
|
|
|
mode: OutputMode,
|
2017-12-19 09:25:41 -08:00
|
|
|
debug: bool,
|
2018-01-29 21:20:38 -08:00
|
|
|
typescript: bool,
|
2018-04-11 11:43:18 -07:00
|
|
|
demangle: bool,
|
2018-07-13 08:10:51 -07:00
|
|
|
keep_debug: bool,
|
2018-11-09 07:45:19 -08:00
|
|
|
remove_name_section: bool,
|
2019-02-14 10:08:24 -08:00
|
|
|
remove_producers_section: bool,
|
2018-11-28 09:25:51 -08:00
|
|
|
emit_start: bool,
|
2019-05-26 09:30:33 -05:00
|
|
|
// Experimental support for weakrefs, an upcoming ECMAScript feature.
|
2018-08-15 17:52:26 -07:00
|
|
|
// Currently only enable-able through an env var.
|
|
|
|
weak_refs: bool,
|
2019-07-23 07:30:32 -07:00
|
|
|
// Support for the wasm threads proposal, transforms the wasm module to be
|
|
|
|
// "ready to be instantiated on any thread"
|
|
|
|
threads: wasm_bindgen_threads_xform::Config,
|
2018-10-18 08:43:36 -07:00
|
|
|
anyref: bool,
|
2019-09-10 11:19:51 -07:00
|
|
|
multi_value: bool,
|
2019-06-25 01:21:38 -07:00
|
|
|
wasm_interface_types: bool,
|
2019-02-20 08:39:46 -08:00
|
|
|
encode_into: EncodeInto,
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2019-07-29 13:32:18 -07:00
|
|
|
pub struct Output {
|
|
|
|
module: walrus::Module,
|
|
|
|
stem: String,
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
generated: Generated,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Generated {
|
|
|
|
InterfaceTypes,
|
|
|
|
Js(JsGenerated),
|
|
|
|
}
|
|
|
|
|
|
|
|
struct JsGenerated {
|
|
|
|
mode: OutputMode,
|
2019-07-29 13:32:18 -07:00
|
|
|
js: String,
|
|
|
|
ts: String,
|
|
|
|
snippets: HashMap<String, Vec<String>>,
|
|
|
|
local_modules: HashMap<String, String>,
|
|
|
|
npm_dependencies: HashMap<String, (PathBuf, String)>,
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
typescript: bool,
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2019-02-25 11:11:30 -08:00
|
|
|
enum OutputMode {
|
2019-03-07 07:33:40 -08:00
|
|
|
Bundler { browser_only: bool },
|
|
|
|
Web,
|
2019-02-25 11:11:30 -08:00
|
|
|
NoModules { global: String },
|
|
|
|
Node { experimental_modules: bool },
|
|
|
|
}
|
|
|
|
|
2018-07-25 15:49:50 -07:00
|
|
|
enum Input {
|
|
|
|
Path(PathBuf),
|
|
|
|
Module(Module, String),
|
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
2019-02-20 08:39:46 -08:00
|
|
|
pub enum EncodeInto {
|
|
|
|
Test,
|
|
|
|
Always,
|
|
|
|
Never,
|
|
|
|
}
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
impl Bindgen {
|
|
|
|
pub fn new() -> Bindgen {
|
2019-06-25 01:21:38 -07:00
|
|
|
let anyref = env::var("WASM_BINDGEN_ANYREF").is_ok();
|
|
|
|
let wasm_interface_types = env::var("WASM_INTERFACE_TYPES").is_ok();
|
2019-09-10 11:19:51 -07:00
|
|
|
let multi_value = env::var("WASM_BINDGEN_MULTI_VALUE").is_ok();
|
2017-12-14 19:31:01 -08:00
|
|
|
Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
input: Input::None,
|
2018-12-04 21:35:05 -05:00
|
|
|
out_name: None,
|
2019-03-19 11:25:13 -07:00
|
|
|
mode: OutputMode::Bundler {
|
|
|
|
browser_only: false,
|
|
|
|
},
|
2017-12-19 09:25:41 -08:00
|
|
|
debug: false,
|
2018-01-29 21:20:38 -08:00
|
|
|
typescript: false,
|
2018-04-11 11:43:18 -07:00
|
|
|
demangle: true,
|
2018-07-13 08:10:51 -07:00
|
|
|
keep_debug: false,
|
2018-11-09 07:45:19 -08:00
|
|
|
remove_name_section: false,
|
2019-02-15 11:22:46 -08:00
|
|
|
remove_producers_section: false,
|
2018-11-28 09:25:51 -08:00
|
|
|
emit_start: true,
|
2018-08-15 17:52:26 -07:00
|
|
|
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
|
2018-10-04 20:00:23 -07:00
|
|
|
threads: threads_config(),
|
2019-06-25 01:21:38 -07:00
|
|
|
anyref: anyref || wasm_interface_types,
|
2019-10-03 12:57:26 -07:00
|
|
|
multi_value: multi_value || wasm_interface_types,
|
2019-06-25 01:21:38 -07:00
|
|
|
wasm_interface_types,
|
2019-02-20 08:39:46 -08:00
|
|
|
encode_into: EncodeInto::Test,
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn input_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
self.input = Input::Path(path.as_ref().to_path_buf());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-12-04 21:35:05 -05:00
|
|
|
pub fn out_name(&mut self, name: &str) -> &mut Bindgen {
|
|
|
|
self.out_name = Some(name.to_string());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-07-25 15:49:50 -07:00
|
|
|
/// Explicitly specify the already parsed input module.
|
2018-10-08 10:01:53 -07:00
|
|
|
pub fn input_module(&mut self, name: &str, module: Module) -> &mut Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
let name = name.to_string();
|
2018-10-08 10:01:53 -07:00
|
|
|
self.input = Input::Module(module, name);
|
|
|
|
return self;
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
fn switch_mode(&mut self, mode: OutputMode, flag: &str) -> Result<(), Error> {
|
|
|
|
match self.mode {
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Bundler { .. } => self.mode = mode,
|
2019-02-25 11:11:30 -08:00
|
|
|
_ => bail!(
|
|
|
|
"cannot specify `{}` with another output mode already specified",
|
|
|
|
flag
|
|
|
|
),
|
|
|
|
}
|
|
|
|
Ok(())
|
2017-12-14 21:55:21 -08:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
pub fn nodejs(&mut self, node: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if node {
|
|
|
|
self.switch_mode(
|
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules: false,
|
|
|
|
},
|
2019-03-19 11:25:13 -07:00
|
|
|
"--target nodejs",
|
2019-02-25 11:11:30 -08:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
Ok(self)
|
2018-07-04 22:37:09 -05:00
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
pub fn nodejs_experimental_modules(&mut self, node: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if node {
|
|
|
|
self.switch_mode(
|
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules: true,
|
|
|
|
},
|
|
|
|
"--nodejs-experimental-modules",
|
|
|
|
)?;
|
|
|
|
}
|
|
|
|
Ok(self)
|
2018-03-07 08:50:56 -08:00
|
|
|
}
|
|
|
|
|
2019-03-19 11:25:13 -07:00
|
|
|
pub fn bundler(&mut self, bundler: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if bundler {
|
|
|
|
self.switch_mode(
|
|
|
|
OutputMode::Bundler {
|
|
|
|
browser_only: false,
|
|
|
|
},
|
|
|
|
"--target bundler",
|
|
|
|
)?;
|
|
|
|
}
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
2019-03-07 07:33:40 -08:00
|
|
|
pub fn web(&mut self, web: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if web {
|
2019-03-19 11:25:13 -07:00
|
|
|
self.switch_mode(OutputMode::Web, "--target web")?;
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
|
|
|
Ok(self)
|
2018-04-04 20:06:53 +05:45
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
pub fn no_modules(&mut self, no_modules: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if no_modules {
|
|
|
|
self.switch_mode(
|
|
|
|
OutputMode::NoModules {
|
|
|
|
global: "wasm_bindgen".to_string(),
|
|
|
|
},
|
2019-03-19 11:25:13 -07:00
|
|
|
"--target no-modules",
|
2019-02-25 11:11:30 -08:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
2019-03-07 07:33:40 -08:00
|
|
|
pub fn browser(&mut self, browser: bool) -> Result<&mut Bindgen, Error> {
|
|
|
|
if browser {
|
|
|
|
match &mut self.mode {
|
|
|
|
OutputMode::Bundler { browser_only } => *browser_only = true,
|
|
|
|
_ => bail!("cannot specify `--browser` with other output types"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
pub fn no_modules_global(&mut self, name: &str) -> Result<&mut Bindgen, Error> {
|
|
|
|
match &mut self.mode {
|
|
|
|
OutputMode::NoModules { global } => *global = name.to_string(),
|
2019-03-19 11:25:13 -07:00
|
|
|
_ => bail!("can only specify `--no-modules-global` with `--target no-modules`"),
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
|
|
|
Ok(self)
|
2018-04-19 13:33:58 -07:00
|
|
|
}
|
|
|
|
|
2017-12-19 09:25:41 -08:00
|
|
|
pub fn debug(&mut self, debug: bool) -> &mut Bindgen {
|
|
|
|
self.debug = debug;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-29 21:20:38 -08:00
|
|
|
pub fn typescript(&mut self, typescript: bool) -> &mut Bindgen {
|
|
|
|
self.typescript = typescript;
|
2017-12-24 15:32:40 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-04-11 11:43:18 -07:00
|
|
|
pub fn demangle(&mut self, demangle: bool) -> &mut Bindgen {
|
|
|
|
self.demangle = demangle;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-07-13 08:10:51 -07:00
|
|
|
pub fn keep_debug(&mut self, keep_debug: bool) -> &mut Bindgen {
|
|
|
|
self.keep_debug = keep_debug;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-11-09 07:45:19 -08:00
|
|
|
pub fn remove_name_section(&mut self, remove: bool) -> &mut Bindgen {
|
|
|
|
self.remove_name_section = remove;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-02-14 10:08:24 -08:00
|
|
|
pub fn remove_producers_section(&mut self, remove: bool) -> &mut Bindgen {
|
|
|
|
self.remove_producers_section = remove;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-11-28 09:25:51 -08:00
|
|
|
pub fn emit_start(&mut self, emit: bool) -> &mut Bindgen {
|
|
|
|
self.emit_start = emit;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-02-20 08:39:46 -08:00
|
|
|
pub fn encode_into(&mut self, mode: EncodeInto) -> &mut Bindgen {
|
|
|
|
self.encode_into = mode;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-29 21:20:38 -08:00
|
|
|
pub fn generate<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
|
2019-07-29 13:32:18 -07:00
|
|
|
self.generate_output()?.emit(path.as_ref())
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2019-07-29 13:32:18 -07:00
|
|
|
pub fn generate_output(&mut self) -> Result<Output, Error> {
|
2018-07-25 15:49:50 -07:00
|
|
|
let (mut module, stem) = match self.input {
|
|
|
|
Input::None => bail!("must have an input by now"),
|
|
|
|
Input::Module(ref mut m, ref name) => {
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
let blank_module = Module::default();
|
2018-07-25 15:49:50 -07:00
|
|
|
(mem::replace(m, blank_module), &name[..])
|
|
|
|
}
|
|
|
|
Input::Path(ref path) => {
|
2019-12-04 22:39:57 -06:00
|
|
|
let wasm = wit_text::parse_file(&path)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to read `{}`", path.display()))?;
|
2019-12-04 22:39:57 -06:00
|
|
|
wit_validator::validate(&wasm)
|
|
|
|
.with_context(|| format!("failed to validate `{}`", path.display()))?;
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
let module = walrus::ModuleConfig::new()
|
|
|
|
// Skip validation of the module as LLVM's output is
|
|
|
|
// generally already well-formed and so we won't gain much
|
|
|
|
// from re-validating. Additionally LLVM's current output
|
|
|
|
// for threads includes atomic instructions but doesn't
|
|
|
|
// include shared memory, so it fails that part of
|
|
|
|
// validation!
|
|
|
|
.strict_validate(false)
|
2019-02-14 06:35:40 -08:00
|
|
|
.generate_dwarf(self.keep_debug)
|
|
|
|
.generate_name_section(!self.remove_name_section)
|
2019-02-14 10:08:24 -08:00
|
|
|
.generate_producers_section(!self.remove_producers_section)
|
2019-12-03 11:16:44 -06:00
|
|
|
.on_parse(wit_walrus::on_parse)
|
2019-12-04 22:39:57 -06:00
|
|
|
.parse(&wasm)
|
2018-07-25 15:49:50 -07:00
|
|
|
.context("failed to parse input file as wasm")?;
|
2018-12-04 21:35:05 -05:00
|
|
|
let stem = match &self.out_name {
|
|
|
|
Some(name) => &name,
|
|
|
|
None => path.file_stem().unwrap().to_str().unwrap(),
|
|
|
|
};
|
2018-07-25 15:49:50 -07:00
|
|
|
(module, stem)
|
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
};
|
2018-10-18 08:43:36 -07:00
|
|
|
|
|
|
|
// This isn't the hardest thing in the world too support but we
|
|
|
|
// basically don't know how to rationalize #[wasm_bindgen(start)] and
|
|
|
|
// the actual `start` function if present. Figure this out later if it
|
|
|
|
// comes up, but otherwise we should continue to be compatible with
|
|
|
|
// LLVM's output today.
|
|
|
|
//
|
|
|
|
// Note that start function handling in `js/mod.rs` will need to be
|
|
|
|
// updated as well, because `#[wasm_bindgen(start)]` is inserted *after*
|
|
|
|
// a module's start function, if any, because we assume start functions
|
|
|
|
// only show up when injected on behalf of wasm-bindgen's passes.
|
|
|
|
if module.start.is_some() {
|
2019-02-25 11:11:30 -08:00
|
|
|
bail!(
|
|
|
|
"wasm-bindgen is currently incompatible with modules that \
|
|
|
|
already have a start function"
|
|
|
|
);
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
|
|
|
|
2019-08-12 11:28:37 -07:00
|
|
|
self.threads
|
|
|
|
.run(&mut module)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| "failed to prepare module for threading")?;
|
2018-10-04 20:00:23 -07:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
// If requested, turn all mangled symbols into prettier unmangled
|
|
|
|
// symbols with the help of `rustc-demangle`.
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
if self.demangle {
|
|
|
|
demangle(&mut module);
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
unexported_unused_lld_things(&mut module);
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
// We're making quite a few changes, list ourselves as a producer.
|
|
|
|
module
|
|
|
|
.producers
|
|
|
|
.add_processed_by("wasm-bindgen", &wasm_bindgen_shared::version());
|
|
|
|
|
|
|
|
// Learn about the type signatures of all wasm-bindgen imports and
|
|
|
|
// exports by executing `__wbindgen_describe_*` functions. This'll
|
|
|
|
// effectively move all the descriptor functions to their own custom
|
|
|
|
// sections.
|
|
|
|
descriptors::execute(&mut module)?;
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
// Process and remove our raw custom sections emitted by the
|
|
|
|
// #[wasm_bindgen] macro and the compiler. In their stead insert a
|
2019-12-03 11:16:44 -06:00
|
|
|
// forward-compatible wasm interface types section as well as an
|
|
|
|
// auxiliary section for all sorts of miscellaneous information and
|
|
|
|
// features #[wasm_bindgen] supports that aren't covered by wasm
|
|
|
|
// interface types.
|
|
|
|
wit::process(
|
2019-09-10 11:20:19 -07:00
|
|
|
&mut module,
|
|
|
|
self.anyref,
|
|
|
|
self.wasm_interface_types,
|
|
|
|
self.emit_start,
|
|
|
|
)?;
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
|
2019-06-04 09:18:48 -07:00
|
|
|
// Now that we've got type information from the webidl processing pass,
|
|
|
|
// touch up the output of rustc to insert anyref shims where necessary.
|
|
|
|
// This is only done if the anyref pass is enabled, which it's
|
|
|
|
// currently off-by-default since `anyref` is still in development in
|
|
|
|
// engines.
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
//
|
|
|
|
// If the anyref pass isn't necessary, then we blanket delete the
|
|
|
|
// export of all our anyref intrinsics which will get cleaned up in the
|
|
|
|
// GC pass before JS generation.
|
2019-05-31 10:54:03 -07:00
|
|
|
if self.anyref {
|
2019-12-03 11:16:44 -06:00
|
|
|
anyref::process(&mut module)?;
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
} else {
|
|
|
|
let ids = module
|
|
|
|
.exports
|
|
|
|
.iter()
|
|
|
|
.filter(|e| e.name.starts_with("__anyref"))
|
|
|
|
.map(|e| e.id())
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
for id in ids {
|
|
|
|
module.exports.delete(id);
|
|
|
|
}
|
2019-05-31 10:54:03 -07:00
|
|
|
}
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
// If wasm interface types are enabled then the `__wbindgen_throw`
|
|
|
|
// intrinsic isn't available but it may be used by our runtime, so
|
|
|
|
// change all calls to this function to calls to `unreachable` instead.
|
|
|
|
// See more documentation in the pass documentation itself.
|
|
|
|
if self.wasm_interface_types {
|
|
|
|
throw2unreachable::run(&mut module);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Using all of our metadata convert our module to a multi-value using
|
|
|
|
// module if applicable.
|
|
|
|
if self.multi_value {
|
|
|
|
if !self.wasm_interface_types {
|
|
|
|
anyhow::bail!(
|
|
|
|
"Wasm multi-value is currently only available when \
|
|
|
|
Wasm interface types is also enabled"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
multivalue::run(&mut module)
|
|
|
|
.context("failed to transform return pointers into multi-value Wasm")?;
|
|
|
|
}
|
|
|
|
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
// We've done a whole bunch of transformations to the wasm module, many
|
|
|
|
// of which leave "garbage" lying around, so let's prune out all our
|
|
|
|
// unnecessary things here.
|
|
|
|
gc_module_and_adapters(&mut module);
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
// We're ready for the final emission passes now. If we're in wasm
|
|
|
|
// interface types mode then we execute the various passes there and
|
|
|
|
// generate a valid interface typess section into the wasm module.
|
|
|
|
//
|
|
|
|
// Otherwise we execute the JS generation passes to actually emit
|
|
|
|
// JS/TypeScript/etc. The output here is unused in wasm interfac
|
|
|
|
let generated = if self.wasm_interface_types {
|
|
|
|
wit::section::add(&mut module)
|
|
|
|
.context("failed to generate a standard interface types section")?;
|
|
|
|
Generated::InterfaceTypes
|
|
|
|
} else {
|
|
|
|
let aux = module
|
|
|
|
.customs
|
|
|
|
.delete_typed::<wit::WasmBindgenAux>()
|
|
|
|
.expect("aux section should be present");
|
|
|
|
let adapters = module
|
|
|
|
.customs
|
|
|
|
.delete_typed::<wit::NonstandardWitSection>()
|
|
|
|
.unwrap();
|
2019-12-03 11:16:44 -06:00
|
|
|
let mut cx = js::Context::new(&mut module, self, &adapters, &aux)?;
|
|
|
|
cx.generate()?;
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let (js, ts) = cx.finalize(stem)?;
|
|
|
|
Generated::Js(JsGenerated {
|
|
|
|
snippets: aux.snippets.clone(),
|
|
|
|
local_modules: aux.local_modules.clone(),
|
|
|
|
mode: self.mode.clone(),
|
|
|
|
typescript: self.typescript,
|
|
|
|
npm_dependencies: cx.npm_dependencies.clone(),
|
|
|
|
js,
|
|
|
|
ts,
|
|
|
|
})
|
2018-02-06 15:52:44 -08:00
|
|
|
};
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2019-07-29 13:32:18 -07:00
|
|
|
Ok(Output {
|
|
|
|
module,
|
|
|
|
stem: stem.to_string(),
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
generated,
|
2019-07-29 13:32:18 -07:00
|
|
|
})
|
2018-03-29 01:47:44 -07:00
|
|
|
}
|
Support emitting direct imports in wasm files
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 some
degree) 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 imports
were 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 ignored
imports 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 cause
instantiation 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 import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were 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 the `web` target where
previously 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 the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #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 web
standards 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 main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
|
|
|
|
fn local_module_name(&self, module: &str) -> String {
|
|
|
|
format!("./snippets/{}", module)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inline_js_module_name(
|
|
|
|
&self,
|
|
|
|
unique_crate_identifier: &str,
|
|
|
|
snippet_idx_in_crate: usize,
|
|
|
|
) -> String {
|
|
|
|
format!(
|
|
|
|
"./snippets/{}/inline{}.js",
|
|
|
|
unique_crate_identifier, snippet_idx_in_crate,
|
|
|
|
)
|
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2018-06-15 12:55:37 -05:00
|
|
|
fn reset_indentation(s: &str) -> String {
|
2018-07-09 07:44:41 -07:00
|
|
|
let mut indent: u32 = 0;
|
|
|
|
let mut dst = String::new();
|
2018-06-15 12:55:37 -05:00
|
|
|
|
2018-07-09 07:44:41 -07:00
|
|
|
for line in s.lines() {
|
|
|
|
let line = line.trim();
|
2018-07-09 14:55:25 -05:00
|
|
|
if line.starts_with('}') || (line.ends_with('}') && !line.starts_with('*')) {
|
2018-07-09 07:44:41 -07:00
|
|
|
indent = indent.saturating_sub(1);
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
2018-09-26 08:26:00 -07:00
|
|
|
let extra = if line.starts_with(':') || line.starts_with('?') {
|
|
|
|
1
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
2018-09-13 22:13:07 -07:00
|
|
|
if !line.is_empty() {
|
|
|
|
for _ in 0..indent + extra {
|
|
|
|
dst.push_str(" ");
|
|
|
|
}
|
|
|
|
dst.push_str(line);
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
2018-07-09 07:44:41 -07:00
|
|
|
dst.push_str("\n");
|
|
|
|
if line.ends_with('{') {
|
|
|
|
indent += 1;
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
|
|
|
}
|
2018-09-26 08:26:00 -07:00
|
|
|
return dst;
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
2018-10-04 20:00:23 -07:00
|
|
|
|
|
|
|
// Eventually these will all be CLI options, but while they're unstable features
|
|
|
|
// they're left as environment variables. We don't guarantee anything about
|
|
|
|
// backwards-compatibility with these options.
|
2019-07-23 07:30:32 -07:00
|
|
|
fn threads_config() -> wasm_bindgen_threads_xform::Config {
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
let mut cfg = wasm_bindgen_threads_xform::Config::new();
|
2018-10-04 20:00:23 -07:00
|
|
|
if let Ok(s) = env::var("WASM_BINDGEN_THREADS_MAX_MEMORY") {
|
|
|
|
cfg.maximum_memory(s.parse().unwrap());
|
|
|
|
}
|
|
|
|
if let Ok(s) = env::var("WASM_BINDGEN_THREADS_STACK_SIZE") {
|
|
|
|
cfg.thread_stack_size(s.parse().unwrap());
|
|
|
|
}
|
2019-07-23 07:30:32 -07:00
|
|
|
cfg
|
2018-10-04 20:00:23 -07:00
|
|
|
}
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
|
|
|
|
fn demangle(module: &mut Module) {
|
|
|
|
for func in module.funcs.iter_mut() {
|
|
|
|
let name = match &func.name {
|
|
|
|
Some(name) => name,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
if let Ok(sym) = rustc_demangle::try_demangle(name) {
|
|
|
|
func.name = Some(sym.to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-25 11:11:30 -08:00
|
|
|
|
|
|
|
impl OutputMode {
|
2019-07-29 13:32:18 -07:00
|
|
|
fn uses_es_modules(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
OutputMode::Bundler { .. }
|
|
|
|
| OutputMode::Web
|
|
|
|
| OutputMode::Node {
|
|
|
|
experimental_modules: true,
|
|
|
|
} => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-25 11:11:30 -08:00
|
|
|
fn nodejs_experimental_modules(&self) -> bool {
|
|
|
|
match self {
|
2019-03-05 14:53:14 -08:00
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules,
|
|
|
|
} => *experimental_modules,
|
2019-02-25 11:11:30 -08:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn nodejs(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
OutputMode::Node { .. } => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn no_modules(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
OutputMode::NoModules { .. } => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn always_run_in_browser(&self) -> bool {
|
|
|
|
match self {
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Web => true,
|
2019-02-25 11:11:30 -08:00
|
|
|
OutputMode::NoModules { .. } => true,
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Bundler { browser_only } => *browser_only,
|
2019-02-25 11:11:30 -08:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-07 07:33:40 -08:00
|
|
|
fn web(&self) -> bool {
|
2019-02-25 11:11:30 -08:00
|
|
|
match self {
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Web => true,
|
2019-02-25 11:11:30 -08:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2019-02-27 12:20:33 -08:00
|
|
|
|
|
|
|
fn bundler(&self) -> bool {
|
|
|
|
match self {
|
2019-02-28 11:37:08 -08:00
|
|
|
OutputMode::Bundler { .. } => true,
|
2019-02-27 12:20:33 -08:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
|
|
|
|
/// Remove a number of internal exports that are synthesized by Rust's linker,
|
|
|
|
/// LLD. These exports aren't typically ever needed and just add extra space to
|
|
|
|
/// the binary.
|
|
|
|
fn unexported_unused_lld_things(module: &mut Module) {
|
|
|
|
let mut to_remove = Vec::new();
|
|
|
|
for export in module.exports.iter() {
|
|
|
|
match export.name.as_str() {
|
|
|
|
"__heap_base" | "__data_end" | "__indirect_function_table" => {
|
|
|
|
to_remove.push(export.id());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for id in to_remove {
|
|
|
|
module.exports.delete(id);
|
|
|
|
}
|
|
|
|
}
|
2019-07-29 13:32:18 -07:00
|
|
|
|
|
|
|
impl Output {
|
|
|
|
pub fn js(&self) -> &str {
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
match &self.generated {
|
|
|
|
Generated::InterfaceTypes => panic!("no js with interface types output"),
|
|
|
|
Generated::Js(gen) => &gen.js,
|
|
|
|
}
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wasm(&self) -> &walrus::Module {
|
|
|
|
&self.module
|
|
|
|
}
|
|
|
|
|
2019-11-19 07:48:34 -08:00
|
|
|
pub fn wasm_mut(&mut self) -> &mut walrus::Module {
|
|
|
|
&mut self.module
|
|
|
|
}
|
|
|
|
|
2019-11-04 11:35:28 -06:00
|
|
|
pub fn emit(&mut self, out_dir: impl AsRef<Path>) -> Result<(), Error> {
|
2019-07-29 13:32:18 -07:00
|
|
|
self._emit(out_dir.as_ref())
|
|
|
|
}
|
|
|
|
|
2019-11-04 11:35:28 -06:00
|
|
|
fn _emit(&mut self, out_dir: &Path) -> Result<(), Error> {
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let wasm_name = match &self.generated {
|
|
|
|
Generated::InterfaceTypes => self.stem.clone(),
|
|
|
|
Generated::Js(_) => format!("{}_bg", self.stem),
|
2019-06-25 01:21:38 -07:00
|
|
|
};
|
2019-09-10 11:20:19 -07:00
|
|
|
let wasm_path = out_dir.join(wasm_name).with_extension("wasm");
|
2019-06-25 01:21:38 -07:00
|
|
|
fs::create_dir_all(out_dir)?;
|
2019-09-10 11:34:45 -07:00
|
|
|
let wasm_bytes = self.module.emit_wasm();
|
2019-06-25 01:21:38 -07:00
|
|
|
fs::write(&wasm_path, wasm_bytes)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", wasm_path.display()))?;
|
2019-06-25 01:21:38 -07:00
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let gen = match &self.generated {
|
|
|
|
Generated::InterfaceTypes => return Ok(()),
|
|
|
|
Generated::Js(gen) => gen,
|
|
|
|
};
|
2019-06-25 01:21:38 -07:00
|
|
|
|
2019-07-29 13:32:18 -07:00
|
|
|
// Write out all local JS snippets to the final destination now that
|
|
|
|
// we've collected them from all the programs.
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
for (identifier, list) in gen.snippets.iter() {
|
2019-07-29 13:32:18 -07:00
|
|
|
for (i, js) in list.iter().enumerate() {
|
|
|
|
let name = format!("inline{}.js", i);
|
|
|
|
let path = out_dir.join("snippets").join(identifier).join(name);
|
|
|
|
fs::create_dir_all(path.parent().unwrap())?;
|
|
|
|
fs::write(&path, js)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
for (path, contents) in gen.local_modules.iter() {
|
2019-07-29 13:32:18 -07:00
|
|
|
let path = out_dir.join("snippets").join(path);
|
|
|
|
fs::create_dir_all(path.parent().unwrap())?;
|
|
|
|
fs::write(&path, contents)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
if gen.npm_dependencies.len() > 0 {
|
|
|
|
let map = gen
|
2019-07-29 13:32:18 -07:00
|
|
|
.npm_dependencies
|
|
|
|
.iter()
|
|
|
|
.map(|(k, v)| (k, &v.1))
|
|
|
|
.collect::<BTreeMap<_, _>>();
|
|
|
|
let json = serde_json::to_string_pretty(&map)?;
|
|
|
|
fs::write(out_dir.join("package.json"), json)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
// And now that we've got all our JS and TypeScript, actually write it
|
|
|
|
// out to the filesystem.
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let extension = if gen.mode.nodejs_experimental_modules() {
|
2019-07-29 13:32:18 -07:00
|
|
|
"mjs"
|
|
|
|
} else {
|
|
|
|
"js"
|
|
|
|
};
|
|
|
|
let js_path = out_dir.join(&self.stem).with_extension(extension);
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
fs::write(&js_path, reset_indentation(&gen.js))
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", js_path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
if gen.typescript {
|
2019-07-29 13:32:18 -07:00
|
|
|
let ts_path = js_path.with_extension("d.ts");
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
fs::write(&ts_path, &gen.ts)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", ts_path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
if gen.mode.nodejs() {
|
2019-07-29 13:32:18 -07:00
|
|
|
let js_path = wasm_path.with_extension(extension);
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let shim = gen.generate_node_wasm_import(&self.module, &wasm_path);
|
2019-07-29 13:32:18 -07:00
|
|
|
fs::write(&js_path, shim)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", js_path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
if gen.typescript {
|
2019-07-29 13:32:18 -07:00
|
|
|
let ts_path = wasm_path.with_extension("d.ts");
|
|
|
|
let ts = wasm2es6js::typescript(&self.module)?;
|
|
|
|
fs::write(&ts_path, ts)
|
2019-11-04 11:35:28 -06:00
|
|
|
.with_context(|| format!("failed to write `{}`", ts_path.display()))?;
|
2019-07-29 13:32:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
}
|
2019-07-29 13:32:18 -07:00
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
impl JsGenerated {
|
2019-07-29 13:32:18 -07:00
|
|
|
fn generate_node_wasm_import(&self, m: &Module, path: &Path) -> String {
|
|
|
|
let mut imports = BTreeSet::new();
|
|
|
|
for import in m.imports.iter() {
|
|
|
|
imports.insert(&import.module);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut shim = String::new();
|
|
|
|
|
|
|
|
if self.mode.nodejs_experimental_modules() {
|
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
shim.push_str(&format!("import * as import{} from '{}';\n", i, module));
|
|
|
|
}
|
|
|
|
// On windows skip the leading `/` which comes out when we parse a
|
|
|
|
// url to use `C:\...` instead of `\C:\...`
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
|
|
|
import * as path from 'path';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as url from 'url';
|
|
|
|
import * as process from 'process';
|
|
|
|
|
|
|
|
let file = path.dirname(url.parse(import.meta.url).pathname);
|
|
|
|
if (process.platform === 'win32') {{
|
|
|
|
file = file.substring(1);
|
|
|
|
}}
|
|
|
|
const bytes = fs.readFileSync(path.join(file, '{}'));
|
|
|
|
",
|
|
|
|
path.file_name().unwrap().to_str().unwrap()
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
|
|
|
const path = require('path').join(__dirname, '{}');
|
|
|
|
const bytes = require('fs').readFileSync(path);
|
|
|
|
",
|
|
|
|
path.file_name().unwrap().to_str().unwrap()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
shim.push_str("let imports = {};\n");
|
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
if self.mode.nodejs_experimental_modules() {
|
|
|
|
shim.push_str(&format!("imports['{}'] = import{};\n", module, i));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
|
|
|
const wasmModule = new WebAssembly.Module(bytes);
|
|
|
|
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
|
|
|
|
",
|
|
|
|
));
|
|
|
|
|
|
|
|
if self.mode.nodejs_experimental_modules() {
|
|
|
|
for entry in m.exports.iter() {
|
|
|
|
shim.push_str("export const ");
|
|
|
|
shim.push_str(&entry.name);
|
|
|
|
shim.push_str(" = wasmInstance.exports.");
|
|
|
|
shim.push_str(&entry.name);
|
|
|
|
shim.push_str(";\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shim.push_str("module.exports = wasmInstance.exports;\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
reset_indentation(&shim)
|
|
|
|
}
|
|
|
|
}
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
|
|
|
|
fn gc_module_and_adapters(module: &mut Module) {
|
|
|
|
loop {
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
// Fist up, cleanup the native wasm module. Note that roots can come
|
|
|
|
// from custom sections, namely our wasm interface types custom section
|
|
|
|
// as well as the aux section.
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
walrus::passes::gc::run(module);
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
// ... and afterwards we can delete any `implements` directives for any
|
|
|
|
// imports that have been deleted.
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
let imports_remaining = module
|
|
|
|
.imports
|
|
|
|
.iter()
|
|
|
|
.map(|i| i.id())
|
|
|
|
.collect::<HashSet<_>>();
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
let mut section = module
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
.customs
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
.delete_typed::<wit::NonstandardWitSection>()
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
.unwrap();
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
section
|
|
|
|
.implements
|
|
|
|
.retain(|pair| imports_remaining.contains(&pair.0));
|
|
|
|
|
|
|
|
// ... and after we delete the `implements` directive we try to
|
|
|
|
// delete some adapters themselves. If nothing is deleted, then we're
|
|
|
|
// good to go. If something is deleted though then we may have free'd up
|
|
|
|
// some functions in the main module to get deleted, so go again to gc
|
|
|
|
// things.
|
|
|
|
let aux = module.customs.get_typed::<wit::WasmBindgenAux>().unwrap();
|
|
|
|
let any_removed = section.gc(aux);
|
|
|
|
module.customs.add(*section);
|
|
|
|
if !any_removed {
|
Add reference output tests for JS operations (#1894)
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
2019-12-04 12:01:39 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Add tests for the interface types output of wasm-bindgen (#1898)
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
2019-12-04 15:19:48 -06:00
|
|
|
|
|
|
|
/// Returns a sorted iterator over a hash map, sorted based on key.
|
|
|
|
///
|
|
|
|
/// The intention of this API is to be used whenever the iteration order of a
|
|
|
|
/// `HashMap` might affect the generated JS bindings. We want to ensure that the
|
|
|
|
/// generated output is deterministic and we do so by ensuring that iteration of
|
|
|
|
/// hash maps is consistently sorted.
|
|
|
|
fn sorted_iter<K, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)>
|
|
|
|
where
|
|
|
|
K: Ord,
|
|
|
|
{
|
|
|
|
let mut pairs = map.iter().collect::<Vec<_>>();
|
|
|
|
pairs.sort_by_key(|(k, _)| *k);
|
|
|
|
pairs.into_iter()
|
|
|
|
}
|