Skip to content

sandbox Phase 2 — drop asyncify (sync QuickJS variant), keep per-invocation modules #3296

Description

@os-zhuang

Part 2 of #3275 — see its Phase 2 section for the full spec. Blocked by #3295 (Phase 1).

Verified against the installed quickjs-emscripten@0.32.0: the sync release variant @jitl/quickjs-wasmfile-release-sync (RELEASE_SYNC) is already installed — no new dependency. The sync QuickJSContext exposes evalCode() + newPromise(), and its .runtime exposes executePendingJobs() / setInterruptHandler() / setMemoryLimit() / setMaxStackSize() — identical to the async path.

Change (packages/runtime/src/sandbox/quickjs-runner.ts):

  • newAsyncContext()const mod = await newQuickJSWASMModule(); const vm = mod.newContext(); — a fresh isolated module (own linear memory) per invocation, so the isolation model is UNCHANGED (confirmed in the .d.ts; only newContext() on a shared module shares memory, which we do not do).
  • vm.evalCodeAsync(wrapped)vm.evalCode(wrapped).
  • Imports/types: newAsyncContext/QuickJSAsyncContextnewQuickJSWASMModule/QuickJSContext.
  • Disposal: hold both mod and vm; in finally dispose the context then the module (verify whether disposing the context alone frees the module in 0.32 — dispose the module explicitly to be safe; it owns the linear memory).

Why it's safe now: the original crashes were an ASYNCIFY limitation (one suspended stack per module); the deferred-promise + pump redesign already removed all wasm-stack suspension (installApiMethod uses plain newPromise, not newAsyncifiedFunction). See #3275 §Phase 2.

Acceptance criteria

  • Sync variant wired; per-invocation module isolation preserved; disposal frees the linear memory.
  • Re-entrancy / fan-out / lvl4-nesting / real-sqlite suites green unchanged.
  • Bench (quickjs-runner.bench.ts, npx vitest bench) shows the expected compile/instantiate + per-instruction win vs asyncify.
  • Changeset (@objectstack/runtime patch/minor).

Refs: #3275 (parent) · #3295 (Phase 1).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions