WebAssembly
Raven compiles ahead of time to WebAssembly – not as one backend among many, but as the target. Wasm's sandboxing, small binaries and run-anywhere portability are core to what Raven is for: interactive browser experiences, serverless functions, safely executing untrusted (or LLM-written) code.
Building and running
$ raven build hello.rv # -> hello.wasm
$ raven hello.wasm # run a compiled binary
The output uses modern wasm proposals (GC, reference types, JS string builtins where available). The raven CLI runs binaries under Node; binaries also run in browsers and other runtimes supporting the relevant proposals.
Inline wasm
For the lowest-level work, Raven has inline WebAssembly. A wasm block takes wasm instructions, with typed Raven values in and out:
@extend
fn Float32(x: Float64) {
wasm { f32.demote_f64(x: f64): f32 }
}
The wasm call(...) form calls host or support functions directly:
fn string(Char(val)) {
ref = wasm call("wasm:js-string".fromCodePoint, widen(bits(val)): i32): ref!
return unsafeString(ref)
}
This isn't an FFI bolted on the side – it's how the standard library bottoms out. Integers are defined over raw bits, floats over wasm float instructions, and the allocator (malloc, in Raven) over raw loads and stores. The common/wasm modules expose some of this machinery – Ptr, Cell, memoryPages and friends – if you need manual control over memory.
Inspecting output
The usual wasm tooling works on Raven binaries:
$ wasm-tools print hello.wasm | less # disassemble
$ wasm-tools validate hello.wasm
$ llvm-dwarfdump hello.wasm # debug info
Binaries include DWARF debug metadata (names, source locations) unless built with --strip, which is what makes stack traces and debugger support work.