wasm-bindgen/guide/src/closures.md
Nick Fitzgerald 7c9973d9d1 guide: Add the wasm-bindgen guide
Essentially split up the monolithic README.md into an `mdbook`.
2018-06-19 12:05:27 -07:00

1.8 KiB

Closures

The #[wasm_bindgen] attribute supports some Rust closures being passed to JS. Examples of what you can do are:

#[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:

#[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:

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:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
    fn another(a: &Closure<FnMut() -> u32>);
}

At this time you cannot pass a JS closure to Rust, you can only pass a Rust closure to JS in limited circumstances.