michael@0: // Setting a breakpoint in a generator function works, and we can michael@0: // traverse the stack and evaluate expressions in the context of older michael@0: // generator frames. michael@0: michael@0: var g = newGlobal(); michael@0: var dbg = Debugger(g); michael@0: dbg.onDebuggerStatement = function (frame) { michael@0: function hit(frame) { michael@0: assertEq(frame.generator, true); michael@0: assertEq(frame.older.generator, true); michael@0: frame.older.eval("q += 16"); michael@0: } michael@0: michael@0: var s = frame.script; michael@0: var offs = s.getLineOffsets(g.line0 + 9); michael@0: for (var i = 0; i < offs.length; i++) michael@0: s.setBreakpoint(offs[i], {hit: hit}); michael@0: }; michael@0: michael@0: g.eval("line0 = Error().lineNumber;\n" + michael@0: "function* g(x) {\n" + // + 1 michael@0: " var q = 10;\n" + // + 2 michael@0: " yield* x;\n" + // + 3 michael@0: " return q;\n" + // + 4 michael@0: "}\n" + // + 5 michael@0: "function* range(n) {\n" + // + 6 michael@0: " debugger;\n" + // + 7 michael@0: " for (var i = 0; i < n; i++)\n" + // + 8 michael@0: " yield i;\n" + // + 9 <-- breakpoint michael@0: " return;\n" + // so that line 9 only has the yield michael@0: "}"); michael@0: michael@0: g.eval("var iter = g(range(2))"); michael@0: g.eval("var first = iter.next().value"); michael@0: g.eval("var second = iter.next().value"); michael@0: g.eval("var third = iter.next().value"); michael@0: michael@0: assertEq(g.first, 0); michael@0: assertEq(g.second, 1); michael@0: assertEq(g.third, 42);