wasm-bindgen

    Yew uses wasm-bindgen to interact with the browser through a number of crates:

    This section will explore some of these crates in a high level in order to make it easier to understand and use wasm-bindgen APIs with Yew. For a more in-depth guide to wasm-bindgen and its associated crates then check out The wasm-bindgen Guide.

    For documentation on the above crates check out .

    提示

    Use the wasm-bindgen doc.rs search to find browser APIs and JavaScript types that have been imported over using wasm-bindgen.

    This crate provides many of the building blocks for the rest of the crates above. In this section we are only going to cover two main areas of the wasm-bindgen crate and that is the macro and some types / traits you will see pop up again and again.

    The #[wasm_bindgen] macro provides an interface between Rust and JavaScript, providing a system for translating between the two. Using this macro is more advanced, and you shouldn’t need to reach for it unless you are trying to use an external JavaScript library. The js-sys and web-sys crates expose wasm-bindgen definitions for built-in Javascript types and browser APIs.

    Let’s go over a simple example of using the #[wasm-bindgen] macro to import some specific flavours of the console.log function.

    This example was adapted from .

    Simulating inheritance

    Inheritance between JavaScript classes is a core feature of the Javascript language, and the DOM (Document Object Model) is designed around it. When types are imported using wasm-bindgen you can also add attributes that describe their inheritance.

    In Rust this inheritance is represented using the and AsRef traits. An example of this might help; so say you have three types A, B, and C where C extends B which in turn extends A.

    When importing these types the #[wasm-bindgen] macro will implement the Deref and AsRef traits in the following way:

    • B can Deref to
    • C can be AsRef to B
    • Both C & B can be AsRef to A

    Its important to note that every single type imported using #[wasm-bindgen] has the same root type, you can think of it as the A in the example above, this type is which has its own section below.

    extends section in The wasm-bindgen Guide

    This is a representation of an object owned by JavaScript, this is a root catch-all type for wasm-bindgen. Any type that comes from wasm-bindgen is a JsValue and this is because JavaScript doesn’t have a strong type system so any function that accepts a variable x doesn’t define its type so x can be a valid JavaScript value; hence JsValue. If you are working with imported functions or types that accept a JsValue, then any imported value is technically valid.

    JsValue can be accepted by a function but that function may still only accept certain types and this can lead to panics - so when using raw wasm-bindgen APIs check the documentation of the JavaScript being imported as to whether an exception (panic) will be raised if that value is not a certain type.

    JsValue documentation.

    JsCast

    Rust has a strong type system and JavaScript…doesn’t 😞. In order for Rust to maintain these strong types but still be convenient the WebAssembly group came up with a pretty neat trait JsCast. Its job is to help you move from one JavaScript “type” to another, which sounds vague, but it means that if you have one type which you know is really another then you can use the functions of JsCast to jump from one type to the other. It’s a nice trait to get to know when working with web-sys, wasm_bindgen, - you’ll notice lots of types will implement JsCast from those crates.

    JsCast provides both checked and unchecked methods of casting - so that at runtime if you are unsure what type a certain object is you can try to cast it which returns possible failure types like and Result.

    A common example of this in is when you are trying to get the target of an event, you might know what the target element is but the web_sys::Event API will always return an so you will need to cast it to the element type. so you can call its methods.

    The dyn_ref method is a checked cast that returns an Option<&T> which means the original type can be used again if the cast failed and thus returned None. The method will consume self, as per convention for into methods in Rust, and the type returned is Result<T, Self>. If the casting fails, the original Self value is returned in Err. You can try again or do something else with the original type.

    JsCast documentation.

    The Closure type provides a way to transfer Rust closures to JavaScript, the closures passed to JavaScript must have a 'static lifetime for soundness reasons.

    This type is a “handle” in the sense that whenever it is dropped it will invalidate the JS closure that it refers to. Any usage of the closure in JS after the Closure has been dropped will raise an exception.

    Closure documentation.

    The js-sys crate provides bindings / imports of JavaScript’s standard, built-in objects, including their methods and properties.

    This does not include any web APIs as this is what web-sys is for!

    .

    The wasm-bindgen-futures crate provides a bridge for working with JavaScript Promise types as a Rust , and contains utilities to turn a rust Future into a JavaScript Promise. This can be useful when working with asynchronous or otherwise blocking work in Rust (wasm), and provides the ability to interoperate with JavaScript events and JavaScript I/O primitives.

    There are three main interfaces in this crate currently:

    1. JsFuture - A type that is constructed with a and can then be used as a Future<Output=Result<JsValue, JsValue>>. This Rust future will resolve or reject with the value coming out of the Promise.

    2. future_to_promise - Converts a Rust Future<Output=Result<JsValue, JsValue>> into a JavaScript Promise. The future’s result will translate to either a resolved or rejected Promise in JavaScript.

    3. - Spawns a Future<Output = ()> on the current thread. This is the best way to run a Future in Rust without sending it to JavaScript.

    wasm-bindgen-futures documentation.

    spawn_local

    spawn_local is going to be the most commonly used part of the wasm-bindgen-futures crate in Yew as this helps when using libraries that have async APIs.

    Yew has also added support for futures in certain APIs, most notably you can create a callback_future which accepts an async block - this uses spawn_local internally.