Thrown by Sandbox.dispose() when upstream QuickJS aborts while freeing the
runtime (#1922).
A failure raised inside a drained promise job — the reported case is an
out-of-memory in the post-await body of an async function run() — leaves
objects orphaned on rt->gc_obj_list with leaked refcounts. JS_FreeRuntime
asserts that list is empty, so teardown comes back as
Aborted(Assertion failed: list_empty(&rt->gc_obj_list)) — long after the
eval() that caused it resolved normally, with a message that says nothing
about which script did it or what to do next.
This class does not fix that; it names it. The following were each measured
against the issue's reproducer in a fresh process per trial — the
isolation matters, because emscripten latches ABORT per module instance
and every trial after the first on one module reports a false clean:
forcing a QuickJS collection before teardown, by allocating 256 through
1,000,000 object literals in the realm: still aborts. The orphaned objects
have leaked refcounts, so the collector cannot reach them.
the same with the memory limit lifted first, and with large retained-then-
dropped allocations to push past the collector's threshold: still aborts.
draining the job queue repeatedly, creating and freeing a second context,
and skipping context.dispose(): all still abort.
quickjs-emscripten 0.32 exposes no GC entry point, so preventing the abort
has no in-repo lever. Surviving it does: the aborted module is retired and
the next sandbox is built on a fresh instance, so this error means "the
script that just ran is over", not "scripting is over until a page reload"
(see quickjs-module.ts).
Thrown by
Sandbox.dispose()when upstream QuickJS aborts while freeing the runtime (#1922).A failure raised inside a drained promise job — the reported case is an out-of-memory in the post-
awaitbody of anasync function run()— leaves objects orphaned onrt->gc_obj_listwith leaked refcounts.JS_FreeRuntimeasserts that list is empty, so teardown comes back asAborted(Assertion failed: list_empty(&rt->gc_obj_list))— long after theeval()that caused it resolved normally, with a message that says nothing about which script did it or what to do next.This class does not fix that; it names it. The following were each measured against the issue's reproducer in a fresh process per trial — the isolation matters, because emscripten latches
ABORTper module instance and every trial after the first on one module reports a false clean:context.dispose(): all still abort.quickjs-emscripten 0.32 exposes no GC entry point, so preventing the abort has no in-repo lever. Surviving it does: the aborted module is retired and the next sandbox is built on a fresh instance, so this error means "the script that just ran is over", not "scripting is over until a page reload" (see quickjs-module.ts).