Skip to content

WebAssembly support via WAMR interpreter#3

Merged
dannote merged 14 commits intomasterfrom
wasm
Apr 9, 2026
Merged

WebAssembly support via WAMR interpreter#3
dannote merged 14 commits intomasterfrom
wasm

Conversation

@dannote
Copy link
Copy Markdown
Member

@dannote dannote commented Mar 31, 2026

Pure Elixir WASM parser + WAMR-backed runtime + browser-style WebAssembly API inside QuickBEAM runtimes and contexts.

  • Elixir-side module compile / instantiate / call / memory / globals
  • JS WebAssembly namespace with Module, Instance, Memory, Global, streaming APIs, and custom sections
  • typed wasm calls for i32, i64, f32, and f64
  • function, memory, and global import handling
  • JS host function imports now run inline on the owning QuickJS runtime / ContextPool worker
  • host import registration and callback policy moved into Zig, with wamr_bridge.c reduced to WAMR ABI glue
  • test-env source builds stabilized with a local Zig cache

Verified:

  • QUICKBEAM_BUILD=1 mix compile
  • MIX_ENV=test QUICKBEAM_BUILD=1 mix compile
  • QUICKBEAM_BUILD=1 mix test test/wasm_test.exs
  • QUICKBEAM_BUILD=1 mix test --no-start --exclude napi_addon --exclude napi_sqlite test/wasm_test.exs
  • QUICKBEAM_BUILD=1 mix test test/wasm_test.exs test/quickbeam_test.exs
  • bun run lint

dannote added 14 commits April 9, 2026 12:51
Pure Elixir implementation that decodes .wasm binaries into structured
data — types, imports, exports, function bodies with decoded opcodes,
memories, tables, globals, data segments, and custom sections.

Opcodes use the same {offset, name, ...operands} tuple format as
QuickBEAM.Bytecode.

- QuickBEAM.WASM.disasm/1 — full module disassembly
- QuickBEAM.WASM.validate/1 — structural validation
- QuickBEAM.WASM.exports/1 — list module exports
- QuickBEAM.WASM.imports/1 — list module imports
- QuickBEAM.WASM.Module — decoded module struct
- QuickBEAM.WASM.Function — decoded function struct
- QuickBEAM.WASM.Parser — LEB128, sections, all MVP opcodes
Vendor WAMR (WebAssembly Micro Runtime) in interpreter mode and
expose compile/start/call/stop/memory APIs as NIFs.

- Vendor WAMR core: interpreter, common runtime, platform layer,
  memory allocator, utils (~57KB code footprint)
- C bridge (wamr_bridge.c) wraps WAMR embedding API
- Zig NIF layer (wasm_nif.zig) with WasmModule/WasmInstance resources
- Elixir API: QuickBEAM.WASM.compile/1, start/2, call/3, stop/1,
  memory_size/1, memory_grow/2, read_memory/3, write_memory/3

All 27 WASM tests pass (19 parser + 8 runtime).
Implements the standard WebAssembly JS API as a TypeScript polyfill
backed by WAMR through Beam.callSync handlers.

Supported:
- WebAssembly.compile(bytes) → Promise<Module>
- WebAssembly.instantiate(bytes|module, imports?) → Promise<{module, instance}>
- WebAssembly.validate(bytes) → boolean
- new WebAssembly.Module(bytes)
- new WebAssembly.Instance(module)
- WebAssembly.Module.exports(mod)
- instance.exports.funcName(...args)
- WebAssembly.Memory, Table, Global constructors
- CompileError, LinkError, RuntimeError error types

7 new JS API tests (34 total).
- QuickBEAM.WASM.start/1 returns a pid (like QuickBEAM.start/1)
- QuickBEAM.WASM.call/3 goes through GenServer (like QuickBEAM.call/3)
- QuickBEAM.WASM.stop/1 stops the GenServer
- child_spec/1 and start_link/1 for supervision trees
- Named instances: start(module: bytes, name: :my_wasm)
- Raw NIF compile/start are internal (@doc false)

36 tests (19 parser + 7 runtime + 7 JS API + 3 supervision).
@dannote dannote merged commit 93b3b3e into master Apr 9, 2026
4 checks passed
@dannote dannote deleted the wasm branch April 9, 2026 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant