Javascript WebAssembly API

29 阅读1分钟

JavaScript has introduced several key features and APIs to seamlessly integrate WebAssembly (Wasm) into the web ecosystem. Here are the most important additions:


1. WebAssembly Core API

The global WebAssembly object provides methods to compile, instantiate, and interact with Wasm modules.

Key Methods:

  • WebAssembly.compile() / WebAssembly.compileStreaming()
    Compiles Wasm binary code (.wasm files) into executable modules.

    const module = await WebAssembly.compileStreaming(fetch('module.wasm'));
    
  • WebAssembly.instantiate() / WebAssembly.instantiateStreaming()
    Instantiates a Wasm module with imports (e.g., JS functions, memory).

    const { instance } = await WebAssembly.instantiateStreaming(fetch('module.wasm'));
    console.log(instance.exports.add(2, 3)); // Call a Wasm function
    
  • WebAssembly.validate()
    Checks if a binary is valid Wasm code.

    const isValid = WebAssembly.validate(wasmBinary);
    

2. Memory Management (WebAssembly.Memory)

Allows JS and Wasm to share a resizable ArrayBuffer for passing data (e.g., strings, arrays).

Example:

// Create 1 page (64KB) of shared memory
const memory = new WebAssembly.Memory({ initial: 1 });

// Write data from JS
const uint8Array = new Uint8Array(memory.buffer);
uint8Array[0] = 42; // Accessible in Wasm

// Pass memory to Wasm during instantiation
const { instance } = await WebAssembly.instantiateStreaming(
  fetch('module.wasm'),
  { js: { memory } } // Import memory into Wasm
);

3. Table API (WebAssembly.Table)

Enables indirect function references between JS and Wasm (useful for dynamic linking).

Example:

const table = new WebAssembly.Table({
  initial: 2,
  element: 'anyfunc' // Function references
});

// Pass table to Wasm
const { instance } = await WebAssembly.instantiateStreaming(
  fetch('module.wasm'),
  { js: { table } }
);

// Call a function from Wasm via table
table.get(0)(42); // Invokes the first table entry

4. Streaming APIs (compileStreaming, instantiateStreaming)

Optimized for loading .wasm files directly from network requests without buffering.

Example:

// Best practice: Stream and compile in one step
const { instance } = await WebAssembly.instantiateStreaming(
  fetch('module.wasm'),
  { /* imports */ }
);

5. Integration with ES Modules (import wasm)

Modern browsers support loading Wasm as ES modules.

Example:

// In JS
import { add } from './module.wasm';
console.log(add(2, 3));

// Corresponding Wasm (Rust with `wasm-bindgen`)
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
  a + b
}

6. Error Handling

  • WebAssembly.CompileError / WebAssembly.LinkError / WebAssembly.RuntimeError
    Specific error types for Wasm-related failures.

Example:

try {
  await WebAssembly.instantiateStreaming(fetch('broken.wasm'));
} catch (e) {
  if (e instanceof WebAssembly.CompileError) {
    console.error("Wasm compilation failed:", e);
  }
}

7. Thread Support (via SharedArrayBuffer)

Allows Wasm to use multi-threading (requires COOP/COEP headers for security).

Example:

const memory = new WebAssembly.Memory({
  initial: 1,
  shared: true // Enable shared memory
});

8. Garbage Collection Integration (Proposal)

Future JS/Wasm interop will allow Wasm to access JS objects directly via the GC proposal.


Key Takeaways

  1. Core APIs: WebAssembly object for loading/instantiating modules.
  2. Memory/Table: Shared memory and function references between JS/Wasm.
  3. Streaming: Efficient network loading.
  4. ES Modules: Native browser support for import wasm.
  5. Threads: Shared memory for parallel processing.

These features make Wasm a first-class citizen in the JS ecosystem. For full details, check the MDN WebAssembly docs.