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 (.wasmfiles) 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
- Core APIs:
WebAssemblyobject for loading/instantiating modules. - Memory/Table: Shared memory and function references between JS/Wasm.
- Streaming: Efficient network loading.
- ES Modules: Native browser support for
import wasm. - 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.