Source code

Revision control

Copy as Markdown

Other Tools

// Test for Debugger.getNewestFrame's evalInFramePrev-following behavior when
// multiple debuggers and debuggees are involved.
let G1 = newGlobal({newCompartment: true});
let G2 = newGlobal({newCompartment: true});
G2.G1 = G1;
G1.G2 = G2;
// Set up the following call stack (oldest to youngest):
//
// G1.A => G2.B => G1.C => G2.D
G1.evaluate(`
function A() { return G2.B(); }
function C() { return G2.D(); }
`);
G2.evaluate(`
function B() { return G1.C(); }
function D() { debugger; return 5; }
`);
let dbg1 = new Debugger(G1); // observes only G1
let dbg2 = new Debugger(G2); // observes only G2
let callCount = 0;
dbg2.onDebuggerStatement = function (frame) {
callCount++;
if (callCount === 1) {
// Hit the debugger-statement in G2.D. Perform an eval in
// G2.B's frame to create an eval frame with evalInFramePrev
// pointing to B's frame.
//
// The eval code contains another debugger-statement which will trigger
// the code below.
assertEq(frame.callee.name, "D");
var frameB = frame.older;
assertEq(frameB.callee.name, "B");
assertEq(frameB.older, null);
frameB.eval("debugger;");
return;
}
// Second debugger-statement (from the debugger-eval code).
// The stack now looks like this:
//
// Debugger eval frame with evalInFramePrev ---+
// G2.D |
// G1.C |
// G2.B <------------------------------------+
// G1.A
//
// If we now call dbg1.getNewestFrame(), we skip G1.C so get G1.A.
assertEq(callCount, 2);
var frameA = dbg1.getNewestFrame();
assertEq(frameA.callee.name, "A");
assertEq(frameA.older, null);
};
assertEq(G1.A(), 5);
assertEq(callCount, 2);