Turns out `heap.fill(undefined)` is required to ensure it's a dense
array, otherwise we'll accidentally be a sparse array and much slower
than necessary!
This commit switches strategies for storing `JsValue` from a heap/stack
to just one heap. This mirrors the new strategy for `JsValue` storage
in #1002 and should make multiplexing those strategies at
`wasm-bindgen`-time much easier.
Instead of having one array which acts as a stack for borrowed values
and one array for a heap of borrowed values, only one JS array is used
for storage of JS values now. This makes `getObject` far simpler by
simply being an array access, but it means that cloning an object now
reserves a new slot instead of reference counting it. If the old
reference counting behavior is needed it's thought that `Rc<JsValue>`
can be used in Rust.
The new "heap" has an initial stack pointer which grows downwards, and a
heap which grows upwards. The heap is a singly-linked-list which is
allocated/deallocated from. The stack grows downwards to zero and
presumably starts generating errors once it underflows. An initial stack
size of 32 is chosen as that should encompass all use cases today, but
we can eventually probably add configuration for this!
Note that the heap is initialized to all `null` for the stack and then
the initial JS values (`undefined`, `null`, `true`, `false`) are pushed
onto the heap in reserved locations.
Previously `catch` and `variadic` would exopse methods in our JS shims,
but they did so earlier than necessary. Turns out `variadic` didn't
actually need to expose anything and `catch` could do so much later!
Currently closure shims are communicated to JS at runtime, although at
runtime the same constant value is always passed to JS! More pressing,
however, work in #1002 requires knowledge of closure descriptor indices
at `wasm-bindgen` time which is not currently known.
Since the closure descriptor shims and such are already constant values,
this commit moves the descriptor function indices into the *descriptor*
for a closure/function pointer. This way we can learn about these values
at `wasm-bindgen` time instead of only knowing them at runtime.
This should have no semantic change on users of `wasm-bindgen`, although
some closure invocations may be slightly speedier because there's less
arguments being transferred over the boundary. Overall though this will
help #1002 as the closure shims that the Rust compiler generates may not
be the exact ones we hand out to JS, but rather wrappers around them
which do `anyref` business things.
This commit fixes a case in `wasm2es6js` where if an imported function
was reexported it wasn't handled correctly. This doesn't have a direct
test but came up during the development of #1002
This is split out from #1002 and is intended to fix the tool's handling
of the `start` function. For the most accurate emulation of the wasm ESM
spec I believe we need to defer execution of the start function until
all our exports are wired up which should allow valid cyclical
references during instantiation.
The fix here is to remove the start function, if one is present, and
inject an invocation of it at the end of initialization (after our
exports are wired up). This fixes tests on #1002, but doesn't have any
direct analogue for tests here just yet.
Along the way because multiple files now come out of `wasm2es6js` by
default I've added an `--out-dir` argument as well as `-o` to ensure
that a folder for all outputs can be specified.
This commit adds a new attribute to `#[wasm_bindgen]`: `start`. The
`start` attribute can be used to indicate that a function should be
executed when the module is loaded, configuring the `start` function of
the wasm executable. While this doesn't necessarily literally configure
the `start` section, it does its best!
Only one crate in a crate graph may indicate `#[wasm_bindgen(start)]`,
so it's not recommended to be used in libraries but only end-user
applications. Currently this still must be used with the `crate-type =
["cdylib"]` annotation in `Cargo.toml`.
The implementation here is somewhat tricky because of the circular
dependency between our generated JS and the wasm file that we emit. This
circular dependency makes running initialization routines (like the
`start` shim) particularly fraught with complications because one may
need to run before the other but bundlers may not necessarily respect
it. Workarounds have been implemented for various emission strategies,
for example calling the start function directly after exports are wired
up with `--no-modules` and otherwise working around what appears to be
a Webpack bug with initializers running in a different order than we'd
like. In any case, this in theory doesn't show up to the end user!
Closes#74
This generates a `*.d.ts` file for the wasm file that wasm-bindgen emits
whenever typescript is enable *in addition* to the `*.d.ts` file that
already exists for the JS shim.
Closes#1040
Recently proposed in WebAssembly/tool-conventions#65 each wasm file will
now have an optional `producers` section listing the tooling that went
into producing it. Let's add `wasm-bindgen` in when it processes a wasm
file!
This commit adds an optimization to `wasm-bindgen` to directly import
and invoke other modules' functions from the wasm module, rather than
going through a shim in the imported bindings. This will be an important
optimization in the future for the host bindings proposal, but for now
it's largely just a proof-of-concept to show that we can do it and is
unlikely to bring about many performance benefits.
The implementation in this commit is largely refactoring to reorganize a
bit how functions are imported, but the implementation happens in
`generate_import_function`.
With this commit, 71/287 imports in the `tests/wasm/main.rs` suite get
hooked up directly to the ES modules, no shims needed!
When returning a ptr/length for allocations and such wasm-bindgen's
generated JS would previously return an array with two elements. It
turns out this doesn't optimize well in all engines! (See #1031). It
looks like we can optimize the array destructuring a bit more, but this
is all generated code which doesn't need to be too readable so we can
also remove the temporary allocation entirely and just pass the second
element of this array through a global instead of the return value.
Closes#1031
This fixes a mistake in allowing a `WebAssembly.Module` to be passed to
the initialization function in `--no-modules` mode by ensuring that it
resolves to a map of an instance/module instead of just resolving to an
instance.
This commit adds a `--remove-name-section` flag to the `wasm-bindgen`
command which will remove the `name` section of the wasm file, used to
indicate the names of functions typically used in debugging. This flag
is off-by-default and will primarily be controlled by wasm-pack,
typically being passed by default with `wasm-pack build --release`.
Closes#1021
This commit removes shims, where possible, for `structural` items.
Instead of generating code that looks like:
const target = function() { this.foo(); };
exports.__wbg_thing = function(a) { target.call(getObject(a)); };
we now instead generate:
exports.__wbg_thing = function(a) { getObject(a).foo(); };
Note that this only applies to `structural` bindings, all default
bindings (as of this commit) are still using imported targets to ensure
that their binding can't change after instantiation.
This change was [detailed in RFC #5][link] as an important optimization
for `structural` bindings to ensure they've got performance parity with
today's non-`structural` default bindings.
[link]: https://rustwasm.github.io/rfcs/005-structural-and-deref.html#why-is-it-ok-to-make-structural-the-default
... and add a parallel raytracing demo!
This commit adds enough support to `wasm-bindgen` to produce a workable
wasm binary *today* with the experimental WebAssembly threads support
implemented in Firefox Nightly. I've tried to comment what's going on in
the commits and such, but at a high level the changes made here are:
* A new transformation, living in a new `wasm-bindgen-threads-xform`
crate, prepares a wasm module for parallel execution. This performs a
number of mundane tasks which I hope to detail in a blog post later on.
* The `--no-modules` output is enhanced with more support for when
shared memory is enabled, allowing passing in the module/memory to
initialize the wasm instance on multiple threads (sharing both module
and memory).
* The `wasm-bindgen` crate now offers the ability, in `--no-modules`
mode, to get a handle on the `WebAssembly.Module` instance.
* The example itself requires Xargo to recompile the standard library
with atomics and an experimental feature enabled. Afterwards it
experimentally also enables threading support in wasm-bindgen.
I've also added hopefully enough CI support to compile this example in a
builder so we can upload it and poke around live online. I hope to
detail more about the technical details here in a blog post soon as
well!
I've noticed this in a few cases where it's sometimes easy to have a
`WebAssembly.Module` on-hand for the `--no-modules` mode where you don't
want to necessarily `fetch`. This commit changes the exported
initialization function in `--no-modules` mode to support both!
This commit migrates away from using Serde for the custom section in
wasm executables. This is a refactoring of a purely-internal data
structure to `wasm-bindgen` and should have no visible functional change
on users.
The motivation for this commit is two fold:
* First, the compile times using `serde_json` and `serde_derive` for the
syntax extension isn't the most fun.
* Second, eventually we're going to want to stablize the layout of the
custom section, and it's highly unlikely to be json!
Primarily, though, the intention of this commit is to improve the
cold-cache compile time of `wasm-bindgen` by ensuring that for new users
this project builds as quickly as possible. By removing some heavyweight
dependencies from the procedural macro, `serde`, `serde_derive`, and
`serde_json`, we're able to get a pretty nice build time improvement for
the `wasm-bindgen` crate itself:
| | single-core build | parallel build |
|-------------|-------------------|----------------|
| master | 36.5s | 17.3s |
| this commit | 20.5s | 11.8s |
These are't really end-all-be-all wins but they're much better
especially on the spectrum of weaker CPUs (in theory modeled by the
single-core case showing we have 42% less CPU work in theory).
This commit fixes instantiation of the wasm module even if some of the
improted APIs don't exist. This extends the functionality initially
added in #409 to attempt to gracefully allow importing values from the
environment which don't actually exist in all contexts. In addition to
nonexistent methods being handled now entire nonexistent types are now
also handled.
I suspect that eventually we'll add a CLI flag to `wasm-bindgen` to say
"I assert everything exists, don't check it" to trim out the extra JS
glue generated here. In the meantime though this'll pave the way for a
wasm-bindgen shim to be instantiated in both a web worker and the main
thread, while using DOM-like APIs only on the main thread.
The bindings generation for a class would accidentally omit the `__wrap`
function if it was only discovered very late in the process that
`__wrap` was needed, after we'd already passed the point where we needed
to have decided that.
This commit moves struct field generation of bindings much earlier in
the binding generation process which should ensure everything is all
hooked up by the time we generate the classes themselves.
Closes#949
The `wasm-bindgen` crate is effectively the only user of this crate now
that the `wasm-gc` tool has been deprecated. It's also much easier to
keep it in this repository as it's easier to sync changes to
`parity-wasm`. I'd also like to start refactoring out utilities for
managing a `parity_wasm::Module` to share between this crate and the
other CLI support code.