The parser under src/ is plain, self-contained C with no dependency
on the Ruby C API, so it can be compiled to WebAssembly as-is. This directory
holds the small entry-point shim (rbs_wasm.c) that exposes a
stable ABI to a WebAssembly host.
This is how RBS runs on Ruby implementations that cannot load the MRI C
extension (notably JRuby): the host loads rbs_parser.wasm, runs the parser over
a source buffer, and reads the serialized AST back out. The Ruby side then
rebuilds RBS::AST objects with RBS::WASM::Deserializer — no native build per
platform required. See lib/rbs/wasm and
docs/wasm_serialization.md.
The build needs the WASI SDK
(for clang, the wasi-libc sysroot, and the wasm32 compiler-rt builtins):
$ export WASI_SDK_PATH=/path/to/wasi-sdk
$ rake wasm:build # compile rbs_parser.wasm
$ rake wasm:check # also smoke-test it (needs wasmtime)
$ rake wasm:jruby_setup # copy rbs_parser.wasm into lib/rbs/wasm/ for JRuby
$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRuby)The compiled rbs_parser.wasm is a build artifact and is not checked in.
The module is built as a "reactor": it has no main, and the host calls
_initialize once before invoking any export.
Memory management and results:
| Export | Signature | Description |
|---|---|---|
rbs_wasm_alloc |
(i32) -> i32 |
Allocate N bytes in linear memory, return the offset. |
rbs_wasm_free |
(i32) -> () |
Free a region from rbs_wasm_alloc. |
rbs_wasm_result_ptr |
() -> i32 |
Offset of the most recent result. |
rbs_wasm_result_len |
() -> i32 |
Length of the most recent result. |
Parsing — each takes the whole buffer (ptr/len), its Ruby encoding name
(enc/enc_len, e.g. "UTF-8" or "EUC-JP"; falls back to UTF-8 when empty or
unknown), and the character range to parse (start/end). Each returns 1 on
success or 0 on a parse error. On success the result is the serialized AST; on
error it is an error blob (start/end positions, syntax flag, token type,
message). Type/method-type parsing also takes a buffer of newline-separated
type-variable names (vars/vars_len, with vars_len < 0 meaning "none"):
| Export | Signature |
|---|---|
rbs_wasm_parse_signature |
(ptr, len, enc, enc_len, start, end) -> i32 |
rbs_wasm_parse_type |
(ptr, len, enc, enc_len, start, end, vars, vars_len, require_eof, void_allowed, self_allowed, classish_allowed) -> i32 |
rbs_wasm_parse_method_type |
(ptr, len, enc, enc_len, start, end, vars, vars_len, require_eof) -> i32 |
rbs_wasm_selftest |
() -> i32 (parses a fixed sample; 1 on success) |
For type and method-type parsing, a successful result of length 0 means the input
was empty (nil).