mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-05 00:51:22 +00:00
Merge pull request #661 from fitzgen/guide-closures-and-attributes
Guide: closures and attributes
This commit is contained in:
commit
6d4d9150cb
@ -9,12 +9,29 @@
|
|||||||
- [What Just Happened?](./whirlwind-tour/what-just-happened.md)
|
- [What Just Happened?](./whirlwind-tour/what-just-happened.md)
|
||||||
- [What Else Can We Do?](./whirlwind-tour/what-else-can-we-do.md)
|
- [What Else Can We Do?](./whirlwind-tour/what-else-can-we-do.md)
|
||||||
- [Reference](./reference/index.md)
|
- [Reference](./reference/index.md)
|
||||||
- [Closures](./reference/closures.md)
|
- [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md)
|
||||||
|
- [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md)
|
||||||
- [No ES Modules](./reference/no-esm.md)
|
- [No ES Modules](./reference/no-esm.md)
|
||||||
- [Passing Arbitrary data](./reference/passing-data.md)
|
- [Passing Arbitrary data](./reference/passing-data.md)
|
||||||
- [Feature Reference](./reference/feature-reference.md)
|
- [Feature Reference](./reference/feature-reference.md)
|
||||||
- [Command Line Interface](./reference/cli.md)
|
- [Command Line Interface](./reference/cli.md)
|
||||||
- [Supported Types](./reference/types.md)
|
- [Supported Types](./reference/types.md)
|
||||||
|
- [`#[wasm_bindgen]` Attributes](./reference/attributes/index.md)
|
||||||
|
- [On JavaScript Imports](./reference/attributes/on-js-imports/index.md)
|
||||||
|
- [`catch`](./reference/attributes/on-js-imports/catch.md)
|
||||||
|
- [`constructor`](./reference/attributes/on-js-imports/constructor.md)
|
||||||
|
- [`getter` and `setter`](./reference/attributes/on-js-imports/getter-and-setter.md)
|
||||||
|
- [`js_class = "Blah"`](./reference/attributes/on-js-imports/js_class.md)
|
||||||
|
- [`js_name`](./reference/attributes/on-js-imports/js_name.md)
|
||||||
|
- [`js_namespace`](./reference/attributes/on-js-imports/js_namespace.md)
|
||||||
|
- [`method`](./reference/attributes/on-js-imports/method.md)
|
||||||
|
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
|
||||||
|
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
|
||||||
|
- [`structural`](./reference/attributes/on-js-imports/structural.md)
|
||||||
|
- [On Rust Exports](./reference/attributes/on-rust-exports/index.md)
|
||||||
|
- [`constructor`](./reference/attributes/on-rust-exports/constructor.md)
|
||||||
|
- [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md)
|
||||||
|
- [`readonly`](./reference/attributes/on-rust-exports/readonly.md)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -23,10 +40,8 @@
|
|||||||
- [JS Objects in Rust](./design/js-objects-in-rust.md)
|
- [JS Objects in Rust](./design/js-objects-in-rust.md)
|
||||||
- [Exporting a function to JS](./design/exporting-rust.md)
|
- [Exporting a function to JS](./design/exporting-rust.md)
|
||||||
- [Exporting a struct to JS](./design/exporting-rust-struct.md)
|
- [Exporting a struct to JS](./design/exporting-rust-struct.md)
|
||||||
- [Customizing exports](./design/export-customization.md)
|
|
||||||
- [Importing a function from JS](./design/importing-js.md)
|
- [Importing a function from JS](./design/importing-js.md)
|
||||||
- [Importing a class from JS](./design/importing-js-struct.md)
|
- [Importing a class from JS](./design/importing-js-struct.md)
|
||||||
- [Customizing imports](./design/import-customization.md)
|
|
||||||
- [Rust Type conversions](./design/rust-type-conversions.md)
|
- [Rust Type conversions](./design/rust-type-conversions.md)
|
||||||
- [Types in `wasm-bindgen`](./design/describe.md)
|
- [Types in `wasm-bindgen`](./design/describe.md)
|
||||||
- [`js-sys`](./js-sys.md)
|
- [`js-sys`](./js-sys.md)
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
# Customizing import behavior
|
|
||||||
|
|
||||||
The `#[wasm_bindgen]` macro supports a good amount of configuration for
|
|
||||||
controlling precisely how exports are exported and what they generate in JS.
|
|
||||||
This section is intended to hopefully be an exhaustive reference of the
|
|
||||||
possibilities!
|
|
||||||
|
|
||||||
* `readonly` - when attached to a `pub` struct field this indicates that it's
|
|
||||||
readonly from JS and a setter will not be generated.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[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.
|
|
||||||
|
|
||||||
* `constructor` - when attached to a Rust "constructor" it will make the
|
|
||||||
generated JS bindings callable as `new Foo()`, for example:
|
|
||||||
|
|
||||||
```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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Here this can be used in JS as:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { Foo } from './my_module';
|
|
||||||
|
|
||||||
const f = new Foo();
|
|
||||||
console.log(f.get_contents());
|
|
||||||
```
|
|
||||||
|
|
||||||
* `js_name` - this can be used to export a different name in JS than what
|
|
||||||
something is named in Rust, for example:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub struct Foo {
|
|
||||||
contents: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = makeFoo)]
|
|
||||||
pub fn make_foo() -> Foo {
|
|
||||||
Foo { contents: 6 }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
impl Foo {
|
|
||||||
#[wasm_bindgen(js_name = getContents)]
|
|
||||||
pub fn get_contents(&self) -> u32 {
|
|
||||||
self.contents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Here this can be used in JS as:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { makeFoo } from './my_module';
|
|
||||||
|
|
||||||
const foo = makeFoo();
|
|
||||||
console.log(foo.getContents());
|
|
||||||
```
|
|
@ -1,193 +0,0 @@
|
|||||||
# Customizing import behavior
|
|
||||||
|
|
||||||
The `#[wasm_bindgen]` macro supports a good amount of configuration for
|
|
||||||
controlling precisely how imports are imported and what they map to in JS. This
|
|
||||||
section is intended to hopefully be an exhaustive reference of the
|
|
||||||
possibilities!
|
|
||||||
|
|
||||||
* `catch` - this attribute allows catching a JS exception. This can be attached
|
|
||||||
to any imported function and the function must return a `Result` where the
|
|
||||||
`Err` payload is a `JsValue`, like so:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
#[wasm_bindgen(catch)]
|
|
||||||
fn foo() -> Result<(), JsValue>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If the imported function throws an exception then `Err` will be returned with
|
|
||||||
the exception that was raised, and 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!
|
|
||||||
|
|
||||||
* `constructor` - this is used to indicate that the function being bound should
|
|
||||||
actually translate to a `new` constructor in JS. The final argument must be a
|
|
||||||
type that's imported from JS, and it's what'll get used in JS:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(constructor)]
|
|
||||||
fn new() -> Foo;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This will attach the `new` function to the `Foo` type (implied by
|
|
||||||
`constructor`) and in JS when this function is called it will be equivalent to
|
|
||||||
`new Foo()`.
|
|
||||||
|
|
||||||
* `method` - this is the gateway to adding methods to imported objects or
|
|
||||||
otherwise accessing properties on objects via methods and such. This should be
|
|
||||||
done for doing the equivalent of expressions like `foo.bar()` in JS.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(method)]
|
|
||||||
fn work(this: &Foo);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The first argument of a `method` annotation must be a borrowed reference (not
|
|
||||||
mutable, shared) to the type that the method is attached to. In this case
|
|
||||||
we'll be able to call this method like `foo.work()` in JS (where `foo` has
|
|
||||||
type `Foo`).
|
|
||||||
|
|
||||||
In JS this invocation will correspond to accessing `Foo.prototype.work` and
|
|
||||||
then calling that when the import is called. Note that `method` by default
|
|
||||||
implies going through `prototype` to get a function pointer.
|
|
||||||
|
|
||||||
* `js_namespace` - this attribute indicates that the JS type is accessed through
|
|
||||||
a particular namespace. For example the `WebAssembly.Module` APIs are all
|
|
||||||
accessed through the `WebAssembly` namespace. The `js_namespace` can be
|
|
||||||
applied to any import and whenever the generated JS attempts to reference a
|
|
||||||
name (like a class or function name) it'll be accessed through this namespace.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(s: &str);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This is an example of how to bind `console.log(x)` in Rust. The `log` function
|
|
||||||
will be available in the Rust module and will be invoked as `console.log` in
|
|
||||||
JS.
|
|
||||||
|
|
||||||
* `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 JS 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\_".
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(method, getter)]
|
|
||||||
fn property(this: &Foo) -> u32;
|
|
||||||
#[wasm_bindgen(method, setter)]
|
|
||||||
fn set_property(this: &Foo, val: u32);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Here we're importing the `Foo` type and defining the ability to access each
|
|
||||||
object's `property` property. The first function here is a getter and will be
|
|
||||||
available in Rust as `foo.property()`, and the latter is the setter which is
|
|
||||||
accessible as `foo.set_property(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 {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(method, getter = property)]
|
|
||||||
fn assorted_method_name(this: &Foo) -> u32;
|
|
||||||
#[wasm_bindgen(method, setter = "property")]
|
|
||||||
fn some_other_method_name(this: &Foo, val: u32);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Properties in JS are accessed through `Object.getOwnPropertyDescriptor`. Note
|
|
||||||
that this typically only works for class-like-defined properties which aren't
|
|
||||||
just attached properties on any old object. For accessing any old property on
|
|
||||||
an object we can use the `structural` flag.
|
|
||||||
|
|
||||||
* `indexing_getter`, `indexing_setter` and `indexing_deleter` - these three
|
|
||||||
attributes can be combined with `method` to indicate that this is a indexing
|
|
||||||
getter, indexing setter or indexing deleter method. They are different from
|
|
||||||
`getter` and `setter` in a way that `getter` and `setter` can only access
|
|
||||||
properties that have a name corresponding to the function name or their
|
|
||||||
argument, but `indexing_getter`, `indexing_setter` and `indexing_deleter`
|
|
||||||
work in a dynamic manner, similarly to the indexing syntax in JS
|
|
||||||
(`object[propertyName]`), hence the name. Should always be used together with
|
|
||||||
the `structural` flag. For example:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type 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);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* `structural` - this is a flag to `method` annotations which indicates that the
|
|
||||||
method being accessed (or property with getters/setters) should be accessed in
|
|
||||||
a structural fashion. For example methods are *not* accessed through
|
|
||||||
`prototype` and properties are accessed on the object directly rather than
|
|
||||||
through `Object.getOwnPropertyDescriptor`.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(method, structural)]
|
|
||||||
fn bar(this: &Foo);
|
|
||||||
#[wasm_bindgen(method, getter, structural)]
|
|
||||||
fn baz(this: &Foo) -> u32;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The type here, `Foo`, is not required to exist in JS (it's not referenced).
|
|
||||||
Instead wasm-bindgen will generate shims that will access the passed in JS
|
|
||||||
value's `bar` property to or the `baz` property (depending on the function).
|
|
||||||
|
|
||||||
* `js_name = foo` - this can be used to bind to a different function in JS than
|
|
||||||
the identifier that's defined in Rust. For example you can also define
|
|
||||||
multiple signatures for a polymorphic function in JS as well:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
|
||||||
fn log_string(s: &str);
|
|
||||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
|
||||||
fn log_u32(n: u32);
|
|
||||||
#[wasm_bindgen(js_namespace = console, js_name = log)]
|
|
||||||
fn log_many(a: u32, b: JsValue);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
All of these functions will call `console.log` in JS, but each identifier
|
|
||||||
will have only one signature in Rust.
|
|
6
guide/src/reference/attributes/index.md
Normal file
6
guide/src/reference/attributes/index.md
Normal 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!
|
29
guide/src/reference/attributes/on-js-imports/catch.md
Normal file
29
guide/src/reference/attributes/on-js-imports/catch.md
Normal 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 {
|
||||||
|
// `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!
|
24
guide/src/reference/attributes/on-js-imports/constructor.md
Normal file
24
guide/src/reference/attributes/on-js-imports/constructor.md
Normal 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 {
|
||||||
|
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();
|
||||||
|
```
|
@ -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 {
|
||||||
|
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 {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
```
|
5
guide/src/reference/attributes/on-js-imports/index.md
Normal file
5
guide/src/reference/attributes/on-js-imports/index.md
Normal 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 { ... }`
|
||||||
|
block.
|
20
guide/src/reference/attributes/on-js-imports/js_class.md
Normal file
20
guide/src/reference/attributes/on-js-imports/js_class.md
Normal 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 {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
```
|
46
guide/src/reference/attributes/on-js-imports/js_name.md
Normal file
46
guide/src/reference/attributes/on-js-imports/js_name.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# `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 {
|
||||||
|
#[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 {
|
||||||
|
#[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 {
|
||||||
|
#[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.
|
21
guide/src/reference/attributes/on-js-imports/js_namespace.md
Normal file
21
guide/src/reference/attributes/on-js-imports/js_namespace.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# `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 {
|
||||||
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
|
fn log(s: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
log("hello, console!");
|
||||||
|
```
|
||||||
|
|
||||||
|
This is an example of how to bind `console.log` in Rust. The `log` function will
|
||||||
|
be available in the Rust module and will be invoked as `console.log` in
|
||||||
|
JavaScript.
|
26
guide/src/reference/attributes/on-js-imports/method.md
Normal file
26
guide/src/reference/attributes/on-js-imports/method.md
Normal 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 {
|
||||||
|
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) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
33
guide/src/reference/attributes/on-js-imports/module.md
Normal file
33
guide/src/reference/attributes/on-js-imports/module.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# `module = "blah"`
|
||||||
|
|
||||||
|
The `module` attributes configures the module from which items are imported. For
|
||||||
|
example,
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[wasm_bindgen(module = "wu/tang/clan")]
|
||||||
|
extern {
|
||||||
|
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 {
|
||||||
|
fn illmatic() -> u32;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
generates JavaScript import glue like:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let illmatic = this.illmatic;
|
||||||
|
```
|
@ -0,0 +1,25 @@
|
|||||||
|
# `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 {
|
||||||
|
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.
|
50
guide/src/reference/attributes/on-js-imports/structural.md
Normal file
50
guide/src/reference/attributes/on-js-imports/structural.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# `structural`
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why don't we always use the `structural` behavior?
|
||||||
|
|
||||||
|
In theory, it is faster since the prototype chain doesn't need to be traversed
|
||||||
|
every time the method or property is accessed, but today's optimizing JIT
|
||||||
|
compilers are really good about eliminating that cost. The real reason is to be
|
||||||
|
future compatible with the ["host bindings" proposal][host-bindings], which
|
||||||
|
requires that there be no JavaScript shim between the caller and the native host
|
||||||
|
function. In this scenario, the properties and methods *must* be resolved before
|
||||||
|
the wasm is instantiated.
|
||||||
|
|
||||||
|
[host-bindings]: https://github.com/WebAssembly/host-bindings/blob/master/proposals/host-bindings/Overview.md
|
@ -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());
|
||||||
|
```
|
4
guide/src/reference/attributes/on-rust-exports/index.md
Normal file
4
guide/src/reference/attributes/on-rust-exports/index.md
Normal 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.
|
24
guide/src/reference/attributes/on-rust-exports/js_name.md
Normal file
24
guide/src/reference/attributes/on-rust-exports/js_name.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# `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);
|
||||||
|
```
|
39
guide/src/reference/attributes/on-rust-exports/readonly.md
Normal file
39
guide/src/reference/attributes/on-rust-exports/readonly.md
Normal 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);
|
||||||
|
```
|
@ -1,65 +0,0 @@
|
|||||||
# Closures
|
|
||||||
|
|
||||||
The `#[wasm_bindgen]` attribute supports some Rust closures being passed to JS.
|
|
||||||
Examples of what you can do are:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
fn foo(a: &Fn()); // could also be `&mut FnMut()`
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Here a function `foo` is imported from JS where the first argument is a *stack
|
|
||||||
closure*. You can call this function with a `&Fn()` argument and JS will receive
|
|
||||||
a JS function. When the `foo` function returns, however, the JS function will be
|
|
||||||
invalidated and any future usage of it will raise an exception.
|
|
||||||
|
|
||||||
Closures also support arguments and return values like exports do, for example:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
type Foo;
|
|
||||||
|
|
||||||
fn bar(a: &Fn(u32, String) -> Foo);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Sometimes the stack behavior of these 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 JS
|
|
||||||
through `setTimeout`. For this you want the imported function to return but the
|
|
||||||
JS closure still needs to be valid!
|
|
||||||
|
|
||||||
To support this use case you can do:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
fn baz(a: &Closure<Fn()>);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `Closure` type is defined in the `wasm_bindgen` crate and represents a "long
|
|
||||||
lived" closure. The JS closure passed to `baz` is still valid after `baz`
|
|
||||||
returns, and the validity of the JS closure is tied to the lifetime of the
|
|
||||||
`Closure` in Rust. Once `Closure` is dropped it will deallocate its internal
|
|
||||||
memory and invalidate the corresponding JS function.
|
|
||||||
|
|
||||||
Like stack closures a `Closure` also supports `FnMut`:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
fn another(a: &Closure<FnMut() -> u32>);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
At this time you cannot [pass a JS closure to Rust][cbjs], you can only pass a
|
|
||||||
Rust closure to JS in limited circumstances.
|
|
||||||
|
|
||||||
[cbjs]: https://github.com/rustwasm/wasm-bindgen/issues/103
|
|
118
guide/src/reference/passing-rust-closures-to-js.md
Normal file
118
guide/src/reference/passing-rust-closures-to-js.md
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# 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 `&Fn` or `&mut
|
||||||
|
FnMut` trait objects:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Import JS functions that take closures
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern {
|
||||||
|
fn takes_immutable_closure(f: &Fn());
|
||||||
|
|
||||||
|
fn takes_mutable_closure(f: &mut 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 {
|
||||||
|
fn takes_closure_that_takes_int_and_returns_string(x: &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 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 {
|
||||||
|
fn setInterval(closure: &Closure<FnMut()>, millis: u32) -> f64;
|
||||||
|
fn cancelInterval(token: f64);
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
|
fn log(s: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct Interval {
|
||||||
|
closure: Closure<FnMut()>,
|
||||||
|
token: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interval {
|
||||||
|
pub fn new<F>(millis: u32, f: F) -> Interval
|
||||||
|
where
|
||||||
|
F: FnMut()
|
||||||
|
{
|
||||||
|
// Construct a new closure.
|
||||||
|
let closure = Closure::new(f);
|
||||||
|
|
||||||
|
// Pass the closuer 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"));
|
||||||
|
}
|
||||||
|
```
|
31
guide/src/reference/receiving-js-closures-in-rust.md
Normal file
31
guide/src/reference/receiving-js-closures-in-rust.md
Normal 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
|
||||||
|
extern crate js_sys;
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user