WebAssembly with Elide

Run WASI command modules and load WASM libraries from JavaScript and TypeScript

WebAssembly support is experimental in 1.6.0.

You haveUseResult
A WASI commandelide run app.wasmRuns the module with WASI Preview 1 imports.
A WASM libraryThe WebAssembly API or an ES module import from JS/TSExposes the module’s exports.
elide app.wasm — WASI commands and WASM libraries from JavaScript

To compile Java or Kotlin to WebAssembly, see WebImage; its output needs its JavaScript loader and does not run with elide run.

Run a WASM file

elide run app.wasm
elide app.wasm
elide run app.wasm -- first second   # program arguments
elide run --timeout=5s app.wasm      # exit 124 after 5 seconds

Elide calls the module’s exported _start, or _main if _start is absent; a module with neither fails, so load it from JavaScript instead.

BehaviorValue
Argument zeroThe module’s absolute path.
Exit statusSet by WASI proc_exit, not by a function’s return value.
Traps, malformed binariesNonzero exit.
--timeoutCovers instantiation and execution; exits 124.

Project entrypoints

Name a module as the project entrypoint in elide.pkl, then run elide run in the project:

amends "elide:project.pkl"
name = "wasm-app"
entrypoint { "app.wasm" }

See Elide Projects.

WASI

Commands receive WASI Snapshot Preview 1 imports under wasi_snapshot_preview1: standard streams, arguments, exit status, and filesystem operations. Libraries loaded from JavaScript do not get WASI.

Directory access

WASI commands cannot access host directories until you map one:

elide -Xpolyglot.wasm.WasiMapDirs=work::./data run app.wasm

This exposes ./data as the guest directory work. Separate mappings with commas: work::./data,output::./results.

The sandbox still applies, and WASI file opens need both read and write permission, even for reads:

elide -Xpolyglot.wasm.WasiMapDirs=work::./data run \
  --sandbox --allow-read=./data --allow-write=./data app.wasm

See Sandbox and Limits.

JavaScript and TypeScript interop

The global WebAssembly API needs no flag:

import { readFile } from "node:fs/promises";

const bytes = await readFile(new URL("./math.wasm", import.meta.url));
const { instance } = await WebAssembly.instantiate(bytes, {});
console.log(instance.exports.add(20, 22));

Elide does not call _start or _main on modules loaded from JavaScript. The second argument supplies the module’s imports:

const imports = { env: { log: (value) => console.log(value) } };
const { instance } = await WebAssembly.instantiate(bytes, imports);

The API includes validate, compile, Module, Instance, Memory, Table, Global, and import and export inspection. A compiled Module can be instantiated more than once. File reads follow the same permissions as other JS code.

ES module imports

import { add } from "./math.wasm";
console.log(add(20, 22));
const math = await import("./math.wasm");
console.log(math.add(20, 22));

Specifiers can be relative or absolute paths, file: URLs, or package exports that resolve to .wasm. A source-phase import gives you the compiled module to instantiate yourself:

import source mathModule from "./math.wasm";
const math = await WebAssembly.instantiate(mathModule, {});
console.log(math.exports.add(20, 22));

Supported WebAssembly proposals

Defaults for both commands and JS/TS interop:

Feature / proposalStandard distributionWith Python installed
Mutable globals, sign-extension operatorsEnabledEnabled
Non-trapping float-to-integer conversionsEnabledEnabled
Multi-value function and block resultsEnabledEnabled
Bulk memory operations and reference typesEnabledEnabled
Multiple memoriesEnabledEnabled
Extended constant expressionsEnabledEnabled
Exception handlingEnabledEnabled
Typed function referencesEnabledEnabled
Garbage-collected types (WasmGC)EnabledEnabled
Tail callsEnabledEnabled
Fixed-width SIMD (v128)EnabledDisabled
Relaxed SIMDEnabledDisabled

Off by default:

ProposalOptionNotes
Memory64wasm.Memory64Also requires wasm.UseUnsafeMemory.
Threads and atomicswasm.ThreadsNo WASI thread-spawning host API is supplied.
Wide integer arithmeticwasm.WideArithmeticSeparate from ordinary i64 arithmetic.
Legacy exception handlingwasm.LegacyExceptionsThe newer exception-handling proposal is on by default.

Enable one with -Xpolyglot.<option>=true, for example -Xpolyglot.wasm.WideArithmetic=true. Enabling a proposal does not supply the host imports a module needs.

Limits

  • Binary modules only. No .wat, no compiling C or Rust, no WASM REPL.
  • WASI Preview 1 only. No WASI Preview 2, component model, or node:wasi; no general network access.
  • Host imports. elide run supplies only WASI; modules that expect browser APIs or Emscripten glue need a host that supplies them.
  • SIMD with Python. With Python installed, SIMD modules are rejected. Use an install without Python, or a scalar build of the module.