Convert Figma logo to code with AI

wasm-bindgen logowasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript

8,355
1,134
8,355
558

Top Related Projects

📦✨ your favorite rust -> wasm workflow tool!

Emscripten: An LLVM-to-WebAssembly Compiler

16,700

A lightweight WebAssembly runtime that is fast, secure, and standards-compliant

19,923

🚀 Fast, secure, lightweight containers based on WebAssembly

A TypeScript-like language for WebAssembly.

7,475

The WebAssembly Binary Toolkit

Quick Overview

wasm-bindgen is a project that facilitates high-level interactions between Wasm modules and JavaScript. It allows developers to import JavaScript functionality into Rust and export Rust functionality to JavaScript, making it easier to use Rust-generated WebAssembly modules in web applications.

Pros

  • Seamless integration between Rust and JavaScript
  • Automatic generation of TypeScript definitions
  • Support for complex data types and async functions
  • Reduces boilerplate code for Wasm/JS interoperability

Cons

  • Learning curve for developers new to Rust or WebAssembly
  • Potential performance overhead for certain operations
  • Limited support for some advanced JavaScript features
  • Dependency on external tools and build processes

Code Examples

  1. Exporting a Rust function to JavaScript:
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
  1. Importing a JavaScript function into Rust:
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
  1. Working with complex types:
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Point {
    x: f64,
    y: f64,
}

#[wasm_bindgen]
impl Point {
    pub fn new(x: f64, y: f64) -> Point {
        Point { x, y }
    }

    pub fn distance(&self, other: &Point) -> f64 {
        let dx = self.x - other.x;
        let dy = self.y - other.y;
        (dx * dx + dy * dy).sqrt()
    }
}

Getting Started

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

    [dependencies]
    wasm-bindgen = "0.2"
    
  2. Use the #[wasm_bindgen] attribute on functions and structs you want to expose to JavaScript.

  3. Build your project with:

    wasm-pack build --target web
    
  4. Import and use your Wasm module in JavaScript:

    import init, { add, greet, Point } from './pkg/your_project.js';
    
    async function run() {
      await init();
      console.log(add(2, 3));
      greet("World");
      const p1 = Point.new(0, 0);
      const p2 = Point.new(3, 4);
      console.log(p1.distance(p2));
    }
    
    run();
    

Competitor Comparisons

📦✨ your favorite rust -> wasm workflow tool!

Pros of wasm-pack

  • Provides a complete toolchain for building and publishing Rust-generated WebAssembly
  • Simplifies the process of creating npm packages from Rust code
  • Includes built-in testing and documentation generation features

Cons of wasm-pack

  • May have a steeper learning curve for developers new to Rust and WebAssembly
  • Requires additional setup compared to using wasm-bindgen directly
  • Can be slower for small projects due to its comprehensive nature

Code Comparison

wasm-bindgen:

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

wasm-pack:

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

wasm-pack build

The code for the function itself is identical, but wasm-pack requires an additional command to build the project for WebAssembly use.

Summary

While wasm-bindgen focuses on providing low-level bindings between Rust and JavaScript, wasm-pack offers a more comprehensive solution for building and publishing WebAssembly modules. wasm-pack builds on top of wasm-bindgen, adding features like npm package generation and testing tools. However, this comes at the cost of increased complexity and potentially slower build times for smaller projects.

Emscripten: An LLVM-to-WebAssembly Compiler

Pros of Emscripten

  • Broader language support, including C and C++
  • More mature and established ecosystem
  • Extensive toolchain for compiling to WebAssembly

Cons of Emscripten

  • Steeper learning curve
  • Larger output size compared to Wasm-bindgen
  • Less seamless integration with JavaScript

Code Comparison

Emscripten (C++):

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
    return a + b;
}

Wasm-bindgen (Rust):

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

Emscripten requires explicit use of EMSCRIPTEN_KEEPALIVE to export functions, while Wasm-bindgen uses a more declarative #[wasm_bindgen] attribute. Wasm-bindgen's approach is generally more ergonomic for Rust developers.

Emscripten is better suited for projects with existing C/C++ codebases or those requiring its extensive toolchain. Wasm-bindgen, on the other hand, offers a more streamlined experience for Rust developers and typically produces smaller output sizes. The choice between the two often depends on the project's language requirements and the developer's familiarity with the respective ecosystems.

16,700

A lightweight WebAssembly runtime that is fast, secure, and standards-compliant

Pros of Wasmtime

  • More comprehensive WebAssembly runtime with broader use cases
  • Supports multiple programming languages beyond just JavaScript
  • Offers standalone CLI tool for running and debugging Wasm modules

Cons of Wasmtime

  • Steeper learning curve for simple JavaScript/Wasm integrations
  • Requires more setup and configuration for basic web projects
  • May be overkill for small-scale or web-only applications

Code Comparison

Wasmtime (Rust):

use wasmtime::*;

let engine = Engine::default();
let module = Module::from_file(&engine, "example.wasm")?;
let store = Store::new(&engine, ());
let instance = Instance::new(&store, &module, &[])?;

wasm-bindgen (JavaScript):

import init, { greet } from './pkg/hello_wasm.js';

async function run() {
  await init();
  greet('World');
}

Wasmtime provides a more low-level API for working with WebAssembly modules, while wasm-bindgen focuses on seamless JavaScript-Wasm interop for web applications. Wasmtime is better suited for complex, multi-language projects, while wasm-bindgen excels in simplifying Wasm usage in web environments.

19,923

🚀 Fast, secure, lightweight containers based on WebAssembly

Pros of Wasmer

  • Supports multiple programming languages, not just JavaScript
  • Can run WebAssembly modules outside the browser environment
  • Provides a more comprehensive WebAssembly runtime ecosystem

Cons of Wasmer

  • Higher complexity and learning curve compared to wasm-bindgen
  • May have more overhead for simple browser-based WebAssembly use cases
  • Less focused on JavaScript/browser integration

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::new(&store, wasm_bytes)?;
let instance = Instance::new(&module, &imports! {})?;
let add = instance.exports.get_function("add")?;
let result = add.call(&[Value::I32(5), Value::I32(37)])?;

wasm-bindgen focuses on seamless JavaScript integration, making it easier to use WebAssembly in browser environments. It automatically generates JavaScript bindings for Rust functions.

Wasmer provides a more versatile WebAssembly runtime, allowing execution of WebAssembly modules in various environments and languages. It offers more control over module instantiation and execution but requires more setup code.

Both projects serve different use cases, with wasm-bindgen being more suitable for browser-centric applications and Wasmer for broader WebAssembly runtime needs.

A TypeScript-like language for WebAssembly.

Pros of AssemblyScript

  • Easier learning curve for JavaScript developers
  • Supports a wider range of programming paradigms
  • Offers a more familiar syntax for web developers

Cons of AssemblyScript

  • Less mature ecosystem compared to Rust
  • May have performance limitations in certain scenarios
  • Smaller community and fewer resources available

Code Comparison

AssemblyScript:

export function add(a: i32, b: i32): i32 {
  return a + b;
}

wasm-bindgen:

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

AssemblyScript provides a TypeScript-like syntax, making it more accessible for JavaScript developers. It allows for easier integration with existing web projects and supports object-oriented programming. However, it may not achieve the same level of performance as Rust in certain scenarios.

wasm-bindgen, being based on Rust, offers better performance and memory safety guarantees. It has a more mature ecosystem and a larger community, providing more resources and tools. However, it has a steeper learning curve for developers not familiar with Rust.

Both projects aim to simplify WebAssembly development, but they cater to different developer preferences and project requirements. The choice between them often depends on the team's expertise, performance needs, and existing codebase.

7,475

The WebAssembly Binary Toolkit

Pros of wabt

  • Broader scope: Supports multiple WebAssembly-related tools and utilities
  • Language-agnostic: Works with various programming languages, not limited to Rust
  • Mature project: Longer development history and wider adoption in the WebAssembly community

Cons of wabt

  • Lower-level tooling: Requires more manual work and understanding of WebAssembly internals
  • Less seamless integration: Doesn't provide automatic JavaScript bindings like wasm-bindgen
  • Steeper learning curve: May be more challenging for developers new to WebAssembly

Code comparison

wabt (C++):

#include "src/binary-reader-ir.h"
#include "src/binary-writer.h"
#include "src/ir.h"

void example() {
  wabt::Module module;
  // ... manipulate module ...
}

wasm-bindgen (Rust):

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn example() {
    // ... Rust code ...
}

wabt focuses on low-level WebAssembly manipulation, while wasm-bindgen provides high-level Rust-to-JavaScript bindings. wabt offers more flexibility across languages, but wasm-bindgen simplifies Rust-WebAssembly integration. Choose based on your project's specific needs and language preferences.

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.