wasm-bindgen
!Rust generated bindings between JS and WebAssembly
wasm-bindgen
Facilitating high-level interactions between wasm modules and JavaScript
wasm-bindgen
Facilitating high-level interactions between wasm modules and JavaScript
wasm-bindgen
Facilitating high-level interactions between wasm modules and JavaScript
wasm-bindgen
Facilitating high-level interactions between wasm modules and JavaScript
wasm-bindgen
dowasm-bindgen
Featureswasm-bindgen
evenwasm-bindgen
dowasm-bindgen
is an unusual bindgenwasm-bindgen
is an unusual bindgenwasm-bindgen
is an unusual bindgenwasm-bindgen
generates JavaScript!wasm-bindgen
generates JavaScript!wasm-bindgen
wasm
) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.(module (func $addTwo (param i32 i32) (result i32) (i32.add (get_local 0) (get_local 1))) (export "addTwo" $addTwo))
wasm
wasm
?
i32
, i64
, f32
, and f64
.wasm
is the ABI of the Web...wasm
is the ABI of the Web...wasm
is not trying to replace JavaScriptwasm
to surgically replace hotpaths in JavaScript//Cargo.toml[lib]crate-type = ["cdylib"][dependencies]wasm-bindgen = "0.2"
// lib.rs#![feature(use_extern_macros)]extern crate wasm_bindgen;use wasm_bindgen::prelude::*;#[wasm_bindgen]extern { fn alert(s: &str);}#[wasm_bindgen]pub fn greet(name: &str) { alert(&format!("Hello, {}!", name));}
cargo install wasm-pack
wasm-pack publish
{ "scripts": { "start": "webpack-dev-server" }, "dependencies": { "hello-wasm": "^6.6.6" }, "devDependencies": { "webpack": "^4.0.1", "webpack-cli": "^2.0.10", "webpack-dev-server": "^3.1.0" }}
wasm
#[wasm_bindgen]
attributewasm-bindgen
CLI#[wasm_bindgen]extern { type Shoes; #[wasm_bindgen(constructor)] fn new() -> Shoes;}
// Become a cobbler; construct new Shoes()let shoes = Shoes::new();
#[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 }}
import { Foo } from './my_module';const f = new Foo();console.log(f.get_contents());
#[wasm_bindgen]extern { type Set; #[wasm_bindgen(method)] fn has(this: &Set, element: &JsValue) -> bool;}
let set: Set = ...;let elem: JsValue = ...;if set.has(&elem) { ...}
extends
#[wasm_bindgen]extern { type Foo; #[wasm_bindgen(extends = Foo)] type Bar;}let x: &Bar = ...;let y: &Foo = x.as_ref(); // zero cost cast
impl From<Bar> for Foo { ... }impl AsRef<Foo> for Bar { ... }impl AsMut<Foo> for Bar { ... }
extends
#[wasm_bindgen]extern { 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 = x.as_ref();
js-sys
and web-sys
js-sys
Provide raw bindings to all the global APIs guaranteed to exist in every JavaScript environment by the ECMAScript standard without writing the #[wasm_bindgen]
imports by hand.
extern crate js_sys;extern crate wasm_bindgen;use wasm_bindgen::prelude::*;#[wasm_bindgen]pub fn timed(callback: &js_sys::Function) -> f64 { let then = js_sys::Date::now(); callback.apply(JsValue::null(), &js_sys::Array::new()).unwrap(); let now = js_sys::Date::now(); now - then}
web-sys
The web-sys crate provides raw bindings to all of the Web's APIs, and its source lives at wasm-bindgen/crates/web-sys.
The web-sys crate is entirely mechanically generated inside build.rs using wasm-bindgen's WebIDL frontend and the WebIDL interface definitions for Web APIs.
wasm-bindgen
evenu32
for wasm
to use?pub struct JsValue { idx: u32,}// "private" constructorsimpl Drop for JsValue { fn drop(&mut self) { unsafe { __wbindgen_object_drop_ref(self.idx); } }}
// foo.rs#[wasm_bindgen]pub fn foo(a: &JsValue) { // ...}
Here we're using the special JsValue
type from the wasm-bindgen
library itself. Our exported function, foo, takes a reference to an object. This notably means that it can't persist the object past the lifetime of this function call.
Now what we actually want to generate is a JS module that looks like (in Typescript parlance):
// foo.d.tsexport function foo(a: any);
// foo.jsimport * as wasm from './foo_bg';const stack = [];function addBorrowedObject(obj) { stack.push(obj); return stack.length - 1;}export function foo(arg0) { const idx0 = addBorrowedObject(arg0); try { wasm.foo(idx0); } finally { stack.pop(); }}
// what the user wrotepub fn foo(a: &JsValue) { // ...}// what got gen'd#[export_name = "foo"]pub extern fn __wasm_bindgen_generated_foo(arg0: u32) { let arg0 = unsafe { ManuallyDrop::new(JsValue::__from_idx(arg0)) }; let arg0 = &*arg0; foo(arg0);}
wasm-bindgen
is that you don't have to worry about how it works.wasm-bindgen
is that you don't have to worry about how it works.
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |