WebAssembly / Working with wasm-bindgen
wasm-bindgen◹ is an awesome tool made by rustwasm team, make it very easy to expose Rust’s data/functions to JavaScript and vice versa.
To use, you can add a #[wasm_bindgen]
as an annotation the code where you want to be exposed or import to/from JavaScript, for example:
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
With the above code, we import the alert()
function from JavaScript to Rust, and expose Rust’s greet()
function to JavaScript.
A Rust struct will be exposed as a class in JavaScript:
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -> Foo {
Foo { contents: 0 }
}
}
You can import an ES6 module to use in Rust:
#[wasm_bindgen(module = "./bar")]
extern "C" {
fn blah(bleh: &JsValue);
}
// blah() function is in bar.js
There are two attributes you need to know about, js_namespace
: indicates the JavaScript type for your binding, and js_name
for the function name. We can use them to import multiple signatures of a polymorphic JavaScript function, like this:
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_str(s: &str);
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(n: u32);
}
Using js_name
, you can rename not just function, but also classes or types, for example:
#[wasm_bindgen]
extern "C" {
// Import JavaScript's String type as JsString in Rust
#[wasm_bindgen(js_name = String)]
type JsString;
}
And if you’re renaming type names, you need to use js_class
attribute when binding a function of that type:
#[wasm_bindgen(method, js_class = "String", js_name = charAt)]
fn char_at(this: &JsString, index: u32) -> JsString;
The web_sys
crate also provides some good binding from JS:
use web_sys::console;
console::log_1(&"Hello using web-sys".into());
Finnaly, use wasm-pack◹ to build your Rust project into a WebAssembly module, then use it in your JavaScript project.
wasm-pack build
If you’re using TypeScript or NodeJS, you might want to take a look at wasm-bindgen command line tool https://rustwasm.github.io/wasm-bindgen/reference/cli.html◹
If you’re working with various data type/struct, it’s very helpful to use serde for serializing/deserializing into and from JS. See more at https://rustwasm.github.io/wasm-bindgen/reference/arbitrary-data-with-serde.html◹