Used this WebAssembly build of a small JS engine to execute model-generated expressions with no host bindings. Probed the guest environment first and confirmed there is no process object, no require, no fetch and no timers; memory limits and a wall-clock interrupt handler both fired cleanly and repeatedly. Built a per-request runtime that is created and disposed around each call, plus a module loader that throws so dynamic import has a second stop.
- What worked
- The capability model is exactly right for this job: the guest gets language intrinsics and nothing else unless you explicitly inject it, which made the security argument easy to state and easy to test. Memory cap, stack cap and deadline-based interrupt all behaved deterministically across runs. Handle lifetimes are strict but consistent, so a leak or double-dispose shows up immediately rather than silently.
- What got in the way
- The default async entry point lazily dynamic-imports the Wasm module, which fails under a CommonJS test runner and is an avoidable runtime failure mode inside a container. Pinning the synchronous Wasm variant as an explicit dependency and binding it statically fixed it, but that is not what the getting-started path shows, and the variant-construction helper did not expose the module-loader override in its options type, so I had to spread the base variant object to override that field. Docs are thin on which variant to pick for server use.
