Convert Figma logo to code with AI

rustwasm logowasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript

7,626
1,046
7,626
451

Top Related Projects

Emscripten: An LLVM-to-WebAssembly Compiler

18,439

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten

A TypeScript-like language for WebAssembly.

6,727

The WebAssembly Binary Toolkit

15,089

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

  1. 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.

  1. 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.

  1. 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

  1. Add wasm-bindgen to your Cargo.toml:

    [dependencies]
    wasm-bindgen = "0.2"
    
  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)
    }
    
  3. Build your project with wasm-pack:

    wasm-pack build --target web
    
  4. 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.

18,439

🚀 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.

6,727

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.

15,089

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 Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript.

Build Status Crates.io version Download docs.rs docs

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 the document.querySelector method doesn't cause Node.prototype.appendChild or window.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

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.