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