Source code
Revision control
Copy as Markdown
Other Tools
// Tests stepping through the wasm code with JS PI suspendable stack.
const g = newGlobal({ newCompartment: true });
const dbg = new Debugger(g);
// Estimate internal SP range.
var base = stackPointerInfo();
var estimatedLimit = base - 300000;
var checkFailed = false;
var checksPerformed = {};
// Checks current SP being in the estimated range --
// the debugger callbacks must be executed on the main stack.
function checkStack(s) {
var sp = stackPointerInfo();
checksPerformed[s] = true;
if (sp < estimatedLimit || sp > base) {
print(`Check failed: ${sp} not in [${estimatedLimit}, ${base}], at ${s}`);
checkFailed = true;
}
}
checkStack();
assertEq(checkFailed, false);
dbg.onEnterFrame = function(frame) {
if (frame.type != "wasmcall") {
return;
}
checkStack("enter");
frame.onStep = () => {
checkStack("step");
frame.offset; // check if frame is valid
};
frame.onPop = () => {
checkStack("pop");
}
};
dbg.onExceptionUnwind = function (f, e) {
checkStack("exception");
};
// Run typical JS PI program: create suspendable stack, suspend execution,
// throw on suspendable stack.
g.eval(`
function wasmEvalText(t, imp) {
var wasm = wasmTextToBinary(t)
var mod = new WebAssembly.Module(wasm);
var ins = new WebAssembly.Instance(mod, imp);
return ins;
}
try{throw"";}catch(_){} // init onExceptionUnwind
var compute_delta = (i) => {
return Promise.resolve(i/100 || 1);
};
var suspending_compute_delta = new WebAssembly.Suspending(compute_delta);
var ins = wasmEvalText(\`(module
(import "js" "compute_delta"
(func $compute_delta (param i32) (result f64)))
(tag $t)
(func (export "update_state_export") (param i32) (result f64)
local.get 0
call $compute_delta
i32.const 4
i32.const 2
i32.add
drop
throw $t
)
)\`, {
js: {
compute_delta: suspending_compute_delta,
},
});
var update_state = WebAssembly.promising(ins.exports.update_state_export);
var res = update_state(4);
res.then((r) => {
print("RES:" + r);
}).catch(e => {
print("ERR: " + e);
});
drainJobQueue();
`);
assertEq(checkFailed, false);
for (let i of ['enter', 'step', 'pop', 'exception']) {
assertEq(i in checksPerformed, true, `${i} check performed`);
}