|
| 1 | +# chidori-wasm |
| 2 | + |
| 3 | +The chidori-js engine — bytecode compiler, VM, GC, builtins, and the durable |
| 4 | +replay runtime — compiled to WebAssembly and driven from a browser page. |
| 5 | + |
| 6 | +The engine crate is pure Rust (`#![forbid(unsafe_code)]`, no C, no threads, no |
| 7 | +filesystem), so it builds for `wasm32-unknown-unknown` unmodified. This crate |
| 8 | +adds only the boundary: a `wasm-bindgen` wrapper around |
| 9 | +`chidori_js::replay::ReplayRuntime` that exposes the record/replay pump to |
| 10 | +JavaScript. |
| 11 | + |
| 12 | +## The pump protocol |
| 13 | + |
| 14 | +The page owns the event loop and the host effects (fetch, time, randomness, |
| 15 | +prompts). The runtime is a pump: |
| 16 | + |
| 17 | +```js |
| 18 | +const rt = new WasmRuntime(bundle, ['now', 'random', 'httpFetch']); |
| 19 | +for (;;) { |
| 20 | + const status = JSON.parse(rt.runUntilBlocked()); |
| 21 | + if (status.status === 'completed') break; |
| 22 | + // status: { status: 'blocked', opId, name, args } |
| 23 | + const result = await host[status.name](...status.args); // e.g. fetch() |
| 24 | + rt.resolveOp(status.opId, JSON.stringify(result)); // journaled |
| 25 | +} |
| 26 | +const blob = rt.toBlob(); // durable artifact: bundle + effects + journal |
| 27 | +``` |
| 28 | + |
| 29 | +`WasmRuntime.fromBlob(blob)` restores in replay mode: journaled effects are |
| 30 | +served from the journal (no network, no reruns of anything non-deterministic), |
| 31 | +and the pump only surfaces ops past the recorded frontier — so a suspended run |
| 32 | +can resume in a fresh tab, or a completed run can replay with byte-identical |
| 33 | +output and zero live host calls. The blob is the same `DurableBlob` artifact |
| 34 | +the native runtime uses. |
| 35 | + |
| 36 | +## Build and run the demo |
| 37 | + |
| 38 | +```sh |
| 39 | +rustup target add wasm32-unknown-unknown |
| 40 | +cargo install wasm-bindgen-cli # version must match Cargo.toml's wasm-bindgen pin |
| 41 | + |
| 42 | +scripts/build-wasm.sh |
| 43 | +python3 -m http.server -d crates/chidori-wasm/www 8080 |
| 44 | +# open http://localhost:8080 — record a run, then replay it offline |
| 45 | +``` |
| 46 | + |
| 47 | +## What stays native |
| 48 | + |
| 49 | +The `chidori` CLI crate is deliberately not part of the wasm build: it is the |
| 50 | +*host* side — tokio, reqwest, axum, SQLite session stores, OS sandboxing |
| 51 | +(seccomp/Landlock) — and in the browser those responsibilities belong to the |
| 52 | +page (fetch, IndexedDB/localStorage, the browser sandbox). The engine and the |
| 53 | +journal format are shared; the host is swapped. |
| 54 | + |
| 55 | +## Tests |
| 56 | + |
| 57 | +The driver core is plain Rust (`src/lib.rs`, `driver` module), so the full |
| 58 | +record → suspend → resolve → replay cycle runs under `cargo test -p |
| 59 | +chidori-wasm` on the native target; browser behavior is exercised by the demo |
| 60 | +page. |
0 commit comments