// Test yield* with iter.throw and monkeypatching. function* g1() { return (yield 1); } function* g2() { try { yield 1; } catch (e) { yield e; } } function* delegate(iter) { return yield* iter; } var GeneratorObjectPrototype = Object.getPrototypeOf(g1).prototype; var GeneratorObjectPrototype_throw = GeneratorObjectPrototype.throw; // An uncaught delegated throw. var inner = g1(); var outer = delegate(inner); assertIteratorNext(outer, 1); assertThrowsValue(function () { outer.throw(42) }, 42); assertThrowsValue(function () { outer.throw(42) }, 42); // A caught delegated throw. inner = g2(); outer = delegate(inner); assertIteratorNext(outer, 1); assertIteratorResult(outer.throw(42), 42, false); assertThrowsValue(function () { outer.throw(42) }, 42); assertThrowsValue(function () { outer.throw(42) }, 42); // What would be an uncaught delegated throw, but with a monkeypatched iterator. inner = g1(); outer = delegate(inner); assertIteratorNext(outer, 1); inner.throw = function(e) { return { value: e*2 }; }; assertEq(84, outer.throw(42).value); assertIteratorDone(outer, undefined); // Monkeypatching inner.next. inner = g1(); outer = delegate(inner); inner.next = function() { return { value: 13, done: true } }; assertIteratorDone(outer, 13); // What would be a caught delegated throw, but with a monkeypunched prototype. inner = g2(); outer = delegate(inner); assertIteratorNext(outer, 1); delete GeneratorObjectPrototype.throw; var outer_throw_42 = GeneratorObjectPrototype_throw.bind(outer, 42); // yield* protocol violation: no 'throw' method assertThrowsInstanceOf(outer_throw_42, TypeError); // Now done, so just throws. assertThrowsValue(outer_throw_42, 42); // Monkeypunch a different throw handler. inner = g2(); outer = delegate(inner); outer_throw_42 = GeneratorObjectPrototype_throw.bind(outer, 42); assertIteratorNext(outer, 1); GeneratorObjectPrototype.throw = function(e) { return { value: e*2 }; } assertEq(84, outer_throw_42().value); assertEq(84, outer_throw_42().value); // This continues indefinitely. assertEq(84, outer_throw_42().value); assertIteratorDone(outer, undefined); // The same, but restoring the original pre-monkey throw. inner = g2(); outer = delegate(inner); outer_throw_42 = GeneratorObjectPrototype_throw.bind(outer, 42); assertIteratorNext(outer, 1); assertEq(84, outer_throw_42().value); assertEq(84, outer_throw_42().value); GeneratorObjectPrototype.throw = GeneratorObjectPrototype_throw; assertIteratorResult(outer_throw_42(), 42, false); assertIteratorDone(outer, undefined); if (typeof reportCompare == "function") reportCompare(true, true);