You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sandbox Phase 3 — precompile the WASM module once, instantiate per invocation #3297
Part 3 of #3275 — see its Phase 3 section for the full spec. Blocked by #3296 (Phase 2).
Verified API (quickjs-emscripten@0.32.0):newVariant(baseVariant, { wasmModule }) where wasmModule?: OrLoader<WebAssembly.Module> — "Emscripten will instantiate the WebAssembly.Instance from this existing WebAssembly.Module." The compiled WebAssembly.Module is stateless bytecode; each newQuickJSWASMModule(variant) still allocates a fresh linear memory (isolation preserved) as long as wasmMemory is NOT also passed (that would share memory = the rejected model).
Change (packages/runtime/src/sandbox/quickjs-runner.ts), module-level once per process:
constwasmModule=awaitWebAssembly.compile(baseWasmBytes);// compile ONCEconstFAST_VARIANT=newVariant(RELEASE_SYNC,{ wasmModule });// reuse across instantiations
then Phase 2's newQuickJSWASMModule() → newQuickJSWASMModule(FAST_VARIANT).
Confirm how to obtain baseWasmBytes once for the RELEASE_SYNC variant (variant wasmLocation; CustomizeVariantOptions.wasmBinary). Fallback: the Emscripten instantiateWasm(imports, onSuccess) hook via emscriptenModule — new WebAssembly.Instance(cachedModule, imports) per call.
If clean bytes access proves awkward in 0.32, use the instantiateWasm fallback; if neither is clean, this phase is deferrable — Phase 2 already removes the asyncify cost.
Deferred (PR #3318, ADR-0102 D3). After verifying the quickjs-emscripten@0.32.0 API against the installed sync variant, precompile-once does not clear D3's own bar:
No clean, portable, edge-safe way to obtain the .wasm bytes.@jitl/quickjs-wasmfile-release-sync loads its wasm lazily via the variant's importModuleLoader (node/browser/workerd conditions). Precompiling needs the raw bytes first — sourcing them ourselves means a Node fs/fetch of emscripten-module.wasm (breaks the Workers/edge-safe design that motivated quickjs-emscripten over isolated-vm) or replicating emscripten's per-runtime locateFile (fragile). The instantiateWasm hook has the same problem.
Revisit only if profiling shows per-invocation compile is a real hotspot and quickjs-emscripten exposes a portable precompiled-module handle. Until then, D1 (#3301) + D2 (#3309) stand on their own. Closed via #3318.
Activity
docs(adr): ADR-0102 — sandbox CPU-time budget + per-invocation sync W…
os-zhuang commentedon Jul 19, 2026
Deferred (PR #3318, ADR-0102 D3). After verifying the
quickjs-emscripten@0.32.0API against the installed sync variant, precompile-once does not clear D3's own bar:.wasmbytes.@jitl/quickjs-wasmfile-release-syncloads its wasm lazily via the variant'simportModuleLoader(node/browser/workerdconditions). Precompiling needs the raw bytes first — sourcing them ourselves means a Nodefs/fetch ofemscripten-module.wasm(breaks the Workers/edge-safe design that motivated quickjs-emscripten over isolated-vm) or replicating emscripten's per-runtimelocateFile(fragile). TheinstantiateWasmhook has the same problem.newQuickJSWASMModule()largely amortizes the compile already; D3 wouldn't remove the inherent per-invocation instantiate. Phase 2 (perf(runtime): drop asyncify — sandbox on the sync QuickJS variant (ADR-0102 D2, #3296) #3309) already shipped the dominant win — dropping asyncify.Revisit only if profiling shows per-invocation compile is a real hotspot and quickjs-emscripten exposes a portable precompiled-module handle. Until then, D1 (#3301) + D2 (#3309) stand on their own. Closed via #3318.
Generated by Claude Code
docs(adr): ADR-0102 D3 (precompile WASM) — DEFERRED after API verific…