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:
const wasmModule = await WebAssembly.compile(baseWasmBytes); // compile ONCE
const FAST_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.
Acceptance criteria
Do NOT take the shared-singleton-module route (see #3275 §REJECTED — cross-tenant blast radius + RSS ratchet).
Refs: #3275 (parent) · #3296 (Phase 2).
🤖 Generated with Claude Code
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 })wherewasmModule?: OrLoader<WebAssembly.Module>— "Emscripten will instantiate the WebAssembly.Instance from this existing WebAssembly.Module." The compiledWebAssembly.Moduleis stateless bytecode; eachnewQuickJSWASMModule(variant)still allocates a fresh linear memory (isolation preserved) as long aswasmMemoryis NOT also passed (that would share memory = the rejected model).Change (
packages/runtime/src/sandbox/quickjs-runner.ts), module-level once per process:then Phase 2's
newQuickJSWASMModule()→newQuickJSWASMModule(FAST_VARIANT).baseWasmBytesonce for theRELEASE_SYNCvariant (variantwasmLocation;CustomizeVariantOptions.wasmBinary). Fallback: the EmscripteninstantiateWasm(imports, onSuccess)hook viaemscriptenModule—new WebAssembly.Instance(cachedModule, imports)per call.instantiateWasmfallback; if neither is clean, this phase is deferrable — Phase 2 already removes the asyncify cost.Acceptance criteria
Do NOT take the shared-singleton-module route (see #3275 §REJECTED — cross-tenant blast radius + RSS ratchet).
Refs: #3275 (parent) · #3296 (Phase 2).
🤖 Generated with Claude Code