RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.

This commit is contained in:
Adam Ierymenko
2022-06-08 07:32:16 -04:00
parent 373ca30269
commit d5ca4e5f52
12611 changed files with 2898014 additions and 284 deletions

View File

@@ -0,0 +1,82 @@
# Accessing Properties of Untyped JavaScript Values
To read and write arbitrary properties from any untyped JavaScript value
regardless if it is an `instanceof` some JavaScript class or not, use [the
`js_sys::Reflect` APIs][js-sys-reflect]. These APIs are bindings to the
[JavaScript builtin `Reflect` object][mdn-reflect] and its methods.
You might also benefit from [using duck-typed
interfaces](./working-with-duck-typed-interfaces.html) instead of working with
untyped values.
## Reading Properties with `js_sys::Reflect::get`
[API documentation for `js_sys::Reflect::get`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.get.html)
A function that returns the value of a property.
#### Rust Usage
```rust
let value = js_sys::Reflect::get(&target, &property_key)?;
```
#### JavaScript Equivalent
```js
let value = target[property_key];
```
## Writing Properties with `js_sys::Reflect::set`
[API documentation for `js_sys::Reflect::set`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.set.html)
A function that assigns a value to a property. Returns a boolean that is true if
the update was successful.
#### Rust Usage
```rust
js_sys::Reflect::set(&target, &property_key, &value)?;
```
#### JavaScript Equivalent
```js
target[property_key] = value;
```
## Determining if a Property Exists with `js_sys::Reflect::has`
[API documentation for `js_sys::Reflect::has`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.has.html)
The JavaScript `in` operator as function. Returns a boolean indicating whether
an own or inherited property exists on the target.
#### Rust Usage
```rust
if js_sys::Reflect::has(&target, &property_key)? {
// ...
} else {
// ...
}
```
#### JavaScript Equivalent
```js
if (property_key in target) {
// ...
} else {
// ...
}
```
## But wait — there's more!
See [the `js_sys::Reflect` API documentation][js-sys-reflect] for the full
listing of JavaScript value reflection and introspection capabilities.
[js-sys-reflect]: https://docs.rs/js-sys/latest/js_sys/Reflect/index.html
[mdn-reflect]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect

View File

@@ -0,0 +1,116 @@
# Serializing and Deserializing Arbitrary Data Into and From `JsValue` with Serde
It's possible to pass arbitrary data from Rust to JavaScript by serializing it
to JSON with [Serde](https://github.com/serde-rs/serde). `wasm-bindgen` includes
the `JsValue` type, which streamlines serializing and deserializing.
## Enable the `"serde-serialize"` Feature
To enable the `"serde-serialize"` feature, do two things in `Cargo.toml`:
1. Add the `serde` and `serde_derive` crates to `[dependencies]`.
2. Add `features = ["serde-serialize"]` to the existing `wasm-bindgen`
dependency.
```toml
[dependencies]
serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
```
## Derive the `Serialize` and `Deserialize` Traits
Add `#[derive(Serialize, Deserialize)]` to your type. All of your type's
members must also be supported by Serde, i.e. their types must also implement
the `Serialize` and `Deserialize` traits.
For example, let's say we'd like to pass this `struct` to JavaScript; doing so
is not possible in `wasm-bindgen` normally due to the use of `HashMap`s, arrays,
and nested `Vec`s. None of those types are supported for sending across the wasm
ABI naively, but all of them implement Serde's `Serialize` and `Deserialize`.
Note that we do not need to use the `#[wasm_bindgen]` macro.
```rust
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Example {
pub field1: HashMap<u32, String>,
pub field2: Vec<Vec<f32>>,
pub field3: [f32; 4],
}
```
## Send it to JavaScript with `JsValue::from_serde`
Here's a function that will pass an `Example` to JavaScript by serializing it to
`JsValue`:
```rust
#[wasm_bindgen]
pub fn send_example_to_js() -> JsValue {
let mut field1 = HashMap::new();
field1.insert(0, String::from("ex"));
let example = Example {
field1,
field2: vec![vec![1., 2.], vec![3., 4.]],
field3: [1., 2., 3., 4.]
};
JsValue::from_serde(&example).unwrap()
}
```
## Receive it from JavaScript with `JsValue::into_serde`
Here's a function that will receive a `JsValue` parameter from JavaScript and
then deserialize an `Example` from it:
```rust
#[wasm_bindgen]
pub fn receive_example_from_js(val: &JsValue) {
let example: Example = val.into_serde().unwrap();
...
}
```
## JavaScript Usage
In the `JsValue` that JavaScript gets, `field1` will be an `Object` (not a
JavaScript `Map`), `field2` will be a JavaScript `Array` whose members are
`Array`s of numbers, and `field3` will be an `Array` of numbers.
```js
import { send_example_to_js, receive_example_from_js } from "example";
// Get the example object from wasm.
let example = send_example_to_js();
// Add another "Vec" element to the end of the "Vec<Vec<f32>>"
example.field2.push([5, 6]);
// Send the example object back to wasm.
receive_example_from_js(example);
```
## An Alternative Approach: `serde-wasm-bindgen`
[The `serde-wasm-bindgen`
crate](https://github.com/cloudflare/serde-wasm-bindgen) serializes and
deserializes Rust structures directly to `JsValue`s, without going through
temporary JSON stringification. This approach has both advantages and
disadvantages.
The primary advantage is smaller code size: going through JSON entrenches code
to stringify and parse floating point numbers, which is not a small amount of
code. It also supports more types than JSON does, such as `Map`, `Set`, and
array buffers.
There are two primary disadvantages. The first is that it is not always
compatible with the default JSON-based serialization. The second is that it
performs more calls back and forth between JS and Wasm, which has not been fully
optimized in all engines, meaning it can sometimes be a speed
regression. However, in other cases, it is a speed up over the JSON-based
stringification, so &mdash; as always &mdash; make sure to profile your own use
cases as necessary.

View File

@@ -0,0 +1,6 @@
# `#[wasm_bindgen]` Attributes
The `#[wasm_bindgen]` macro supports a good amount of configuration for
controlling precisely how exports are exported, how imports are imported, and
what the generated JavaScript glue ends up looking like. This section is an
exhaustive reference of the possibilities!

View File

@@ -0,0 +1,29 @@
# `catch`
The `catch` attribute allows catching a JavaScript exception. This can be
attached to any imported function or method, and the function must return a
`Result` where the `Err` payload is a `JsValue`:
```rust
#[wasm_bindgen]
extern "C" {
// `catch` on a standalone function.
#[wasm_bindgen(catch)]
fn foo() -> Result<(), JsValue>;
// `catch` on a method.
type Zoidberg;
#[wasm_bindgen(catch, method)]
fn woop_woop_woop(this: &Zoidberg) -> Result<u32, JsValue>;
}
```
If calling the imported function throws an exception, then `Err` will be
returned with the exception that was raised. Otherwise, `Ok` is returned with
the result of the function.
> By default `wasm-bindgen` will take no action when wasm calls a JS function
> which ends up throwing an exception. The wasm spec right now doesn't support
> stack unwinding and as a result Rust code **will not execute destructors**.
> This can unfortunately cause memory leaks in Rust right now, but as soon as
> wasm implements catching exceptions we'll be sure to add support as well!

View File

@@ -0,0 +1,24 @@
# `constructor`
The `constructor` attribute is used to indicate that the function being bound
should actually translate to calling the `new` operator in JavaScript. The final
argument must be a type that's imported from JavaScript, and it's what will get
used in the generated glue:
```rust
#[wasm_bindgen]
extern "C" {
type Shoes;
#[wasm_bindgen(constructor)]
fn new() -> Shoes;
}
```
This will attach a `new` static method to the `Shoes` type, and in JavaScript
when this method is called, it will be equivalent to `new Shoes()`.
```rust
// Become a cobbler; construct `new Shoes()`
let shoes = Shoes::new();
```

View File

@@ -0,0 +1,49 @@
# `extends = Class`
The `extends` attribute can be used to say that an imported type extends (in the
JS class hierarchy sense) another type. This will generate `AsRef`, `AsMut`, and
`From` impls for converting a type into another given that we statically know
the inheritance hierarchy:
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(extends = Foo)]
type Bar;
}
let x: &Bar = ...;
let y: &Foo = x.as_ref(); // zero cost cast
```
The trait implementations generated for the above block are:
```rust
impl From<Bar> for Foo { ... }
impl AsRef<Foo> for Bar { ... }
impl AsMut<Foo> for Bar { ... }
```
The `extends = ...` attribute can be specified multiple times for longer
inheritance chains, and `AsRef` and such impls will be generated for each of
the types.
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(extends = Foo)]
type Bar;
#[wasm_bindgen(extends = Foo, extends = Bar)]
type Baz;
}
let x: &Baz = ...;
let y1: &Bar = x.as_ref();
let y2: &Foo = y1.as_ref();
```

View File

@@ -0,0 +1,156 @@
# `final`
The `final` attribute is the converse of the [`structural`
attribute](structural.html). It configures how `wasm-bindgen` will generate JS
imports to call the imported function. Notably a function imported by `final`
never changes after it was imported, whereas a function imported by default (or
with `structural`) is subject to runtime lookup rules such as walking the
prototype chain of an object. Note that `final` is not suitable for accessing
data descriptor properties of JS objects; to accomplish this, use the `structural`
attribute.
[host-bindings]: https://github.com/WebAssembly/host-bindings
[reference-types]: https://github.com/WebAssembly/reference-types
The `final` attribute is intended to be purely related to performance. It
ideally has no user-visible effect, and `structural` imports (the default)
should be able to transparently switch to `final` eventually.
The eventual performance aspect is that with the [host bindings
proposal][host-bindings] then `wasm-bindgen` will need to generate far fewer JS
function shims to import than it does today. For example, consider this import
today:
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(method)]
fn bar(this: &Foo, argument: &str) -> JsValue;
}
```
**Without the `final` attribute** the generated JS looks like this:
```js
// without `final`
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(getObject(arg0).bar(varg1));
}
```
We can see here that this JS function shim is required, but it's all relatively
self-contained. It does, however, execute the `bar` method in a duck-type-y
fashion in the sense that it never validates `getObject(arg0)` is of type `Foo`
to actually call the `Foo.prototype.bar` method.
If we instead, however, write this:
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(method, final)] // note the change here
fn bar(this: &Foo, argument: &str) -> JsValue;
}
```
it generates this JS glue (roughly):
```js
const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
}
```
The difference here is pretty subtle, but we can see how the function being
called is hoisted out of the generated shim and is bound to always be
`Foo.prototype.bar`. This then uses the `Function.call` method to invoke that
function with `getObject(arg0)` as the receiver.
But wait, there's still a JS function shim here even with `final`! That's true,
and this is simply a fact of future WebAssembly proposals not being implemented
yet. The semantics, though, match the future [host bindings
proposal][host-bindings] because the method being called is determined exactly
once, and it's located on the prototype chain rather than being resolved at
runtime when the function is called.
## Interaction with future proposals
If you're curious to see how our JS function shim will be eliminated entirely,
let's take a look at the generated bindings. We're starting off with this:
```js
const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1));
}
```
... and once the [reference types proposal][reference-types] is implemented then
we won't need some of these pesky functions. That'll transform our generated JS
shim to look like:
```js
const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) {
let varg1 = getStringFromWasm(arg1, arg2);
return __wbg_bar_target.call(arg0, varg1);
}
```
Getting better! Next up we need the host bindings proposal. Note that the
proposal is undergoing some changes right now so it's tough to link to reference
documentation, but it suffices to say that it'll empower us with at least two
different features.
First, host bindings promises to provide the concept of "argument conversions".
The `arg1` and `arg2` values here are actually a pointer and a length to a utf-8
encoded string, and with host bindings we'll be able to annotate that this
import should take those two arguments and convert them to a JS string (that is,
the *host* should do this, the WebAssembly engine). Using that feature we can
futher trim this down to:
```js
const __wbg_bar_target = Foo.prototype.bar;
export function __wbg_bar_a81456386e6b526f(arg0, varg1) {
return __wbg_bar_target.call(arg0, varg1);
}
```
And finally, the second promise of the host bindings proposal is that we can
flag a function call to indicate the first argument is the `this` binding of the
function call. Today the `this` value of all called imported functions is
`undefined`, and this flag (configured with host bindings) will indicate the
first argument here is actually the `this`.
With that in mind we can further transform this to:
```js
export const __wbg_bar_a81456386e6b526f = Foo.prototype.bar;
```
and voila! We, with [reference types][reference-types] and [host
bindings][host-bindings], now have no JS function shim at all necessary to call
the imported function. Additionally future wasm proposals to the ES module
system may also mean that don't even need the `export const ...` here too.
It's also worth pointing out that with all these wasm proposals implemented the
default way to import the `bar` function (aka `structural`) would generate a JS
function shim that looks like:
```js
export function __wbg_bar_a81456386e6b526f(varg1) {
return this.bar(varg1);
}
```
where this import is still subject to runtime prototype chain lookups and such.

View File

@@ -0,0 +1,78 @@
# `getter` and `setter`
These two attributes can be combined with `method` to indicate that this is a
getter or setter method. A `getter`-tagged function by default accesses the
JavaScript property with the same name as the getter function. A `setter`'s
function name is currently required to start with `set_` and the property it
accesses is the suffix after `set\_`.
Consider the following JavaScript class that has a getter and setter for the
`white_russians` property:
```js
class TheDude {
get white_russians() {
...
}
set white_russians(val) {
...
}
}
```
We would import this with the following `#[wasm_bindgen]` attributes:
```rust
#[wasm_bindgen]
extern "C" {
type TheDude;
#[wasm_bindgen(method, getter)]
fn white_russians(this: &TheDude) -> u32;
#[wasm_bindgen(method, setter)]
fn set_white_russians(this: &TheDude, val: u32);
}
```
Here we're importing the `TheDude` type and defining the ability to access each
object's `white_russians` property. The first function here is a getter and will
be available in Rust as `the_dude.white_russians()`, and the latter is the
setter which is accessible as `the_dude.set_white_russians(2)`. Note that both
functions have a `this` argument as they're tagged with `method`.
Finally, you can also pass an argument to the `getter` and `setter`
properties to configure what property is accessed. When the property is
explicitly specified then there is no restriction on the method name. For
example the below is equivalent to the above:
```rust
#[wasm_bindgen]
extern "C" {
type TheDude;
#[wasm_bindgen(method, getter = white_russians)]
fn my_custom_getter_name(this: &TheDude) -> u32;
#[wasm_bindgen(method, setter = white_russians)]
fn my_custom_setter_name(this: &TheDude, val: u32);
}
```
Heads up! `getter` and `setter` functions are found on the constructor's
prototype chain once at load time, cached, and then the cached accessor is
invoked on each access. If you need to dynamically walk the prototype chain on
every access, add the `structural` attribute!
```js
// This is the default function Rust will invoke on `the_dude.white_russians()`:
const white_russians = Object.getOwnPropertyDescriptor(
TheDude.prototype,
"white_russians"
).get;
// This is what you get by adding `structural`:
const white_russians = function(the_dude) {
return the_dude.white_russians;
};
```

View File

@@ -0,0 +1,5 @@
# `#[wasm_bindgen]` on JavaScript Imports
This section enumerates the attributes available for customizing bindings for
JavaScript functions and classes imported into Rust within an `extern "C" { ... }`
block.

View File

@@ -0,0 +1,82 @@
# `indexing_getter`, `indexing_setter`, and `indexing_deleter`
These three attributes indicate that a method is an dynamically intercepted
getter, setter, or deleter on the receiver object itself, rather than a direct
access of the receiver's properties. It is equivalent calling the Proxy handler
for the `obj[prop]` operation with some dynamic `prop` variable in JavaScript,
rather than a normal static property access like `obj.prop` on a normal
JavaScript `Object`.
This is useful for binding to `Proxy`s and some builtin DOM types that
dynamically intercept property accesses.
* `indexing_getter` corresponds to `obj[prop]` operation in JavaScript. The
function annotated must have a `this` receiver parameter, a single parameter
that is used for indexing into the receiver (`prop`), and a return type.
* `indexing_setter` corresponds to the `obj[prop] = val` operation in
JavaScript. The function annotated must have a `this` receiver parameter, a
parameter for indexing into the receiver (`prop`), and a value parameter
(`val`).
* `indexing_deleter` corresponds to `delete obj[prop]` operation in
JavaScript. The function annotated must have a `this` receiver and a single
parameter for indexing into the receiver (`prop`).
These must always be used in conjunction with the `structural` and `method`
flags.
For example, consider this JavaScript snippet that uses `Proxy`:
```js
const foo = new Proxy({}, {
get(obj, prop) {
return prop in obj ? obj[prop] : prop.length;
},
set(obj, prop, value) {
obj[prop] = value;
},
deleteProperty(obj, prop) {
delete obj[prop];
},
});
foo.ten;
// 3
foo.ten = 10;
foo.ten;
// 10
delete foo.ten;
foo.ten;
// 3
```
To bind that in `wasm-bindgen` in Rust, we would use the `indexing_*` attributes
on methods:
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
static foo: Foo;
#[wasm_bindgen(method, structural, indexing_getter)]
fn get(this: &Foo, prop: &str) -> u32;
#[wasm_bindgen(method, structural, indexing_setter)]
fn set(this: &Foo, prop: &str, val: u32);
#[wasm_bindgen(method, structural, indexing_deleter)]
fn delete(this: &Foo, prop: &str);
}
assert_eq!(foo.get("ten"), 3);
foo.set("ten", 10);
assert_eq!(foo.get("ten"), 10);
foo.delete("ten");
assert_eq!(foo.get("ten"), 3);
```

View File

@@ -0,0 +1,20 @@
# `js_class = "Blah"`
The `js_class` attribute can be used in conjunction with the `method` attribute
to bind methods of imported JavaScript classes that have been renamed on the
Rust side.
```rust
#[wasm_bindgen]
extern "C" {
// We don't want to import JS strings as `String`, since Rust already has a
// `String` type in its prelude, so rename it as `JsString`.
#[wasm_bindgen(js_name = String)]
type JsString;
// This is a method on the JavaScript "String" class, so specify that with
// the `js_class` attribute.
#[wasm_bindgen(method, js_class = "String", js_name = charAt)]
fn char_at(this: &JsString, index: u32) -> JsString;
}
```

View File

@@ -0,0 +1,87 @@
# `js_name = blah`
The `js_name` attribute can be used to bind to a different function in
JavaScript than the identifier that's defined in Rust.
Most often, this is used to convert a camel-cased JavaScript identifier into a
snake-cased Rust identifier:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = jsOftenUsesCamelCase)]
fn js_often_uses_camel_case() -> u32;
}
```
Sometimes, it is used to bind to JavaScript identifiers that are not valid Rust
identifiers, in which case `js_name = "some string"` is used instead of `js_name
= ident`:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = "$$$")]
fn cash_money() -> u32;
}
```
However, you can also use `js_name` to define multiple signatures for
polymorphic JavaScript functions:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_str(s: &str);
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_u32(n: u32);
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log_many(a: u32, b: &JsValue);
}
```
All of these functions will call `console.log` in JavaScript, but each
identifier will have only one signature in Rust.
Note that if you use `js_name` when importing a type you'll also need to use the
[`js_class` attribute][jsclass] when defining methods on the type:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = String)]
type JsString;
#[wasm_bindgen(method, getter, js_class = "String")]
pub fn length(this: &JsString) -> u32;
}
```
The `js_name` attribute can also be used in situations where a JavaScript module uses
`export default`. In this case, setting the `js_name` attribute to "default" on the
`type` declaration, and the [`js_class` attribute][jsclass] to "default" on any methods
on the exported object will generate the correct imports.
For example, a module that would be imported directly in JavaScript:
```javascript
import Foo from "bar";
let f = new Foo();
```
Could be accessed using this definition in Rust:
```rust
#[wasm_bindgen(module = "bar")]
extern "C" {
#[wasm_bindgen(js_name = default)
type Foo;
#[wasm_bindgen(constructor, js_class = default)]
pub fn new() -> Foo;
}
```
[jsclass]: js_class.html

View File

@@ -0,0 +1,41 @@
# `js_namespace = blah`
This attribute indicates that the JavaScript type is accessed through the given
namespace. For example, the `WebAssembly.Module` APIs are all accessed through
the `WebAssembly` namespace. `js_namespace` can be applied to any import
(function or type) and whenever the generated JavaScript attempts to reference a
name (like a class or function name) it'll be accessed through this namespace.
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
type Foo;
#[wasm_bindgen(constructor, js_namespace = Bar)]
fn new() -> Foo;
}
log("hello, console!");
Foo::new();
```
This is an example of how to bind namespaced items in Rust. The `log` and `Foo::new` functions will
be available in the Rust module and will be invoked as `console.log` and `new Bar.Foo` in
JavaScript.
It is also possible to access the JavaScript object under the nested namespace.
`js_namespace` also accepts the array of the string to specify the namespace.
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = ["window", "document"])]
fn write(s: &str);
}
write("hello, document!");
```
This example shows how to bind `window.document.write` in Rust.

View File

@@ -0,0 +1,26 @@
# `method`
The `method` attribute allows you to describe methods of imported JavaScript
objects. It is applied on a function that has `this` as its first parameter,
which is a shared reference to an imported JavaScript type.
```rust
#[wasm_bindgen]
extern "C" {
type Set;
#[wasm_bindgen(method)]
fn has(this: &Set, element: &JsValue) -> bool;
}
```
This generates a `has` method on `Set` in Rust, which invokes the
`Set.prototype.has` method in JavaScript.
```rust
let set: Set = ...;
let elem: JsValue = ...;
if set.has(&elem) {
...
}
```

View File

@@ -0,0 +1,38 @@
# `module = "blah"`
The `module` attributes configures the module from which items are imported. For
example,
```rust
#[wasm_bindgen(module = "wu/tang/clan")]
extern "C" {
type ThirtySixChambers;
}
```
generates JavaScript import glue like:
```js
import { ThirtySixChambers } from "wu/tang/clan";
```
If a `module` attribute is not present, then the global scope is used
instead. For example,
```rust
#[wasm_bindgen]
extern "C" {
fn illmatic() -> u32;
}
```
generates JavaScript import glue like:
```js
let illmatic = this.illmatic;
```
Note that if the string specified with `module` starts with `./`, `../`, or `/`
then it's interpreted as a path to a [local JS snippet](../../js-snippets.html).
If this doesn't work for your use case you might be interested in the
[`raw_module` attribute](raw_module.html)

View File

@@ -0,0 +1,24 @@
# `no_deref`
The `no_deref` attribute can be used to say that no `Deref` impl should be
generated for an imported type. If this attribute is not present, a `Deref` impl
will be generated with a `Target` of the type's first `extends` attribute, or
`Target = JsValue` if there are no `extends` attributes.
```rust
#[wasm_bindgen]
extern "C" {
type Foo;
#[wasm_bindgen(method)]
fn baz(this: &Foo)
#[wasm_bindgen(extends = Foo, no_deref)]
type Bar;
}
fn do_stuff(bar: &Bar) {
bar.baz() // Does not compile
}
```

View File

@@ -0,0 +1,19 @@
# `raw_module = "blah"`
This attribute performs exactly the same purpose as the [`module`
attribute](module.html) on JS imports, but it does not attempt to interpret
paths starting with `./`, `../`, or `/` as JS snippets. For example:
```rust
#[wasm_bindgen(raw_module = "./some/js/file.js")]
extern "C" {
fn the_function();
}
```
Note that if you use this attribute with a relative or absolute path, it's
likely up to the final bundler or project to assign meaning to that path. This
typically means that the JS file or module will be resolved relative to the
final location of the wasm file itself. That means that `raw_module` is likely
unsuitable for libraries on crates.io, but may be usable within end-user
applications.

View File

@@ -0,0 +1,28 @@
# `static_method_of = Blah`
The `static_method_of` attribute allows one to specify that an imported function
is a static method of the given imported JavaScript class. For example, to bind
to JavaScript's `Date.now()` static method, one would use this attribute:
```rust
#[wasm_bindgen]
extern "C" {
type Date;
#[wasm_bindgen(static_method_of = Date)]
pub fn now() -> f64;
}
```
The `now` function becomes a static method of the imported type in the Rust
bindings as well:
```rust
let instant = Date::now();
```
This is similar to the `js_namespace` attribute, but the usage from within Rust
is different since the method also becomes a static method of the imported type.
Additionally this attribute also specifies that the `this` parameter when
invoking the method is expected to be the JS class, e.g. always invoked as
`Date.now()` instead of `const x = Date.now; x()`.

View File

@@ -0,0 +1,48 @@
# `structural`
> **Note**: As of [RFC 5] this attribute is the default for all imported
> functions. This attribute is largely ignored today and is only retained for
> backwards compatibility and learning purposes.
>
> The inverse of this attribute, [the `final`
> attribute](final.html) is more functionally interesting than
> `structural` (as `structural` is simply the default)
[RFC 5]: https://rustwasm.github.io/rfcs/005-structural-and-deref.html
The `structural` flag can be added to `method` annotations, indicating that the
method being accessed (or property with getters/setters) should be accessed in a
structural, duck-type-y fashion. Rather than walking the constructor's prototype
chain once at load time and caching the property result, the prototype chain is
dynamically walked on every access.
```rust
#[wasm_bindgen]
extern "C" {
type Duck;
#[wasm_bindgen(method, structural)]
fn quack(this: &Duck);
#[wasm_bindgen(method, getter, structural)]
fn is_swimming(this: &Duck) -> bool;
}
```
The constructor for the type here, `Duck`, is not required to exist in
JavaScript (it's not referenced). Instead `wasm-bindgen` will generate shims
that will access the passed in JavaScript value's `quack` method or its
`is_swimming` property.
```js
// Without `structural`, get the method directly off the prototype at load time:
const Duck_prototype_quack = Duck.prototype.quack;
function quack(duck) {
Duck_prototype_quack.call(duck);
}
// With `structural`, walk the prototype chain on every access:
function quack(duck) {
duck.quack();
}
```

View File

@@ -0,0 +1,15 @@
# `typescript_type = "Blah"`
The `typescript_type` attribute is used to specify the TypeScript type for an
imported type. This type will be used in the generated `.d.ts`.
Right now only identifiers are supported, but eventually we'd like to support
all TypeScript types.
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "Foo")]
type Foo;
}
```

View File

@@ -0,0 +1,38 @@
# Variadic Parameters
In javascript, both the types of function arguments, and the number of function arguments are
dynamic. For example
```js
function sum(...rest) {
let i;
// the old way
let old_way = 0;
for (i=0; i<arguments.length; i++) {
old_way += arguments[i];
}
// the new way
let new_way = 0;
for (i=0; i<rest.length; i++) {
new_way += rest[i];
}
// both give the same answer
assert(old_way === new_way);
return new_way;
}
```
This function doesn't translate directly into rust, since we don't currently support variadic
arguments on the wasm target. To bind to it, we use a slice as the last argument, and annotate the
function as variadic:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(variadic)]
fn sum(args: &[i32]) -> i32;
}
```
when we call this function, the last argument will be expanded as the javascript expects.

View File

@@ -0,0 +1,24 @@
# Vendor-prefixed APIs
On the web new APIs often have vendor prefixes while they're in an experimental
state. For example the `AudioContext` API is known as `webkitAudioContext` in
Safari at the time of this writing. The `vendor_prefix` attribute indicates
these alternative names, which are used if the normal name isn't defined.
For example to use `AudioContext` you might do:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(vendor_prefix = webkit)]
type AudioContext;
// methods on `AudioContext` ...
}
```
Whenever `AudioContext` is used it'll use `AudioContext` if the global namespace
defines it or alternatively it'll fall back to `webkitAudioContext`.
Note that `vendor_prefix` cannot be used with `module = "..."` or
`js_namespace = ...`, so it's basically limited to web-platform APIs today.

View File

@@ -0,0 +1,34 @@
# `constructor`
When attached to a Rust "constructor" it will make the generated JavaScript
bindings callable as `new Foo()`.
For example, consider this exported Rust type and `constructor` annotation:
```rust
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -> Foo {
Foo { contents: 0 }
}
pub fn get_contents(&self) -> u32 {
self.contents
}
}
```
This can be used in JavaScript as:
```js
import { Foo } from './my_module';
const f = new Foo();
console.log(f.get_contents());
```

View File

@@ -0,0 +1,64 @@
# `getter` and `setter`
The `getter` and `setter` attributes can be used in Rust `impl` blocks to define
properties in JS that act like getters and setters of a field. For example:
```rust
#[wasm_bindgen]
pub struct Baz {
field: i32,
}
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(constructor)]
pub fn new(field: i32) -> Baz {
Baz { field }
}
#[wasm_bindgen(getter)]
pub fn field(&self) -> i32 {
self.field
}
#[wasm_bindgen(setter)]
pub fn set_field(&mut self, field: i32) {
self.field = field;
}
}
```
Can be combined in `JavaScript` like in this snippet:
```js
const obj = new Baz(3);
assert.equal(obj.field, 3);
obj.field = 4;
assert.equal(obj.field, 4);
```
You can also configure the name of the property that is exported in JS like so:
```rust
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(getter = anotherName)]
pub fn field(&self) -> i32 {
self.field
}
#[wasm_bindgen(setter = anotherName)]
pub fn set_field(&mut self, field: i32) {
self.field = field;
}
}
```
Getters are expected to take no arguments other than `&self` and return the
field's type. Setters are expected to take one argument other than `&mut self`
(or `&self`) and return no values.
The name for a `getter` is by default inferred from the function name it's
attached to. The default name for a `setter` is the function's name minus the
`set_` prefix, and if `set_` isn't a prefix of the function it's an error to not
provide the name explicitly.

View File

@@ -0,0 +1,17 @@
# `getter_with_clone`
By default, Rust exports exposed to JavaScript will generate getters that require fields to implement `Copy`. The `getter_with_clone` attribute can be used to generate getters that require `Clone` instead. This attribute can be applied per struct or per field. For example:
```rust
#[wasm_bindgen]
pub struct Foo {
#[wasm_bindgen(getter_with_clone)]
pub bar: String,
}
#[wasm_bindgen(getter_with_clone)]
pub struct Foo {
pub bar: String,
pub baz: String,
}
```

View File

@@ -0,0 +1,4 @@
# `#[wasm_bindgen]` on Rust Exports
This section enumerates the attributes available for customizing bindings for
Rust functions and `struct`s exported to JavaScript.

View File

@@ -0,0 +1,53 @@
# `inspectable`
By default, structs exported from Rust become JavaScript classes with a single `ptr` property. All other properties are implemented as getters, which are not displayed when calling `toJSON`.
The `inspectable` attribute can be used on Rust structs to provide a `toJSON` and `toString` implementation that display all readable fields. For example:
```rust
#[wasm_bindgen(inspectable)]
pub struct Baz {
pub field: i32,
private: i32,
}
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(constructor)]
pub fn new(field: i32) -> Baz {
Baz { field, private: 13 }
}
}
```
Provides the following behavior as in this JavaScript snippet:
```js
const obj = new Baz(3);
assert.deepStrictEqual(obj.toJSON(), { field: 3 });
obj.field = 4;
assert.strictEqual(obj.toString(), '{"field":4}');
```
One or both of these implementations can be overridden as desired. Note that the generated `toString` calls `toJSON` internally, so overriding `toJSON` will affect its output as a side effect.
```rust
#[wasm_bindgen]
impl Baz {
#[wasm_bindgen(js_name = toJSON)]
pub fn to_json(&self) -> i32 {
self.field
}
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
format!("Baz: {}", self.field)
}
}
```
Note that the output of `console.log` will remain unchanged and display only the `ptr` field in browsers. It is recommended to call `toJSON` or `JSON.stringify` in these situations to aid with logging or debugging. Node.js does not suffer from this limitation, see the section below.
## `inspectable` Classes in Node.js
When the `nodejs` target is used, an additional `[util.inspect.custom]` implementation is provided which calls `toJSON` internally. This method is used for `console.log` and similar functions to display all readable fields of the Rust struct.

View File

@@ -0,0 +1,28 @@
# `js_class = Blah`
The `js_class` attribute is used to indicate that all the methods inside an
`impl` block should be attached to the specified JS class instead of inferring
it from the self type in the `impl` block. The `js_class` attribute is most
frequently paired with [the `js_name` attribute](js_name.html) on structs:
```rust
#[wasm_bindgen(js_name = Foo)]
pub struct JsFoo { /* ... */ }
#[wasm_bindgen(js_class = Foo)]
impl JsFoo {
#[wasm_bindgen(constructor)]
pub fn new() -> JsFoo { /* ... */ }
pub fn foo(&self) { /* ... */ }
}
```
which is accessed like:
```rust
import { Foo } from './my_module';
const x = new Foo();
x.foo();
```

View File

@@ -0,0 +1,54 @@
# `js_name = Blah`
The `js_name` attribute can be used to export a different name in JS than what
something is named in Rust. It can be applied to both exported Rust functions
and types.
For example, this is often used to convert between Rust's snake-cased
identifiers into JavaScript's camel-cased identifiers:
```rust
#[wasm_bindgen(js_name = doTheThing)]
pub fn do_the_thing() -> u32 {
42
}
```
This can be used in JavaScript as:
```js
import { doTheThing } from './my_module';
const x = doTheThing();
console.log(x);
```
Like imports, `js_name` can also be used to rename types exported to JS:
```rust
#[wasm_bindgen(js_name = Foo)]
pub struct JsFoo {
// ..
}
```
to be accessed like:
```js
import { Foo } from './my_module';
// ...
```
Note that attaching methods to the JS class `Foo` should be done via the
[`js_class` attribute](js_class.html):
```rust
#[wasm_bindgen(js_name = Foo)]
pub struct JsFoo { /* ... */ }
#[wasm_bindgen(js_class = Foo)]
impl JsFoo {
// ...
}
```

View File

@@ -0,0 +1,39 @@
# `readonly`
When attached to a `pub` struct field this indicates that it's read-only from
JavaScript, and a setter will not be generated and exported to JavaScript.
```rust
#[wasm_bindgen]
pub fn make_foo() -> Foo {
Foo {
first: 10,
second: 20,
}
}
#[wasm_bindgen]
pub struct Foo {
pub first: u32,
#[wasm_bindgen(readonly)]
pub second: u32,
}
```
Here the `first` field will be both readable and writable from JS, but the
`second` field will be a `readonly` field in JS where the setter isn't
implemented and attempting to set it will throw an exception.
```js
import { make_foo } from "./my_module";
const foo = make_foo();
// Can both get and set `first`.
foo.first = 99;
console.log(foo.first);
// Can only get `second`.
console.log(foo.second);
```

View File

@@ -0,0 +1,46 @@
# `skip`
When attached to a `pub` struct field this indicates that field will not be exposed to JavaScript,
and neither getter nor setter will be generated in ES6 class.
```rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
pub bar: u32,
#[wasm_bindgen(skip)]
pub baz: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Self {
Foo {
bar: 1,
baz: 2
}
}
}
```
Here the `bar` field will be both readable and writable from JS, but the
`baz` field will be `undefined` in JS.
```js
import('./pkg/').then(rust => {
let foo = rust.Foo.new();
// bar is accessible by getter
console.log(foo.bar);
// field marked with `skip` is undefined
console.log(foo.baz);
// you can shadow it
foo.baz = 45;
// so accessing by getter will return `45`
// but it won't affect real value in rust memory
console.log(foo.baz);
});
```

View File

@@ -0,0 +1,42 @@
# `skip_typescript`
By default, Rust exports exposed to JavaScript will generate TypeScript definitions (unless `--no-typescript` is used). The `skip_typescript` attribute can be used to disable type generation per function, enum, struct, or field. For example:
```rust
#[wasm_bindgen(skip_typescript)]
pub enum MyHiddenEnum {
One,
Two,
Three
}
#[wasm_bindgen]
pub struct MyPoint {
pub x: u32,
#[wasm_bindgen(skip_typescript)]
pub y: u32,
}
#[wasm_bindgen]
impl MyPoint {
#[wasm_bindgen(skip_typescript)]
pub fn stringify(&self) -> String {
format!("({}, {})", self.x, self.y)
}
}
```
Will generate the following `.d.ts` file:
```ts
/* tslint:disable */
/* eslint-disable */
export class MyPoint {
free(): void;
x: number;
}
```
When combined with [the `typescript_custom_section` attribute](typescript_custom_section.html), this can be used to manually specify more specific function types instead of using the generated definitions.

View File

@@ -0,0 +1,31 @@
# `start`
When attached to a `pub` function this attribute will configure the `start`
section of the wasm executable to be emitted, executing the tagged function as
soon as the wasm module is instantiated.
```rust
#[wasm_bindgen(start)]
pub fn main() {
// executed automatically ...
}
```
The `start` section of the wasm executable will be configured to execute the
`main` function here as soon as it can. Note that due to various practical
limitations today the start section of the executable may not literally point to
`main`, but the `main` function here should be started up automatically when the
wasm module is loaded.
There's a few caveats to be aware of when using the `start` attribute:
* The `start` function must take no arguments and must either return `()` or
`Result<(), JsValue>`
* Only one `start` function can be placed into a module, including its
dependencies. If more than one is specified then `wasm-bindgen` will fail when
the CLI is run. It's recommended that only applications use this attribute.
* The `start` function will not be executed when testing.
* If you're experimenting with WebAssembly threads, the `start` function is
executed *once per thread*, not once globally!
* Note that the `start` function is relatively new, so if you find any bugs with
it, please feel free to report an issue!

View File

@@ -0,0 +1,34 @@
# `typescript_custom_section`
When added to a `const` `&'static str`, it will append the contents of the
string to the `.d.ts` file exported by `wasm-bindgen-cli` (when the
`--typescript` flag is enabled).
```rust
#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type Coords = { "latitude": number, "longitude": number, };
"#;
```
The primary target for this feature is for code generation. For example, you
can author a macro that allows you to export a TypeScript definition alongside
the definition of a struct or Rust type.
```rust
#[derive(MyTypescriptExport)]
struct Coords {
latitude: u32,
longitude: u32,
}
```
The proc_derive_macro "MyTypescriptExport" can export its own
`#[wasm_bindgen(typescript_custom_section)]` section, which would then be
picked up by wasm-bindgen-cli. This would be equivalent to the contents of
the TS_APPEND_CONTENT string in the first example.
This feature allows plain data objects to be typechecked in Rust and in
TypeScript by outputing a type definition generated at compile time.

View File

@@ -0,0 +1,56 @@
# typescript_type
The `typescript_type` allows us to use typescript declarations in `typescript_custom_section` as arguments for rust functions! For example:
```rust
#[wasm_bindgen(typescript_custom_section)]
const ITEXT_STYLE: &'static str = r#"
interface ITextStyle {
bold: boolean;
italic: boolean;
size: number;
}
"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "ITextStyle")]
pub type ITextStyle;
}
#[wasm_bindgen]
#[derive(Default)]
pub struct TextStyle {
pub bold: bool,
pub italic: bool,
pub size: i32,
}
#[wasm_bindgen]
impl TextStyle {
#[wasm_bindgen(constructor)]
pub fn new(_i: ITextStyle) -> TextStyle {
// parse JsValue
TextStyle::default()
}
pub fn optional_new(_i: Option<ITextStyle>) -> TextStyle {
// parse JsValueo
TextStyle::default()
}
}
```
We can write our `typescript` code like:
```ts
import { ITextStyle, TextStyle } from "./my_awesome_module";
const style: TextStyle = new TextStyle({
bold: true,
italic: true,
size: 42,
});
const optional_style: TextStyle = TextStyle.optional_new();
```

View File

@@ -0,0 +1,72 @@
# Supported Browsers
The output of `wasm-bindgen` includes a JS file, and as a result it's good to
know what browsers that file is expected to be used in! By default the output
uses ES modules which isn't implemented in all browsers today, but when using a
bundler (like Webpack) you should be able to produce output suitable for all
browsers.
Firefox, Chrome, Safari, and Edge browsers are all supported by
`wasm-bindgen`. If you find a problem in one of these browsers please [report
it] as we'd like to fix the bug! If you find a bug in another browser we would
also like to be aware of it!
## Caveats
* **IE 11** - `wasm-bindgen` by default requires support for
`WebAssembly`, but no version of IE currently supports `WebAssembly`. You can
support IE by [compiling wasm files to JS using `wasm2js`][w2js] (you can [see
an example of doing this too](../examples/wasm2js.html)). Note
that at this time no bundler will do this by default, but we'd love to
document plugins which do this if you are aware of one!
* **Edge before 79+** - the `TextEncoder` and `TextDecoder` APIs, which
`wasm-bindgen` uses to encode/decode strings between JS and Rust, were not
available before version 79. You can polyfill this with at least one of two
strategies:
1. If using a bundler, you can likely configure the bundler to polyfill these
types by default. For example if you're using Webpack you can use the
[`ProvidePlugin` interface][wpp] like so after also adding
[`text-encoding`] to your `package.json`
```js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
]
// ... other configuration options
};
```
**Warning:** doing this implies the polyfill will always be used,
even if native APIs are available. This has a very significant
performance impact (the polyfill was measured to be 100x slower in Chromium)!
2. If you're not using a bundler you can also include support manually by
adding a `<script>` tag which defines the `TextEncoder` and `TextDecoder`
globals. [This StackOverflow question][soq] has some example usage and MDN
has a [`TextEncoder` polyfill implementation][mdntepi] to get you started
as well.
* **BigInt and `u64`** - currently the WebAssembly specification for the web
forbids the usage of 64-bit integers (Rust types `i64` and `u64`) in
exported/imported functions. When using `wasm-bindgen`, however, `u64` is
allowed! The reason for this is that it's translated to the `BigInt` type in
JS. The `BigInt` class is supported by all major browsers starting in the
following versions: Chrome 67+, Firefox 68+, Edge 79+, and Safari 14+.
If you find other incompatibilities please report them to us! We'd love to
either keep this list up-to-date or fix the underlying bugs :)
[report it]: https://github.com/rustwasm/wasm-bindgen/issues/new
[w2js]: https://github.com/WebAssembly/binaryen
[wpp]: https://webpack.js.org/plugins/provide-plugin/
[`text-encoding`]: https://www.npmjs.com/package/text-encoding
[soq]: https://stackoverflow.com/questions/40662142/polyfill-for-textdecoder/46549188#46549188
[mdntepi]: https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder#Polyfill

View File

@@ -0,0 +1,101 @@
# The `wasm-bindgen` Command Line Interface
The `wasm-bindgen` command line tool has a number of options available to it to
tweak the JavaScript that is generated. The most up-to-date set of flags can
always be listed via `wasm-bindgen --help`.
## Installation
```
cargo install -f wasm-bindgen-cli
```
## Usage
```
wasm-bindgen [options] ./target/wasm32-unknown-unknown/release/crate.wasm
```
## Options
### `--out-dir DIR`
The target directory to emit the JavaScript bindings, TypeScript definitions,
processed `.wasm` binary, etc...
### `--target`
This flag indicates what flavor of output what `wasm-bindgen` should generate.
For example it could generate code to be loaded in a bundler like Webpack, a
native web page, or Node.js. For a full list of options to pass this flag, see
the section on [deployment]
[deployment]: deployment.html
### `--no-modules-global VAR`
When `--target no-modules` is used this flag can indicate what the name of the
global to assign generated bindings to.
For more information about this see the section on [deployment]
### `--typescript`
Output a TypeScript declaration file for the generated JavaScript bindings. This
is on by default.
### `--no-typescript`
By default, a `*.d.ts` TypeScript declaration file is generated for the
generated JavaScript bindings, but this flag will disable that.
### `--omit-imports`
When the `module` attribute is used with the `wasm-bindgen` macro, the code
generator will emit corresponding `import` or `require` statements in the header
section of the generated javascript. This flag causes those import statements to
be omitted. This is necessary for some use cases, such as generating javascript
which is intended to be used with Electron (with node integration disabled),
where the imports are instead handled through a separate preload script.
### `--debug`
Generates a bit more JS and wasm in "debug mode" to help catch programmer
errors, but this output isn't intended to be shipped to production.
### `--no-demangle`
When post-processing the `.wasm` binary, do not demangle Rust symbols in the
"names" custom section.
### `--keep-debug`
When post-processing the `.wasm` binary, do not strip DWARF debug info custom
sections.
### `--browser`
When generating bundler-compatible code (see the section on [deployment]) this
indicates that the bundled code is always intended to go into a browser so a few
checks for Node.js can be elided.
### `--weak-refs`
Enables usage of the [TC39 Weak References
proposal](https://github.com/tc39/proposal-weakrefs), ensuring that all Rust
memory is eventually deallocated regardless of whether you're calling `free` or
not. This is off-by-default while we're waiting for support to percolate into
all major browsers. For more information see the [documentation about weak
references](./weak-references.md).
### `--reference-types`
Enables usage of the [WebAssembly References Types
proposal](https://github.com/webassembly/reference-types) proposal, meaning that
the WebAssembly binary will use `externref` when importing and exporting
functions that work with `JsValue`. For more information see the [documentation
about reference types](./reference-types.md).
### `--omit-default-module-path`
Don't add WebAssembly fallback imports in generated JavaScript.

View File

@@ -0,0 +1,107 @@
# Deploying Rust and WebAssembly
At this point in time deploying Rust and WebAssembly to the web or other
locations unfortunately isn't a trivial task to do. This page hopes to serve
as documentation for the various known options, and as always PRs are welcome
to update this if it's out of date!
The methods of deployment and integration here are primarily tied to the
`--target` flag.
| Value | Summary |
|-----------------|------------------------------------------------------------|
| [`bundler`] | Suitable for loading in bundlers like Webpack |
| [`web`] | Directly loadable in a web browser |
| [`nodejs`] | Loadable via `require` as a Node.js module |
| [`deno`] | Loadable using imports from Deno modules |
| [`no-modules`] | Like `web`, but older and doesn't use ES modules |
[`bundler`]: #bundlers
[`web`]: #without-a-bundler
[`no-modules`]: #without-a-bundler
[`nodejs`]: #nodejs
[`deno`]: #Deno
## Bundlers
**`--target bundler`**
The default output of `wasm-bindgen`, or the `bundler` target, assumes a model
where the wasm module itself is natively an ES module. This model, however, is not
natively implemented in any JS implementation at this time. As a result, to
consume the default output of `wasm-bindgen` you will need a bundler of some
form.
> **Note**: the choice of this default output was done to reflect the trends of
> the JS ecosystem. While tools other than bundlers don't support wasm files as
> native ES modules today they're all very much likely to in the future!
Currently the only known bundler known to be fully compatible with
`wasm-bindgen` is [webpack]. Most [examples] use webpack, and you can check out
the [hello world example online] to see the details of webpack configuration
necessary.
[webpack]: https://webpack.js.org/
[examples]: ../examples/index.html
[hello world example online]: ../examples/hello-world.html
## Without a Bundler
**`--target web` or `--target no-modules`**
If you're not using a bundler but you're still running code in a web browser,
`wasm-bindgen` still supports this! For this use case you'll want to use the
`--target web` flag. You can check out a [full example][nomex] in the
documentation, but the highlights of this output are:
* When compiling you'll pass `--target web` to `wasm-bindgen`
* The output can natively be included on a web page, and doesn't require any
further postprocessing. The output is included as an ES module.
* The `--target web` mode is not able to use NPM dependencies.
* You'll want to review the [browser requirements] for `wasm-bindgen` because
no polyfills will be available.
[nomex]: ../examples/without-a-bundler.html
[rfc1]: https://github.com/rustwasm/rfcs/pull/6
[rfc2]: https://github.com/rustwasm/rfcs/pull/8
[browser requirements]: browser-support.html
The CLI also supports an output mode called `--target no-modules` which is
similar to the `web` target in that it requires manual initialization of the
wasm and is intended to be included in web pages without any further
postprocessing. See the [without a bundler example][nomex] for some more
information about `--target no-modules`.
## Node.js
**`--target nodejs`**
If you're deploying WebAssembly into Node.js (perhaps as an alternative to a
native module), then you'll want to pass the `--target nodejs` flag to `wasm-bindgen`.
Like the "without a bundler" strategy, this method of deployment does not
require any further postprocessing. The generated JS shims can be `require`'d
just like any other Node module (even the `*_bg` wasm file can be `require`'d
as it has a JS shim generated as well).
Note that this method requires a version of Node.js with WebAssembly support,
which is currently Node 8 and above.
## Deno
**`--target deno`**
To deploy WebAssembly to Deno, use the `--target deno` flag.
To then import your module inside deno, use
```ts
// @deno-types="./out/crate_name.d.ts"
import { yourFunction } from "./out/crate_name.js";
```
## NPM
If you'd like to deploy compiled WebAssembly to NPM, then the tool for the job
is [`wasm-pack`]. More information on this coming soon!
[`wasm-pack`]: https://rustwasm.github.io/docs/wasm-pack/

View File

@@ -0,0 +1,10 @@
# Reference
This section contains reference material for using `wasm-bindgen`. It is not
intended to be read start to finish. Instead, it aims to quickly answer
questions like:
* Is type X supported as a parameter in a Rust function exported to JavaScript?
* What was that CLI flag to disable ECMAScript modules output, and instead
attach the JavaScript bindings directly to `window`?

View File

@@ -0,0 +1,91 @@
# Iterating over JavaScript Values
## Methods That Return `js_sys::Iterator`
Some JavaScript collections have methods for iterating over their values or
keys:
* [`Map::values`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values)
* [`Set::keys`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys)
* etc...
These methods return
[`js_sys::Iterator`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html),
which is the Rust representation of a JavaScript object that has a `next` method
that either returns the next item in the iteration, notes that iteration has
completed, or throws an error. That is, `js_sys::Iterator` represents an object
that implements [the duck-typed JavaScript iteration
protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
`js_sys::Iterator` can be converted into a Rust iterator either by reference
(into
[`js_sys::Iter<'a>`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html))
or by value (into
[`js_sys::IntoIter`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html)). The
Rust iterator will yield items of type `Result<JsValue>`. If it yields an
`Ok(...)`, then the JS iterator protocol returned an element. If it yields an
`Err(...)`, then the JS iterator protocol threw an exception.
```rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn count_strings_in_set(set: &js_sys::Set) -> u32 {
let mut count = 0;
// Call `keys` to get an iterator over the set's elements. Because this is
// in a `for ... in ...` loop, Rust will automatically call its
// `IntoIterator` trait implementation to convert it into a Rust iterator.
for x in set.keys() {
// We know the built-in iterator for set elements won't throw
// exceptions, so just unwrap the element. If this was an untrusted
// iterator, we might want to explicitly handle the case where it throws
// an exception instead of returning a `{ value, done }` object.
let x = x.unwrap();
// If `x` is a string, increment our count of strings in the set!
if x.is_string() {
count += 1;
}
}
count
}
```
## Iterating Over <u>Any</u> JavaScript Object that Implements the Iterator Protocol
You could manually test for whether an object implements JS's duck-typed
iterator protocol, and if so, convert it into a `js_sys::Iterator` that you can
finally iterate over. You don't need to do this by-hand, however, since we
bundled this up as [the `js_sys::try_iter`
function!](https://rustwasm.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html)
For example, we can write a function that collects the numbers from any JS
iterable and returns them as an `Array`:
```rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn collect_numbers(some_iterable: &JsValue) -> Result<js_sys::Array, JsValue> {
let nums = js_sys::Array::new();
let iterator = js_sys::try_iter(some_iterable)?.ok_or_else(|| {
"need to pass iterable JS values!"
})?;
for x in iterator {
// If the iterator's `next` method throws an error, propagate it
// up to the caller.
let x = x?;
// If `x` is a number, add it to our array of numbers!
if x.as_f64().is_some() {
nums.push(&x);
}
}
Ok(nums)
}
```

View File

@@ -0,0 +1,121 @@
# Working with a JS `Promise` and a Rust `Future`
Many APIs on the web work with a `Promise`, such as an `async` function in JS.
Naturally you'll probably want to interoperate with them from Rust! To do that
you can use the `wasm-bindgen-futures` crate as well as Rust `async`
functions.
The first thing you might encounter is the need for working with a `Promise`.
For this you'll want to use [`js_sys::Promise`]. Once you've got one of those
values you can convert that value to `wasm_bindgen_futures::JsFuture`. This type
implements the `std::future::Future` trait which allows naturally using it in an
`async` function. For example:
[`js_sys::Promise`]: https://docs.rs/js-sys/*/js_sys/struct.Promise.html
```rust
async fn get_from_js() -> Result<JsValue, JsValue> {
let promise = js_sys::Promise::resolve(&42.into());
let result = wasm_bindgen_futures::JsFuture::from(promise).await?;
Ok(result)
}
```
Here we can see how converting a `Promise` to Rust creates a `impl Future<Output
= Result<JsValue, JsValue>>`. This corresponds to `then` and `catch` in JS where
a successful promise becomes `Ok` and an erroneous promise becomes `Err`.
You can also import a JS async function directly with a `extern "C"` block, and
the promise will be converted to a future automatically. For now the return type
must be `JsValue` or no return at all:
```rust
#[wasm_bindgen]
extern "C" {
async fn async_func_1() -> JsValue;
async fn async_func_2();
}
```
The `async` can be combined with the `catch` attribute to manage errors from the
JS promise:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(catch)]
async fn async_func_3() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
async fn async_func_4() -> Result<(), JsValue>;
}
```
Next up you'll probably want to export a Rust function to JS that returns a
promise. To do this you can use an `async` function and `#[wasm_bindgen]`:
```rust
#[wasm_bindgen]
pub async fn foo() {
// ...
}
```
When invoked from JS the `foo` function here will return a `Promise`, so you can
import this as:
```js
import { foo } from "my-module";
async function shim() {
const result = await foo();
// ...
}
```
## Return values of `async fn`
When using an `async fn` in Rust and exporting it to JS there's some
restrictions on the return type. The return value of an exported Rust function
will eventually become `Result<JsValue, JsValue>` where `Ok` turns into a
successfully resolved promise and `Err` is equivalent to throwing an exception.
The following types are supported as return types from an `async fn`:
* `()` - turns into a successful `undefined` in JS
* `T: Into<JsValue>` - turns into a successful JS value
* `Result<(), E: Into<JsValue>>` - if `Ok(())` turns into a successful
`undefined` and otherwise turns into a failed promise with `E` converted to a
JS value
* `Result<T: Into<JsValue>, E: Into<JsValue>>` - like the previous case except
both data payloads are converted into a `JsValue`.
Note that many types implement being converted into a `JsValue`, such as all
imported types via `#[wasm_bindgen]` (aka those in `js-sys` or `web-sys`),
primitives like `u32`, and all exported `#[wasm_bindgen]` types. In general,
you should be able to write code without having too many explicit conversions,
and the macro should take care of the rest!
## Using `wasm-bindgen-futures`
The `wasm-bindgen-futures` crate bridges the gap between JavaScript `Promise`s
and Rust `Future`s. Its `JsFuture` type provides conversion from a JavaScript
`Promise` into a Rust `Future`, and its `future_to_promise` function converts a
Rust `Future` into a JavaScript `Promise` and schedules it to be driven to
completion.
Learn more:
* [`wasm_bindgen_futures` on crates.io][crate]
* [`wasm-bindgen-futures` API documentation and example usage][docs]
[crate]: https://crates.io/crates/wasm-bindgen-futures
[docs]: https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/
## Compatibility with versions of `Future`
The current crate on crates.io, `wasm-bindgen-futures 0.4.*`, supports
`std::future::Future` and `async`/`await` in Rust. This typically requires Rust
1.39.0+ (as of this writing on 2019-09-05 it's the nightly channel of Rust).
If you're using the `Future` trait from the `futures` `0.1.*` crate then you'll
want to use the `0.3.*` track of `wasm-bindgen-futures` on crates.io.

View File

@@ -0,0 +1,79 @@
# JS Snippets
Often when developing a crate you want to run on the web you'll want to include
some JS code here and there. While [`js-sys`](https://docs.rs/js-sys) and
[`web-sys`](https://docs.rs/web-sys) cover many needs they don't cover
everything, so `wasm-bindgen` supports the ability to write JS code next to your
Rust code and have it included in the final output artifact.
To include a local JS file, you'll use the `#[wasm_bindgen(module)]` macro:
```rust
#[wasm_bindgen(module = "/js/foo.js")]
extern "C" {
fn add(a: u32, b: u32) -> u32;
}
```
This declaration indicates that all the functions contained in the `extern`
block are imported from the file `/js/foo.js`, where the root is relative to the
crate root (where `Cargo.toml` is located).
The `/js/foo.js` file will make its way to the final output when `wasm-bindgen`
executes, so you can use the `module` annotation in a library without having to
worry users of your library!
The JS file itself must be written with ES module syntax:
```js
export function add(a, b) {
return a + b;
}
```
A full design of this feature can be found in [RFC 6] as well if you're
interested!
[RFC 6]: https://github.com/rustwasm/rfcs/pull/6
### Using `inline_js`
In addition to `module = "..."` if you're a macro author you also have the
ability to use the `inline_js` attribute:
```rust
#[wasm_bindgen(inline_js = "export function add(a, b) { return a + b; }")]
extern "C" {
fn add(a: u32, b: u32) -> u32;
}
```
Using `inline_js` indicates that the JS module is specified inline in the
attribute itself, and no files are loaded from the filesystem. They have the
same limitations and caveats as when using `module`, but can sometimes be easier
to generate for macros themselves. It's not recommended for hand-written code to
make use of `inline_js` but instead to leverage `module` where possible.
### Caveats
While quite useful local JS snippets currently suffer from a few caveats which
are important to be aware of. Many of these are temporary though!
* Currently `import` statements are not supported in the JS file. This is a
restriction we may lift in the future once we settle on a good way to support
this. For now, though, js snippets must be standalone modules and can't import
from anything else.
* Only `--target web` and the default bundler output mode are supported. To
support `--target nodejs` we'd need to translate ES module syntax to CommonJS
(this is
planned to be done, just hasn't been done yet). Additionally to support
`--target no-modules` we'd have to similarly translate from ES modules to
something else.
* Paths in `module = "..."` must currently start with `/`, or be rooted at the
crate root. It is intended to eventually support relative paths like `./` and
`../`, but it's currently believed that this requires more support in
the Rust `proc_macro` crate.
As above, more detail about caveats can be found in [RFC 6].

View File

@@ -0,0 +1,49 @@
# Optimizing for Size with `wasm-bindgen`
The Rust and WebAssembly Working Group's [Game of Life tutorial][gol] has an
excellent section on [shrinking wasm code size][size], but there's a few
`wasm-bindgen`-specific items to mention as well!
First and foremost, `wasm-bindgen` is designed to be lightweight and a "pay only
for what you use" mentality. If you suspect that `wasm-bindgen` is bloating your
program that is a bug and we'd like to know about it! Please feel free to [file
an issue][issue], even if it's a question!
### What to profile
With `wasm-bindgen` there's a few different files to be measuring the size of.
The first of which is the output of the compiler itself, typically at
`target/wasm32-unknown-unknown/release/foo.wasm`. **This file is not optimized
for size and you should not measure it.** The output of the compiler when
linking with `wasm-bindgen` is by design larger than it needs to be, the
`wasm-bindgen` CLI tool will automatically strip all unneeded functionality out
of the binary.
This leaves us with two primary generated files to measure the size of:
* **Generated wasm** - after running the `wasm-bindgen` CLI tool you'll get a
file in `--out-dir` that looks like `foo_bg.wasm`. This file is the final
fully-finished artifact from `wasm-bindgen`, and it reflects the size of the
app you'll be publishing. All the optimizations [mentioned in the code size
tutorial][size] will help reduce the size of this binary, so feel free to go
crazy!
* **Generated JS** - the other file after running `wasm-bindgen` is a `foo.js`
file which is what's actually imported by other JS code. This file is already
generated to be as small as possible (not including unneeded functionality).
The JS, however, is not uglified or minified, but rather still human readable
and debuggable. It's expected that you'll run an uglifier or bundler of the JS
output to minimize it further in your application. If you spot a way we could
reduce the output JS size further (or make it more amenable to bundler
minification), please let us know!
### Example
As an example, the `wasm-bindgen` repository [contains an example][example]
about generating small wasm binaries and shows off how to generate a small wasm
file for adding two numbers.
[gol]: https://rustwasm.github.io/book/game-of-life/introduction.html
[size]: https://rustwasm.github.io/book/game-of-life/code-size.html
[issue]: https://github.com/rustwasm/wasm-bindgen/issues/new
[example]: https://rustwasm.github.io/docs/wasm-bindgen/examples/add.html

View File

@@ -0,0 +1,124 @@
# Passing Rust Closures to Imported JavaScript Functions
The `#[wasm_bindgen]` attribute supports Rust closures being passed to
JavaScript in two variants:
1. Stack-lifetime closures that should not be invoked by JavaScript again after
the imported JavaScript function that the closure was passed to returns.
2. Heap-allocated closures that can be invoked any number of times, but must be
explicitly deallocated when finished.
## Stack-Lifetime Closures
Closures with a stack lifetime are passed to JavaScript as either `&dyn Fn` or `&mut
dyn FnMut` trait objects:
```rust
// Import JS functions that take closures
#[wasm_bindgen]
extern "C" {
fn takes_immutable_closure(f: &dyn Fn());
fn takes_mutable_closure(f: &mut dyn FnMut());
}
// Usage
takes_immutable_closure(&|| {
// ...
});
let mut times_called = 0;
takes_mutable_closure(&mut || {
times_called += 1;
});
```
**Once these imported functions return, the closures that were given to them
will become invalidated, and any future attempts to call those closures from
JavaScript will raise an exception.**
Closures also support arguments and return values like exports do, for example:
```rust
#[wasm_bindgen]
extern "C" {
fn takes_closure_that_takes_int_and_returns_string(x: &dyn Fn(u32) -> String);
}
takes_closure_that_takes_int_and_returns_string(&|x: u32| -> String {
format!("x is {}", x)
});
```
## Heap-Allocated Closures
Sometimes the discipline of stack-lifetime closures is not desired. For example,
you'd like to schedule a closure to be run on the next turn of the event loop in
JavaScript through `setTimeout`. For this, you want the imported function to
return but the JavaScript closure still needs to be valid!
For this scenario, you need the `Closure` type, which is defined in the
`wasm_bindgen` crate, exported in `wasm_bindgen::prelude`, and represents a
"long lived" closure.
The `Closure` type is currently behind a feature which needs to be enabled:
```toml
[dependencies]
wasm-bindgen = {version = "^0.2", features = ["nightly"]}
```
The validity of the JavaScript closure is tied to the lifetime of the `Closure`
in Rust. **Once a `Closure` is dropped, it will deallocate its internal memory
and invalidate the corresponding JavaScript function so that any further
attempts to invoke it raise an exception.**
Like stack closures a `Closure` supports both `Fn` and `FnMut` closures, as well
as arguments and returns.
```rust
#[wasm_bindgen]
extern "C" {
fn setInterval(closure: &Closure<dyn FnMut()>, millis: u32) -> f64;
fn cancelInterval(token: f64);
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen]
pub struct Interval {
closure: Closure<dyn FnMut()>,
token: f64,
}
impl Interval {
pub fn new<F: 'static>(millis: u32, f: F) -> Interval
where
F: FnMut()
{
// Construct a new closure.
let closure = Closure::new(f);
// Pass the closure to JS, to run every n milliseconds.
let token = setInterval(&closure, millis);
Interval { closure, token }
}
}
// When the Interval is destroyed, cancel its `setInterval` timer.
impl Drop for Interval {
fn drop(&mut self) {
cancelInterval(self.token);
}
}
// Keep logging "hello" every second until the resulting `Interval` is dropped.
#[wasm_bindgen]
pub fn hello() -> Interval {
Interval::new(1_000, || log("hello"))
}
```

View File

@@ -0,0 +1,31 @@
# Receiving JavaScript Closures in Exported Rust Functions
You can use the `js-sys` crate to access JavaScript's `Function` type, and
invoke that function via `Function.prototype.apply` and
`Function.prototype.call`.
For example, we can wrap a `Vec<u32>` in a new type, export it to JavaScript,
and invoke a JavaScript closure on each member of the `Vec`:
```rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct VecU32 {
xs: Vec<u32>,
}
#[wasm_bindgen]
impl VecU32 {
pub fn each(&self, f: &js_sys::Function) {
let this = JsValue::null();
for &x in &self.xs {
let x = JsValue::from(x);
let _ = f.call1(&this, &x);
}
}
}
```
Since Rust has no function overloading, the `call#` method also requires a
number representing the amount of arguments passed to the JavaScript closure.

View File

@@ -0,0 +1,59 @@
# Support for Reference Types
WebAssembly recently has gained support for a new value type called `externref`.
Proposed in the [WebAssembly reference types
repo](https://github.com/webassembly/reference-types) this feature of
WebAssembly is hoped to enable more efficient communication between the host
(JS) and the wasm module. This feature removes the need for much of the JS glue
generated by `wasm-bindgen` because it can natively call APIs with JS values.
For example, this Rust function:
```rust
#[wasm_bindgen]
pub fn takes_js_value(a: &JsValue) {
// ...
}
```
generates this JS glue *without* reference types support:
```js
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error('out of js stack');
heap[--stack_pointer] = obj;
return stack_pointer;
}
export function takes_js_value(a) {
try {
wasm.takes_js_value(addBorrowedObject(a));
} finally {
heap[stack_pointer++] = undefined;
}
}
```
We can see here how under the hood the JS is managing a table of JS values which
are passed to the wasm binary, so wasm actually only works in indices. If we
pass the `--reference-types` flag to the CLI, however, the generated JS looks like:
```js
export function takes_js_value(a) {
wasm.takes_js_value(a);
}
```
And that's it! The WebAssembly binary takes the JS value directly and manages it
internally.
Currently this feature is supported in Firefox 79+ and Chrome. Support in other
browsers is likely coming soon! In Node.js this feature is behind the
`--experimental-wasm-anyref` flag, although the support does not currently align
with the upstream specification as of 14.6.0.

View File

@@ -0,0 +1,72 @@
# Supported Rust Targets
> **Note**: This section is about Rust target triples, not targets like node/web
> workers/browsers. More information on that coming soon!
The `wasm-bindgen` project is designed to target the `wasm32-unknown-unknown`
target in Rust. This target is a "bare bones" target for Rust which emits
WebAssembly as output. The standard library is largely inert as modules like
`std::fs` and `std::net` will simply return errors.
## Non-wasm targets
Note that `wasm-bindgen` also aims to compile on all targets. This means that it
should be safe, if you like, to use `#[wasm_bindgen]` even when compiling for
Windows (for example). For example:
```rust
#[wasm_bindgen]
pub fn add(a: u32, b: u32) -> u32 {
a + b
}
#[cfg(not(target_arch = "wasm32"))]
fn main() {
println!("1 + 2 = {}", add(1, 2));
}
```
This program will compile and work on all platforms, not just
`wasm32-unknown-unknown`. Note that imported functions with `#[wasm_bindgen]`
will unconditionally panic on non-wasm targets. For example:
```rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
fn main() {
log("hello!");
}
```
This program will unconditionally panic on all platforms other than
`wasm32-unknown-unknown`.
For better compile times, however, you likely want to only use `#[wasm_bindgen]`
on the `wasm32-unknown-unknown` target. You can have a target-specific
dependency like so:
```toml
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2"
```
And in your code you can use:
```rust
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn only_on_the_wasm_target() {
// ...
}
```
## Other Web Targets
The `wasm-bindgen` target does not support the `wasm32-unknown-emscripten` nor
the `asmjs-unknown-emscripten` targets. There are currently no plans to support
these targets either. All annotations work like other platforms on the targets,
retaining exported functions and causing all imports to panic.

View File

@@ -0,0 +1,5 @@
# Supported Rust Types and their JavaScript Representations
This section provides an overview of all the types that `wasm-bindgen` can send
and receive across the WebAssembly ABI boundary, and how they translate into
JavaScript.

View File

@@ -0,0 +1,17 @@
# `bool`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | Yes | Yes | A JavaScript boolean value |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/bool.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/bool.js}}
```

View File

@@ -0,0 +1,19 @@
# `Box<[JsValue]>`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | Yes | Yes | A JavaScript `Array` object |
Boxed slices of imported JS types and exported Rust types are also supported. `Vec<T>` is supported wherever `Box<[T]>` is.
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/boxed_js_value_slice.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/boxed_js_value_slice.js}}
```

View File

@@ -0,0 +1,21 @@
# Boxed Number Slices: `Box<[u8]>`, `Box<[i8]>`, `Box<[u16]>`, `Box<[i16]>`, `Box<[u32]>`, `Box<[i32]>`, `Box<[u64]>`, `Box<[i64]>`, `Box<[f32]>`, and `Box<[f64]>`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | Yes | Yes | A JavaScript `TypedArray` of the appropriate type (`Int32Array`, `Uint8Array`, etc...) |
Note that the contents of the slice are copied into the JavaScript `TypedArray`
from the Wasm linear memory when returning a boxed slice to JavaScript, and vice
versa when receiving a JavaScript `TypedArray` as a boxed slice in Rust.
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/boxed_number_slices.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/boxed_number_slices.js}}
```

View File

@@ -0,0 +1,17 @@
# `char`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | No | No | A JavaScript string value |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/char.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/char.js}}
```

View File

@@ -0,0 +1,20 @@
# Exported `struct Whatever` Rust Types
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | Yes | Yes | Yes | Yes | Yes | Instances of a `wasm-bindgen`-generated JavaScript `class Whatever { ... }` |
> **Note**: Public fields implementing Copy have automatically generated getters/setters.
> To generate getters/setters for non-Copy public fields, use #[wasm_bindgen(getter_with_clone)] for the struct
> or [implement getters/setters manually](https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-rust-exports/getter-and-setter.html).
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/exported_types.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/exported_types.js}}
```

View File

@@ -0,0 +1,17 @@
# Imported `extern Whatever;` JavaScript Types
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | Yes | No | Yes | Yes | Yes | Instances of the extant `Whatever` JavaScript class / prototype constructor |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/imported_types.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/imported_types.js}}
```

View File

@@ -0,0 +1,17 @@
# `JsValue`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | Yes | No | Yes | No | No | Any JavaScript value |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/js_value.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/js_value.js}}
```

View File

@@ -0,0 +1,17 @@
# Number Slices: `[u8]`, `[i8]`, `[u16]`, `[i16]`, `[u32]`, `[i32]`, `[u64]`, `[i64]`, `[f32]`, and `[f64]`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<&T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| No | Yes | Yes | No | No | No | A JavaScript `TypedArray` view of the Wasm memory for the boxed slice of the appropriate type (`Int32Array`, `Uint8Array`, etc) |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/number_slices.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/number_slices.js}}
```

View File

@@ -0,0 +1,17 @@
# Numbers: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `isize`, `usize`, `f32`, and `f64`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | Yes | Yes | A JavaScript number value |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/numbers.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/numbers.js}}
```

View File

@@ -0,0 +1,17 @@
# `*const T` and `*mut T`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | No | No | A JavaScript number value |
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/pointers.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/pointers.js}}
```

View File

@@ -0,0 +1,20 @@
# `Result<T, JsValue>`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| No | No | No | No | No | Yes | Same as `T`, or an exception |
The `Result` type can be returned from functions exported to JS as well as
closures in Rust. Only `Result<T, JsValue>` is supported where `T` can be
converted to JS. Whenever `Ok(val)` is encountered it's converted to JS and
handed off, and whenever `Err(error)` is encountered an exception is thrown in
JS with `error`.
You can use `Result` to enable handling of JS exceptions with `?` in Rust,
naturally propagating it upwards to the wasm boundary. Furthermore you can also
return custom types in Rust so long as they're all convertible to `JsValue`.
Note that if you import a JS function with `Result` you need
`#[wasm_bindgen(catch)]` to be annotated on the import (unlike exported
functions, which require no extra annotation). This may not be necessary in the
future though and it may work "as is"!.

View File

@@ -0,0 +1,49 @@
# `str`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| No | Yes | No | No | No | No | JavaScript string value |
Copies the string's contents back and forth between the JavaScript
garbage-collected heap and the Wasm linear memory with `TextDecoder` and
`TextEncoder`. If you don't want to perform this copy, and would rather work
with handles to JavaScript string values, use the `js_sys::JsString` type.
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/str.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/str.js}}
```
## UTF-16 vs UTF-8
Strings in JavaScript are encoded as UTF-16, but with one major exception: they
can contain unpaired surrogates. For some Unicode characters UTF-16 uses two
16-bit values. These are called "surrogate pairs" because they always come in
pairs. In JavaScript, it is possible for these surrogate pairs to be missing the
other half, creating an "unpaired surrogate".
When passing a string from JavaScript to Rust, it uses the `TextEncoder` API to
convert from UTF-16 to UTF-8. This is normally perfectly fine... unless there
are unpaired surrogates. In that case it will replace the unpaired surrogates
with U+FFFD (<28>, the replacement character). That means the string in Rust is
now different from the string in JavaScript!
If you want to guarantee that the Rust string is the same as the JavaScript
string, you should instead use `js_sys::JsString` (which keeps the string in
JavaScript and doesn't copy it into Rust).
If you want to access the raw value of a JS string, you can use `JsString::iter`,
which returns an `Iterator<Item = u16>`. This perfectly preserves everything
(including unpaired surrogates), but it does not do any encoding (so you
have to do that yourself!).
If you simply want to ignore strings which contain unpaired surrogates, you can
use `JsString::is_valid_utf16` to test whether the string contains unpaired
surrogates or not.

View File

@@ -0,0 +1,24 @@
# `String`
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| Yes | No | No | Yes | Yes | Yes | JavaScript string value |
Copies the string's contents back and forth between the JavaScript
garbage-collected heap and the Wasm linear memory with `TextDecoder` and
`TextEncoder`
> **Note**: Be sure to check out the [documentation for `str`](str.html) to
> learn about some caveats when working with strings between JS and Rust.
## Example Rust Usage
```rust
{{#include ../../../../examples/guide-supported-types-examples/src/string.rs}}
```
## Example JavaScript Usage
```js
{{#include ../../../../examples/guide-supported-types-examples/string.js}}
```

View File

@@ -0,0 +1,23 @@
# Support for Weak References
By default wasm-bindgen does not use the [TC39 weak references
proposal](https://github.com/tc39/proposal-weakrefs). This proposal just
advanced to stage 4 at the time of this writing, but it will still stake some
time for support to percolate into all the major browsers.
Without weak references your JS integration may be susceptible to memory leaks
in Rust, for example:
* You could forget to call `.free()` on a JS object, leaving the Rust memory
allocated.
* Rust closures converted to JS values (the `Closure` type) may not be executed
and cleaned up.
* Rust closures have `Closure::{into_js_value,forget}` methods which explicitly
do not free the underlying memory.
These issues are all solved with the weak references proposal in JS. The
`--weak-refs` flag to the `wasm-bindgen` CLI will enable usage of
`FinalizationRegistry` to ensure that all memory is cleaned up, regardless of
whether it's explicitly deallocated or not. Note that explicit deallocation
is always a possibility and supported, but if it's not called then memory will
still be automatically deallocated with the `--weak-refs` flag.

View File

@@ -0,0 +1,20 @@
# Working with Duck-Typed Interfaces
Liberal use of [the `structural`
attribute](./attributes/on-js-imports/structural.html) on imported methods,
getters, and setters allows you to define duck-typed interfaces. A duck-typed
interface is one where many different JavaScript objects that don't share the
same base class in their prototype chain and therefore are not `instanceof` the
same base can be used the same way.
## Defining a Duck-Typed Interface in Rust
```rust
{{#include ../../../examples/duck-typed-interfaces/src/lib.rs}}
```
## JavaScript Usage
```js
{{#include ../../../examples/duck-typed-interfaces/duck-typed-interfaces.js}}
```