Skip to content

WebAssembly support via WAMR interpreter#3

Open
dannote wants to merge 13 commits intomasterfrom
wasm
Open

WebAssembly support via WAMR interpreter#3
dannote wants to merge 13 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 13 commits March 30, 2026 16:10
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).
drain_jobs() silently swallowed exceptions thrown during
JS_ExecutePendingJob (ret < 0 treated as ret == 0).

Add drain_jobs_or_set_error() that detects negative return values and
extracts the exception from the correct JSContext. Replace drain_jobs()
in do_eval, do_call, do_load_bytecode, and do_load_module.

Also factor set_error_term into set_error_term_from_ctx to handle
exceptions from a different context than self.ctx.
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