This hasn't ever actually worked in `wasm-bindgen` but there's been
enough refactorings since the initial implementation that it's actually
quite trivial to implement now!
Closes#1777
This tiny crate provides utilities for working with Wasm codegen
conventions (typically established by LLVM or lld) such as getting the shadow
stack pointer.
It also de-duplicates all the places in the codebase where we were implementing
these conventions in one-off ways.
This crate provides a transformation to turn exported functions that use a
return pointer into exported functions that use multi-value.
Consider the following function:
```rust
pub extern "C" fn pair(a: u32, b: u32) -> [u32; 2] {
[a, b]
}
```
LLVM will by default compile this down into the following Wasm:
```wasm
(func $pair (param i32 i32 i32)
local.get 0
local.get 2
i32.store offset=4
local.get 0
local.get 1
i32.store)
```
What's happening here is that the function is not directly returning the
pair at all, but instead the first `i32` parameter is a pointer to some
scratch space, and the return value is written into the scratch space. LLVM
does this because it doesn't yet have support for multi-value Wasm, and so
it only knows how to return a single value at a time.
Ideally, with multi-value, what we would like instead is this:
```wasm
(func $pair (param i32 i32) (result i32 i32)
local.get 0
local.get 1)
```
However, that's not what this transformation does at the moment. This
transformation is a little simpler than mutating existing functions to
produce a multi-value result, instead it introduces new functions that wrap
the original function and translate the return pointer to multi-value
results in this wrapper function.
With our running example, we end up with this:
```wasm
;; The original function.
(func $pair (param i32 i32 i32)
local.get 0
local.get 2
i32.store offset=4
local.get 0
local.get 1
i32.store)
(func $pairWrapper (param i32 i32) (result i32 i32)
;; Our return pointer that points to the scratch space we are allocating
;; on the shadow stack for calling `$pair`.
(local i32)
;; Allocate space on the shadow stack for the result.
global.get $shadowStackPointer
i32.const 8
i32.sub
local.tee 2
global.set $shadowStackPointer
;; Call `$pair` with our allocated shadow stack space for its results.
local.get 2
local.get 0
local.get 1
call $pair
;; Copy the return values from the shadow stack to the wasm stack.
local.get 2
i32.load
local.get 2 offset=4
i32.load
;; Finally, restore the shadow stack pointer.
local.get 2
i32.const 8
i32.add
global.set $shadowStackPointer)
```
This `$pairWrapper` function is what we actually end up exporting instead of
`$pair`.
This commit adds support to attach `#[wasm_bindgen]` on an `async fn`
which will change the return value into a `Promise` in JS. This in
theory has the exact same semantics as an `async` function in JS where
you call it with all the arguments, nothing happens and you get a
promise back, and then later the promise actually resolves.
This commit also adds a helper trait, `IntoJsResult`, to allow `async`
functions with multiple kinds of return values instead of requiring
everything to be `Result<JsValue, JsValue>`.
This commit defaults all crates in-tree to use `std::future` by default
and none of them support the crates.io `futures` 0.1 crate any more.
This is a breaking change for `wasm-bindgen-futures` and
`wasm-bindgen-test` so they've both received a major version bump to
reflect the new defaults. Historical versions of these crates should
continue to work if necessary, but they won't receive any more
maintenance after this is merged.
The movement here liberally uses `async`/`await` to remove the need for
using any combinators on the `Future` trait. As a result many of the
crates now rely on a much more recent version of the compiler,
especially to run tests.
The `wasm-bindgen-futures` crate was updated to remove all of its
futures-related dependencies and purely use `std::future`, hopefully
improving its compatibility by not having any version compat
considerations over time. The implementations of the executors here are
relatively simple and only delve slightly into the `RawWaker` business
since there are no other stable APIs in `std::task` for wrapping these.
This commit also adds support for:
#[wasm_bindgen_test]
async fn foo() {
// ...
}
where previously you needed to pass `(async)` now that's inferred
because it's an `async fn`.
Closes#1558Closes#1695
This needed and update now that we're explicitly importing `*.wasm` to
import `*.js` instead. Additionally this was moved over to the `web`
target to avoid needing Webpack
Closes#1743
* Adding ignoreBOM and fatal to TextDecoder
* Minor tweak to expose_text_processor
* Adding in unit tests for BOM
* Adding in comment for expose_text_decoder
* Attempting to fix build failure
* Temporarily disabling unit tests
* Update browser support for `BigInt`
`BigInt` is supported in Firefox as of Firefox 68!
Also replaced Firefox with Safari as a second example of an unsupported browser.
* Add link to "BigInt" on "Can I use..."
This commit adds support to `wasm-bindgen` to emit a WebAssembly module
that contains a WebAssembly Interface Types section. As of today there are no
native consumers of these WebAssembly modules, and the actual binary format
here is basically arbitrary (chosen by the `wasm-webidl-bindings` crate). The
intention is that we'll be following the [WebAssembly Interface
Types proposal][proposal] very closely and update here as necessary.
The main feature added in this PR is that a new experimental environment
variable, `WASM_INTERFACE_TYPES=1`, is recognized by the `wasm-bindgen`
CLI tool. When present the CLI tool will act differently than it does
today:
* The `anyref` feature will be implicitly enabled
* A WebAssembly interface types section will be emitted in the
WebAssembly module
* For now, the WebAssembly module is strictly validated to require zero
JS glue. This means that `wasm-bindgen` is producing a fully
standalone WebAssembly module.
The last point here is one that will change before this functionality is
stabilized in `wasm-bindgen`. For now it reflects the major use case of
this feature which is to produce a standalone WebAssembly module with no
support JS glue, and to do that we need to verify properties like it's
not using JS global names, nonstandard binding expressions, etc. The
error messages here aren't the best but they at least fail compilation
at some point instead of silently producing weird wasm modules.
Eventually it's envisioned that a WebAssembly module will contain an
interface types section but *also* have JS glue so binding expressions
can be used when available but otherwise we'd still generate JS glue for
things like nonstandard expressions and accessing JS global values.
It should be noted that a major feature not implemented in
`wasm-bindgen` yet is the multi-value proposal for WebAssembly. This is
coming soon (as soon as we can) in `walrus` and later for a pass here,
but for now this means that returning multiple values (like a string
which has a pointer/length) is a bit of a hack. To enable this use case
a `wasm-bindgen`-specific-convention which will never be stabilized is
invented here by using binding expression to indicate "this return value
is actually returned through an out-ptr as the first argument list".
This is a gross hack and is guaranteed to be removed. Eventually we will
support multi-value and the wasm module emitted will simply use
multi-value and contain internal polyfills for Rust's ABI which returns
values through out-ptrs.
Overall this should make `wasm-bindgen` usable for playing around with
the WebIDL bindings proposal and helping us get a taste of what it looks
like to have entirely standalone WebAssembly modules running in multiple
environments, no extra fluff necessary!
[proposal]: https://github.com/webassembly/webidl-bindings
This commit improves our `instantiateStreaming` fallback to only
actually trigger the fallback if the headers look wrong. If the headers
look right then we let through the original error which should help
avoid accidentally papering over bugs with different bugs in
misconfigured situations.
Closes#1696
Turns out #1704 was buggy and ended up never injecting initialization
because the anyref table was never present! This fixes that issue and
this should now be tested on CI to ensure this doesn't regress and
future changes preserve correctness