Source code
Revision control
Copy as Markdown
Other Tools
// |jit-test| skip-if: !wasmJSPromiseIntegrationEnabled()
// Debugger.Frame objects for wasm frames on a JSPI continuation must be
// terminated when the continuation is GC'd, so that a reused slot cannot
// resurrect them as apparently-live frames for a different continuation.
var g = newGlobal({newCompartment: true});
var dbg = new Debugger(g);
var oldFrames = [];
var phase = 1;
dbg.onEnterFrame = function(f) {
if (f.type !== "wasmcall") return;
if (phase === 2) {
// While a new (shallow) continuation is active, verify the stale frames
// from the old (deep, already GC'd) continuation report onStack = false
// and do not crash when accessed.
for (var fr of oldFrames) {
assertEq(fr.onStack, false);
}
} else {
oldFrames.push(f);
}
};
// Phase 1: create a deep (3-frame) JSPI continuation that suspends on a
// never-resolving promise, then drop all references and GC it.
g.eval(`
var binDeep = wasmTextToBinary(\`(module
(import "" "susp" (func $susp))
(func $inner (call $susp))
(func $middle (call $inner))
(func $outer (export "outer") (call $middle))
)\`);
var neverResolve = new WebAssembly.Suspending(() => new Promise(() => {}));
var instD = new WebAssembly.Instance(new WebAssembly.Module(binDeep),
{"":{susp: neverResolve}});
var pfD = WebAssembly.promising(instD.exports.outer);
pfD();
pfD = null; instD = null; neverResolve = null; binDeep = null;
`);
gc(); gc(); gc();
assertEq(oldFrames.length, 3);
phase = 2;
// Phase 2: run a shallow (1-frame) continuation on the same allocator, which
// will reuse the freed slot. The onEnterFrame handler above verifies that the
// stale old frames correctly report onStack = false.
g.eval(`
var binShallow = wasmTextToBinary(\`(module
(import "" "susp" (func $susp))
(func $only (export "outer") (call $susp))
)\`);
var s2 = new WebAssembly.Suspending(() => new Promise(() => {}));
var instS = new WebAssembly.Instance(new WebAssembly.Module(binShallow),
{"":{susp: s2}});
var pfS = WebAssembly.promising(instS.exports.outer);
pfS();
`);
print("ok");