wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript
Top Related Projects
Emscripten: An LLVM-to-WebAssembly Compiler
🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
A TypeScript-like language for WebAssembly.
The WebAssembly Binary Toolkit
A fast and secure runtime for WebAssembly
Quick Overview
wasm-bindgen is a project that facilitates high-level interactions between Rust and JavaScript, specifically for WebAssembly. It allows developers to create and work with JavaScript objects and functions from Rust, and vice versa, making it easier to integrate Rust code into web applications.
Pros
- Seamless integration between Rust and JavaScript for WebAssembly projects
- Automatic generation of JavaScript bindings for Rust code
- Supports complex data types and async functions
- Extensive documentation and examples
Cons
- Learning curve for developers new to Rust or WebAssembly
- Overhead in terms of code size and performance for small projects
- Limited support for some advanced JavaScript features
- Occasional breaking changes in newer versions
Code Examples
- Basic function export:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
This example exports a simple Rust function to be called from JavaScript.
- Working with JavaScript types:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
pub type Date;
#[wasm_bindgen(static_method_of = Date)]
pub fn now() -> f64;
}
#[wasm_bindgen]
pub fn get_current_time() -> f64 {
Date::now()
}
This code demonstrates how to use JavaScript's Date
object from Rust.
- Async functions:
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, Response};
#[wasm_bindgen]
pub async fn fetch_data(url: String) -> Result<JsValue, JsValue> {
let window = web_sys::window().unwrap();
let resp_value = JsFuture::from(window.fetch_with_str(&url)).await?;
let resp: Response = resp_value.dyn_into().unwrap();
let json = JsFuture::from(resp.json()?).await?;
Ok(json)
}
This example shows how to create an async function that fetches data from a URL using the Fetch API.
Getting Started
-
Add wasm-bindgen to your Cargo.toml:
[dependencies] wasm-bindgen = "0.2"
-
Use the
wasm-bindgen
attribute on functions you want to export:use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn greet(name: &str) -> String { format!("Hello, {}!", name) }
-
Build your project with
wasm-pack
:wasm-pack build --target web
-
Import and use the generated JavaScript module in your web application.
Competitor Comparisons
Emscripten: An LLVM-to-WebAssembly Compiler
Pros of Emscripten
- Supports multiple languages (C, C++, etc.), not just Rust
- More mature project with a larger ecosystem and community
- Provides a more complete runtime environment, including a virtual file system
Cons of Emscripten
- Generally produces larger output files compared to wasm-bindgen
- Can be more complex to set up and use, especially for simpler projects
- May include unnecessary features for projects that don't require a full runtime environment
Code Comparison
Emscripten (C++):
#include <emscripten.h>
#include <iostream>
EMSCRIPTEN_KEEPALIVE
extern "C" void greet(const char* name) {
std::cout << "Hello, " << name << "!" << std::endl;
}
wasm-bindgen (Rust):
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(name: &str) {
println!("Hello, {}!", name);
}
Both examples show how to export a simple greeting function to JavaScript. Emscripten requires explicit use of EMSCRIPTEN_KEEPALIVE
and extern "C"
, while wasm-bindgen uses the #[wasm_bindgen]
attribute for similar functionality.
🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
Pros of Wasmer
- More versatile: Supports multiple languages and can run WebAssembly outside the browser
- Standalone runtime: Can execute Wasm modules independently without relying on a browser environment
- Advanced features: Offers memory management, caching, and cross-compilation capabilities
Cons of Wasmer
- Steeper learning curve: Requires more setup and configuration compared to wasm-bindgen
- Larger footprint: Generally has a bigger size and resource usage due to its comprehensive features
- Less focused on JavaScript interop: Not as streamlined for web-specific use cases as wasm-bindgen
Code Comparison
wasm-bindgen:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Wasmer:
use wasmer::{imports, Instance, Module, Store};
let module = Module::from_file(&store, "add.wasm")?;
let instance = Instance::new(&module, &imports! {})?;
let add = instance.exports.get_function("add")?;
let result = add.call(&[Value::I32(5), Value::I32(37)])?;
This comparison highlights the simplicity of wasm-bindgen for web-focused projects, while Wasmer offers more flexibility and power for broader WebAssembly use cases.
A TypeScript-like language for WebAssembly.
Pros of AssemblyScript
- Easier learning curve for JavaScript developers
- Supports a subset of TypeScript syntax
- Faster compilation times compared to Rust
Cons of AssemblyScript
- Less mature ecosystem and tooling
- Limited access to low-level optimizations
- Smaller community and fewer resources
Code Comparison
AssemblyScript:
export function add(a: i32, b: i32): i32 {
return a + b;
}
wasm-bindgen (Rust):
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
Key Differences
- AssemblyScript uses TypeScript-like syntax, making it more familiar to JavaScript developers
- wasm-bindgen requires Rust knowledge but offers more low-level control and optimization possibilities
- AssemblyScript has a simpler setup process, while wasm-bindgen requires additional Rust tooling
- wasm-bindgen benefits from Rust's strong type system and memory safety features
- AssemblyScript compilation is generally faster, but wasm-bindgen produces more optimized WebAssembly code
Both projects aim to simplify WebAssembly development, but they cater to different developer preferences and use cases. AssemblyScript is more accessible for web developers, while wasm-bindgen leverages Rust's performance and safety features.
The WebAssembly Binary Toolkit
Pros of wabt
- Language-agnostic: Works with multiple programming languages, not limited to Rust
- Comprehensive toolset: Includes assembler, disassembler, and other utilities for WebAssembly
- Lower-level control: Provides more direct manipulation of WebAssembly modules
Cons of wabt
- Steeper learning curve: Requires more in-depth knowledge of WebAssembly internals
- Less automated: Manual handling of JavaScript interop and memory management
- Limited high-level abstractions: Focuses on low-level WebAssembly operations
Code Comparison
wabt (C++):
#include <cstdio>
#include "src/binary-reader.h"
#include "src/error-formatter.h"
void ReadBinaryFile(const char* filename) {
// Implementation details
}
wasm-bindgen (Rust):
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
The wabt example shows low-level binary reading, while wasm-bindgen demonstrates high-level JavaScript interop.
A fast and secure runtime for WebAssembly
Pros of wasmtime
- Broader scope: Wasmtime is a general-purpose WebAssembly runtime, supporting various languages and use cases beyond just Rust-to-WebAssembly interop
- Standalone execution: Can run WebAssembly modules directly, without requiring a web browser or JavaScript environment
- Performance-focused: Implements advanced optimization techniques for faster WebAssembly execution
Cons of wasmtime
- Higher complexity: As a full runtime, it may be more complex to set up and use compared to wasm-bindgen's focused approach
- Less integrated with Rust: Doesn't provide the same level of seamless Rust-to-WebAssembly integration as wasm-bindgen
Code comparison
wasm-bindgen:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
wasmtime:
let engine = Engine::default();
let module = Module::from_file(&engine, "add.wasm")?;
let instance = Instance::new(&mut store, &module, &[])?;
let add = instance.get_func(&mut store, "add")?;
let result = add.call(&mut store, &[Val::I32(1), Val::I32(2)])?;
This comparison highlights the different approaches: wasm-bindgen focuses on seamless Rust-to-WebAssembly integration, while wasmtime provides a more general-purpose runtime for executing WebAssembly modules.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript.
Guide (main branch) | API Docs | Contributing | Chat
Built with ð¦ð¸ by The Rust and WebAssembly Working Group
Install wasm-bindgen-cli
You can install it using cargo install
:
cargo install wasm-bindgen-cli
Or, you can download it from the release page.
If you have cargo-binstall
installed,
then you can install the pre-built artifacts by running:
cargo binstall wasm-bindgen-cli
Example
Import JavaScript things into Rust and export Rust things to JavaScript.
use wasm_bindgen::prelude::*;
// Import the `window.alert` function from the Web.
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
// Export a `greet` function from Rust to JavaScript, that alerts a
// hello message.
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
Use exported Rust things from JavaScript with ECMAScript modules!
import { greet } from "./hello_world";
greet("World!");
Features
-
Lightweight. Only pay for what you use.
wasm-bindgen
only generates bindings and glue for the JavaScript imports you actually use and Rust functionality that you export. For example, importing and using thedocument.querySelector
method doesn't causeNode.prototype.appendChild
orwindow.alert
to be included in the bindings as well. -
ECMAScript modules. Just import WebAssembly modules the same way you would import JavaScript modules. Future compatible with WebAssembly modules and ECMAScript modules integration.
-
Designed with the "Web IDL bindings" proposal in mind. Eventually, there won't be any JavaScript shims between Rust-generated wasm functions and native DOM methods. Because the Wasm functions are statically type checked, some of those native methods' dynamic type checks should become unnecessary, promising to unlock even-faster-than-JavaScript DOM access.
Guide
ð Read the wasm-bindgen
guide here! ð
You can find general documentation about using Rust and WebAssembly together here.
API Docs
MSRV Policy
Libraries that are released on crates.io have a MSRV of v1.57. Changes to the MSRV will be accompanied by a minor version bump.
CLI tools and their corresponding support libraries have a MSRV of v1.76. Changes to the MSRV will be accompanied by a patch version bump.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
See the "Contributing" section of the guide for information on
hacking on wasm-bindgen
!
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Top Related Projects
Emscripten: An LLVM-to-WebAssembly Compiler
🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
A TypeScript-like language for WebAssembly.
The WebAssembly Binary Toolkit
A fast and secure runtime for WebAssembly
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot