Source code

Revision control

Copy as Markdown

Other Tools

// Frame properties and methods work in generator-resuming onEnterFrame events.
// Also tests onPop events, for good measure.
let g = newGlobal({newCompartment: true});
g.eval(`\
function* gen(lo, hi) {
var a = 1/2;
yield a;
yield a * a;
}
`);
let dbg = new Debugger;
let gw = dbg.addDebuggee(g);
let hits = 0;
let savedScript = null;
let savedEnv = null;
let savedOffsets = new Set;
function check(frame) {
assertEq(frame.type, "call");
assertEq(frame.constructing, false);
assertEq(frame.callee, gw.makeDebuggeeValue(g.gen));
// `arguments` elements don't work in resumed generator frames,
// because generators don't keep the arguments around.
// However, some of this is initialized when the frame.arguments object is
// created, so if they are created during the first onEnterFrame or onPop
// event, the properties exist, and those events can also see the values.
assertEq(frame.arguments.length, args.length);
for (var i = 0; i < args.length; i++) {
assertEq(frame.arguments.hasOwnProperty(i), true);
if (hits < 2)
assertEq(frame.arguments[i], gw.makeDebuggeeValue(args[i]), `arguments[${i}]`);
else
assertEq(frame.arguments[i], undefined);
}
if (savedEnv === null) {
savedEnv = frame.environment;
assertEq(savedScript, null);
savedScript = frame.script;
} else {
assertEq(frame.environment, savedEnv);
assertEq(frame.script, savedScript);
}
let a_expected = hits < 3 ? undefined : 1/2;
assertEq(savedEnv.getVariable("a"), a_expected);
assertEq(frame.onStack, true);
let pc = frame.offset;
assertEq(savedOffsets.has(pc), false);
savedOffsets.add(pc);
assertEq(frame.older, null);
assertEq(frame.this, gw.makeDebuggeeValue(g));
assertEq(typeof frame.implementation, "string");
// And the moment of truth:
assertEq(frame.eval("2 + 2").return, 4);
assertEq(frame.eval("a").return, a_expected);
assertEq(frame.eval("if (a !== undefined) { assertEq(a < (lo + hi) / 2, true); } 7;").return, 7);
}
dbg.onEnterFrame = frame => {
if (frame.type === "eval")
return;
check(frame);
hits++;
frame.onPop = completion => {
check(frame);
hits++;
};
};
// g.gen ignores the arguments passed to it, but we use them to test
// frame.arguments.
let args = [0, 10, g, dbg];
for (let v of g.gen(...args)) {}
assertEq(hits, 8);