Optionalconfig: SandboxConfigWhether dispose() has run. A disposed sandbox rejects every later
eval(); callers holding one across an async boundary (a React cleanup,
an extension unload) can check this instead of catching.
Whether the WASM module backing this sandbox was retired after a teardown abort (#1922).
True means some sandbox on this module hit the upstream
JS_FreeRuntime assertion, so emscripten's module-wide ABORT latch has
fired: this sandbox still runs scripts, but its own teardown can no
longer report a failure, and it will silently leak whatever
JS_FreeRuntime does not reach. A long-lived host (the extension runtime)
should drop such a sandbox and create a new one — the replacement is built
on a fresh module, so no page reload is needed. Sandboxes created per run
(the viewer's script panel) never observe this: they are already gone.
Always false after dispose(), which releases the module reference.
Dispose the sandbox and free WASM memory.
Each field is cleared before the step that frees it, so a step that
throws is never retried. That matters for runtime.dispose(): an
out-of-memory or CPU-interrupt exception raised inside a drained promise
job leaves QuickJS holding objects with leaked refcounts, and upstream
JS_FreeRuntime then trips assert(list_empty(&rt->gc_obj_list)) and
throws out of dispose() part-way through freeing the runtime (#1922).
Re-entering it — from a second dispose(), a React cleanup, or an
extension unload — would free those same structures twice.
The failure is still reported: the throw propagates, so a caller that cannot tolerate a broken teardown still sees it, and the leak-oracle tests in dispose-leak.test.ts still fail on a retained handle.
The steps run in sequence rather than through a finally chain. Freeing
the runtime after a throwing vm.dispose() would run JS_FreeRuntime
against a live context, which aborts the WASM module for the rest of the
document — a worse outcome than the ~17KB the skipped free costs, and it
would mask the original error.
The abort itself is upstream and cannot be prevented from here (#1922) —
see SandboxAbortError for what was measured and what is done instead.
What is done here is to retire the aborted WASM module, so the next
sandbox is created on a fresh one instead of inheriting a poisoned heap
and a fired ABORT latch (see quickjs-module.ts).
Execute a script in the sandbox.
Supports both JavaScript and TypeScript (TypeScript is type-stripped before execution).
Runs are serialized per sandbox: calling eval() while another run is in
flight queues behind it rather than interleaving with it (#2110). One
sandbox owns one QuickJS realm and one log-capture buffer, so overlapping
runs could never have been independent.
Optionaloptions: { filename?: string; typescript?: boolean }Initialize the sandbox (loads WASM module if not cached)
@ifc-lite/sandbox — QuickJS-in-WASM sandboxed script execution
Runs user scripts in a secure, isolated environment with only the
bim.*API exposed. No DOM, no globalfetch. Outbound HTTP is available only throughbim.network.fetch, gated by thenetworkpermission (off by default) plus an exact-host grant list re-checked on every call — seenetwork-request.tsandbridge-network.ts.Example