| # Design of `wasm-bindgen` |
| |
| This section is intended to be a deep-dive into how `wasm-bindgen` internally |
| works today, specifically for Rust. If you're reading this far in the future it |
| may no longer be up to date, but feel free to open an issue and we can try to |
| answer questions and/or update this! |
| |
| ## Foundation: ES Modules |
| |
| The first thing to know about `wasm-bindgen` is that it's fundamentally built on |
| the idea of ES Modules. In other words this tool takes an opinionated stance |
| that wasm files *should be viewed as ES modules*. This means that you can |
| `import` from a wasm file, use its `export`-ed functionality, etc, from normal |
| JS files. |
| |
| Now unfortunately at the time of this writing the interface of wasm interop |
| isn't very rich. Wasm modules can only call functions or export functions that |
| deal exclusively with `i32`, `i64`, `f32`, and `f64`. Bummer! |
| |
| That's where this project comes in. The goal of `wasm-bindgen` is to enhance the |
| "ABI" of wasm modules with richer types like classes, JS objects, Rust structs, |
| strings, etc. Keep in mind, though, that everything is based on ES Modules! This |
| means that the compiler is actually producing a "broken" wasm file of sorts. The |
| wasm file emitted by rustc, for example, does not have the interface we would |
| like to have. Instead it requires the `wasm-bindgen` tool to postprocess the |
| file, generating a `foo.js` and `foo_bg.wasm` file. The `foo.js` file is the |
| desired interface expressed in JS (classes, types, strings, etc) and the |
| `foo_bg.wasm` module is simply used as an implementation detail (it was |
| lightly modified from the original `foo.wasm` file). |
| |
| As more features are stabilized in WebAssembly over time (like component model) |
| the JS file is expected to get smaller and smaller. It's unlikely to ever |
| disappear, but `wasm-bindgen` is designed to follow the WebAssembly spec and |
| proposals closely to optimize JS/Rust as much as possible. |
| |
| ## Foundation #2: Unintrusive in Rust |
| |
| On the more Rust-y side of things the `wasm-bindgen` crate is designed to |
| ideally have as minimal impact on a Rust crate as possible. Ideally a few |
| `#[wasm_bindgen]` attributes are annotated in key locations and otherwise you're |
| off to the races. The attribute strives to both not invent new syntax and work |
| with existing idioms today. |
| |
| For example a library might exposed a function in normal Rust that looks like: |
| |
| ```rust |
| pub fn greet(name: &str) -> String { |
| // ... |
| } |
| ``` |
| |
| And with `#[wasm_bindgen]` all you need to do in exporting it to JS is: |
| |
| ```rust |
| #[wasm_bindgen] |
| pub fn greet(name: &str) -> String { |
| // ... |
| } |
| ``` |
| |
| Additionally the design here with minimal intervention in Rust should allow us |
| to easily take advantage of the upcoming [component model][component-model] proposal. Ideally |
| you'd simply upgrade `wasm-bindgen`-the-crate as well as your toolchain and |
| you're immediately getting raw access to component model! (this is still a bit of |
| a ways off though...) |
| |
| [component-model]: https://github.com/WebAssembly/component-model |