Source code

Revision control

Copy as Markdown

Other Tools

// Distinct generator calls result in distinct Debugger.Frames.
let g = newGlobal({newCompartment: true});
g.eval(`
function* count(n) {
if (n > 0) {
for (let x of count(n - 1))
yield x;
yield n;
}
}
`);
let log = "";
let dbg = Debugger(g);
let nextId = 0;
function mark(frame) {
if (frame.id === undefined)
frame.id = nextId++;
}
dbg.onEnterFrame = frame => {
mark(frame);
log += frame.id + "[";
frame.onPop = completion => {
mark(frame);
log += "]" + frame.id;
};
};
let j = 0;
for (let k of g.count(5)) {
assertEq(k, ++j);
log += " ";
}
assertEq(log,
// Calling a generator function just returns a generator object
// without running the body at all; hence "0[]0". However, this call
// does evaluate default argument values, if any, so we do report an
// onEnterFrame / onPop for it.
"0[]0" +
// Demanding the first value from the top generator forces
// SpiderMonkey to create all five generator objects (the empty "n[]n"
// pairs) and then demand a value from them (the longer "n[...]n"
// substrings).
"0[1[]11[2[]22[3[]33[4[]44[5[]55[]5]4]3]2]1]0 " +
"0[1[2[3[4[]4]3]2]1]0 " +
"0[1[2[3[]3]2]1]0 " +
"0[1[2[]2]1]0 " +
"0[1[]1]0 " +
"0[]0");