Backend: WASM
The WASM backend is the portable implementation of the SpiceBackend contract.
- Package:
packages/backend-wasm/(@rybosome/tspice-backend-wasm) - Runtime: an Emscripten-compiled CSPICE-derived
.wasm+ glue JS
This page focuses on what’s specific to the WASM backend.
Where the artifacts live
Checked-in Emscripten outputs:
packages/backend-wasm/emscripten/tspice_backend_wasm.web.jspackages/backend-wasm/emscripten/tspice_backend_wasm.web.wasmpackages/backend-wasm/emscripten/tspice_backend_wasm.node.jspackages/backend-wasm/emscripten/tspice_backend_wasm.wasm
(The .node.js vs .web.js glue differs by environment, but the contract surface is the same.)
The C-side integration is just the shared shim compiled for WASM:
packages/backend-wasm/emscripten/tspice_backend_wasm_wrapper.c
Loader split: create-backend.web.ts vs create-backend.node.ts
The backend has two environment-specific constructors:
- Web:
packages/backend-wasm/src/runtime/create-backend.web.ts - Node:
packages/backend-wasm/src/runtime/create-backend.node.ts
Conditional exports in packages/backend-wasm/package.json select the right one at runtime.
packages/backend-wasm/src/index.ts exists primarily to give TypeScript a stable type surface (TS doesn’t currently pick types per export condition).
wasmUrl and locateFile
Both loaders support wasmUrl?: string | URL (see CreateWasmBackendOptions).
Why this exists:
- bundlers often relocate
.wasmassets - blob workers change what
import.meta.urlmeans
The Web loader:
- imports the glue JS via a literal
import("../tspice_backend_wasm.web.js") - passes a
locateFile()callback so Emscripten can find the wasm binary by URL
If you see errors about failing to fetch/instantiate the module, the first thing to check is that the resolved wasmUrl points at the deployed .wasm.
Node loader specifics:
- prefers feeding bytes via
wasmBinaryforfile://...URLs and filesystem paths (avoids Nodefetchlimitations) - keeps a small bounded cache of wasm bytes to reduce repeated disk reads
- supports extra troubleshooting knobs in
CreateWasmBackendOptions:validateEmscriptenModule(defaultstrue)repairInvalidDistWasm(defaultsfalse)
Kernel paths are always virtual
Unlike Node, the WASM backend treats kernel paths as virtual IDs under /kernels/...:
packages/backend-wasm/src/runtime/fs.ts(resolveKernelPath)
This is enforced intentionally so “accidentally passed an OS path/URL” becomes an immediate, actionable error.
Performance + worker guidance
The WASM backend is synchronous and CPU-heavy calls can block the current JS thread.
Typical guidance:
- Browsers: run it in a Web Worker to avoid blocking the UI.
- Parallelism: each worker/module instance has its own isolated CSPICE state, so you can scale out by running multiple workers (at the cost of duplicated wasm memory and kernel state).
- Reuse: instantiate the backend once per worker/process and reuse it; wasm startup + kernel loading can dominate for short-lived tasks.