rasc is Rive’s AssemblyScript compiler — a single self-contained
C++ binary that compiles .as sources to WebAssembly in a few hundred
milliseconds. It adds the things upstream never did — closures, value classes,
allocation sinking — and runs the result everywhere Rive runs: the browser engine
on web, a fast interpreter for instant iteration, ahead-of-time machine code
for shipping.
struct Vec2 {
x: f32;
y: f32;
}
export function reflect(v: Vec2, n: Vec2): Vec2 {
// Value classes never allocate: a Vec2 is two f32 leaves
// living in wasm locals, returned via multi-value.
const d: f32 = 2.0 * (v.x * n.x + v.y * n.y);
let r = Vec2();
r.x = v.x - d * n.x;
r.y = v.y - d * n.y;
return r;
}
export function demo(): f32 {
let v = Vec2();
v.x = 3;
v.y = -1;
let n = Vec2();
n.y = 1;
return reflect(v, n).y; // the bounce: 1
}
rasc stays additive: sources that compile with upstream asc produce byte-identical modules. New syntax only ever adds capability.
Plain-old-data classes that flatten to wasm locals and stack values.
Copy semantics, zero allocation, one-load field access when embedded —
body.transform.p.x compiles to a single load at a constant
offset.
Functions capture enclosing locals — the feature upstream AssemblyScript famously never shipped. Captures snapshot by value into GC-traced context objects, safe to escape through fields and returns.
concepts →Value classes return as native wasm multi-value tuples — every size,
no hidden out-pointers. -O2 enables the feature in wasm-opt
only when a signature actually carries several results.
Non-escaping new scalarizes into locals automatically.
Naive object-per-frame code runs 12× faster on the interp tier
with no hand-optimization.
Opt-in wasm SIMD with f32x4/i32x4 builtins and
relaxed fused multiply-add. One source, two artifacts — output stays
byte-identical when the feature is off.
Versioned import namespaces are the protocol. One IDL generates the C header, WAMR natives, JS stubs, and the AS projection — and unused bindings tree-shake away per module.
host bindings →Measured on real ported workloads — Draco mesh decode, Box2D solving, the Fields app — against native Luau and the shipping Luau web lane.
The same wasm module runs on the browser engine, the WAMR fast interpreter, and wamrc AOT — pick per platform, not per rewrite. The editor iterates on interp instantly and swaps in optimized AOT bits in the background.