erlang-wasmtime
Wasmtime bindings for Erlang (also findable as wasmtime-erlang). WebAssembly
modules run natively through Wasmtime's Cranelift compiler, and a module can
call Erlang functions when it needs to, the way erlang-python lets Python
call Erlang.
{ok, Mod} = wasmtime:compile({wat, ~"""
(module
(import "env" "log" (func $log (param i32) (result i32)))
(func (export "run") (param i32) (result i32)
local.get 0 call $log))
"""}),
{ok, Inst} = wasmtime:instantiate(Mod, #{
imports => #{{~"env", ~"log"} => fun(_Ctx, [N]) -> logger:info("got ~p", [N]), {ok, [N * 2]} end}}),
{ok, [84]} = wasmtime:call(Inst, ~"run", [42]).
Nothing raises for guest failures. Compile, link, trap, WASI and host errors
all come back as {error, #{class => ..., kind => ..., message => ...}}.
What you get
- Native execution: Wasmtime 48, statically linked into one NIF.
- Host functions: an import backed by an Erlang fun, run in the calling process.
- Isolation by default: no WASI, no filesystem, no host functions and a 256 MB memory cap unless you grant more. Each instance has its own store, memory and OS thread.
- Interruption:
timeouton a call, orwasmtime:interrupt/1from any process, stops a running guest within 10 ms. - WASI preview 1 with explicit capabilities:
args,env, preopeneddirs, and stdio redirected to files or inherited. - Linear memory access from Erlang while the guest is idle or inside a host call.
- References as terms:
funcref,externref(wrapping any Erlang term) and GC structs and arrays cross calls, host functions, globals and tables. - Precompiled modules: compile once,
deserialize/1in milliseconds. - Runtime-only builds:
WASMTIME_RUNTIME_ONLY=1gives a 4 MB NIF without the compiler for nodes that only load precompiled modules. - Host functions served by the caller or by a dedicated process.
- Streams: a long-running guest reads what
send/2queues and its writes arrive as messages, through stdin/stdout for stock WASI programs or theerlangimports for modules you build.
Install
{deps, [{erlang_wasmtime, "0.1.1"}]}.
The first rebar3 compile downloads the pinned Wasmtime C API release for your
platform (about 15 MB, checksum verified) and builds the NIF. You need a C
compiler and curl; a platform without a prebuilt archive builds Wasmtime
from source with git, cmake and Rust. See docs/building.md
for offline builds, runtime-only builds and supported platforms.
Requires OTP 27 or later.
Documentation
- Run JavaScript: QuickJS in the sandbox, the shortest path to a demo
- Run Python: CPython's WASI build, with the standard library
- Getting started
- Host functions
- WASI
- Streams: talk to a guest while it runs
- References: funcref, externref and GC values as terms
- Precompiled modules: compile once, load in milliseconds
- Building and shipping
- Troubleshooting
- Design: how the NIF is put together, for contributors; see also CONTRIBUTING.md
- Features: what is implemented, what is refused, what is deferred
- Examples: user-defined event transforms in JavaScript, a guest that reads ETS, logs and notifies processes
Related
- erlang_wasm: a WebAssembly runtime written in Erlang, no native code. Same API style; pick it when you cannot ship a NIF.
- erlang-python: the embedding pattern this project copies, for Python.
License
Apache-2.0