The runtime:wasm module provides WebAssembly runtime capabilities with WASI support and capability-based security.
WASM operations must be declared in manifest.app.toml:
[capabilities.wasm]
load = ["./wasm/*.wasm", "~/.myapp/plugins/*.wasm"]
preopens = ["./data", "~/.myapp/storage"]load- Paths allowed for loading WASM modulespreopens- Directories that can be exposed to WASI modules
Compile WASM binary to a module:
import { compile } from "runtime:wasm";
const response = await fetch("./module.wasm");
const bytes = new Uint8Array(await response.arrayBuffer());
const moduleId = await compile(bytes);Compile WASM from a file path:
import { compileFile } from "runtime:wasm";
const moduleId = await compileFile("./calculator.wasm");Release a compiled module:
import { dropModule } from "runtime:wasm";
await dropModule(moduleId);Create an instance from a compiled module:
import { compileFile, instantiate } from "runtime:wasm";
const moduleId = await compileFile("./module.wasm");
const instance = await instantiate(moduleId);With WASI configuration:
const instance = await instantiate(moduleId, {
preopens: {
"/data": "./app-data", // Guest path -> Host path
"/tmp": "/tmp/myapp"
},
env: {
"APP_MODE": "production",
"DEBUG": "0"
},
args: ["--config", "app.toml"],
inheritStdout: true,
inheritStderr: true
});| Option | Type | Description |
|---|---|---|
preopens |
Record<string, string> |
Guest path to host path mappings |
env |
Record<string, string> |
Environment variables |
args |
string[] |
Command-line arguments |
inheritStdin |
boolean |
Inherit stdin from host |
inheritStdout |
boolean |
Inherit stdout from host |
inheritStderr |
boolean |
Inherit stderr from host |
Call an exported function:
// Simple call with auto type inference
const [result] = await instance.call("add", 5, 3);
console.log(result); // 8
// With explicit types
import { types } from "runtime:wasm";
const [result] = await instance.call("compute",
types.i32(100),
types.f64(3.14)
);Get list of module exports:
const exports = await instance.getExports();
// [
// { name: "add", kind: "function", params: ["i32", "i32"], results: ["i32"] },
// { name: "memory", kind: "memory" },
// { name: "factorial", kind: "function", params: ["i64"], results: ["i64"] }
// ]Release the instance:
await instance.drop();Access linear memory through instance.memory:
Read bytes from memory:
const data = await instance.memory.read(0, 256);
// Returns: Uint8Array
// Read a null-terminated string
function readString(instance, ptr) {
const bytes = await instance.memory.read(ptr, 1024);
const end = bytes.indexOf(0);
return new TextDecoder().decode(bytes.subarray(0, end));
}Write bytes to memory:
const encoder = new TextEncoder();
await instance.memory.write(0, encoder.encode("Hello\0"));Get memory size in pages (64KB each):
const pages = await instance.memory.size();
console.log(`Memory: ${pages * 64}KB`);Grow memory by specified pages:
const previousSize = await instance.memory.grow(1);
console.log(`Grew from ${previousSize} to ${previousSize + 1} pages`);The types object provides explicit type constructors:
import { types } from "runtime:wasm";
types.i32(42) // 32-bit signed integer
types.i64(9007199254740993n) // 64-bit signed integer
types.f32(3.14) // 32-bit float
types.f64(2.718281828) // 64-bit floatFor advanced use cases, low-level functions are available:
import { call, getExports, memory } from "runtime:wasm";
// Direct function call with explicit types
const results = await call(instanceId, "compute", [
{ type: "i32", value: 10 },
{ type: "f64", value: 3.14 }
]);
// Direct memory access
const data = await memory.read(instanceId, 0, 100);
await memory.write(instanceId, 0, new Uint8Array([1, 2, 3]));
const size = await memory.size(instanceId);
await memory.grow(instanceId, 2);import { compileFile, instantiate, types } from "runtime:wasm";
// Load and instantiate a WASM module
const moduleId = await compileFile("./calculator.wasm");
const calc = await instantiate(moduleId);
// Check available functions
const exports = await calc.getExports();
console.log("Available functions:", exports.filter(e => e.kind === "function"));
// Call functions
const [sum] = await calc.call("add", 10, 20);
const [product] = await calc.call("multiply", types.i32(5), types.i32(7));
console.log(`10 + 20 = ${sum}`);
console.log(`5 * 7 = ${product}`);
// Clean up
await calc.drop();
await dropModule(moduleId);import { compileFile, instantiate } from "runtime:wasm";
// Compile a WASI-compatible module
const moduleId = await compileFile("./cli-tool.wasm");
// Instantiate with WASI configuration
const instance = await instantiate(moduleId, {
preopens: {
"/": "./sandbox" // Mount sandbox directory as root
},
env: {
"HOME": "/home/user",
"PATH": "/bin"
},
args: ["tool", "--verbose", "input.txt"],
inheritStdout: true,
inheritStderr: true
});
// Call the WASI _start entry point
await instance.call("_start");
await instance.drop();| Code | Name | Description |
|---|---|---|
| 5000 | CompileError | Failed to compile WASM module |
| 5001 | InstantiateError | Failed to instantiate module |
| 5002 | CallError | Function call failed |
| 5003 | ExportNotFound | Export not found in module |
| 5004 | InvalidModuleHandle | Invalid module ID |
| 5005 | InvalidInstanceHandle | Invalid instance ID |
| 5006 | MemoryError | Memory access error |
| 5007 | TypeError | Type mismatch in function call |
| 5008 | IoError | File loading error |
| 5009 | PermissionDenied | Capability check failed |
| 5010 | WasiError | WASI configuration error |
| 5011 | FuelExhausted | Execution limit reached |