| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --harmony-iterator-close |
| |
| function* g() { yield 42; return 88 }; |
| |
| |
| // Return method is "undefined". |
| { |
| g.prototype.return = null; |
| |
| assertEquals(undefined, (() => { |
| for (let x of g()) { break; } |
| })()); |
| |
| assertEquals(undefined, (() => { |
| for (x of g()) { break; } |
| })()); |
| |
| assertThrowsEquals(() => { |
| for (let x of g()) { throw 42; } |
| }, 42); |
| |
| assertThrowsEquals(() => { |
| for (x of g()) { throw 42; } |
| }, 42); |
| |
| assertEquals(42, (() => { |
| for (let x of g()) { return 42; } |
| })()); |
| |
| assertEquals(42, (() => { |
| for (x of g()) { return 42; } |
| })()); |
| |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| } |
| |
| |
| // Return method is not callable. |
| { |
| g.prototype.return = 666; |
| |
| assertThrows(() => { |
| for (let x of g()) { break; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { break; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (let x of g()) { throw 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { throw 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (let x of g()) { return 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { return 666; } |
| }, TypeError); |
| |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| } |
| |
| |
| // Return method does not return an object. |
| { |
| g.prototype.return = () => 666; |
| |
| assertThrows(() => { |
| for (let x of g()) { break; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { break; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (let x of g()) { throw 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { throw 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (let x of g()) { return 666; } |
| }, TypeError); |
| |
| assertThrows(() => { |
| for (x of g()) { return 666; } |
| }, TypeError); |
| |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| |
| assertEquals(42, eval('for (x of g()) { x; }')); |
| } |
| |
| |
| // Return method returns an object. |
| { |
| let log = []; |
| g.prototype.return = (...args) => { log.push(args); return {} }; |
| |
| log = []; |
| for (let x of g()) { break; } |
| assertEquals([[]], log); |
| |
| log = []; |
| for (x of g()) { break; } |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g()) { throw 42; } |
| }, 42); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (x of g()) { throw 42; } |
| }, 42); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertEquals(42, (() => { |
| for (let x of g()) { return 42; } |
| })()); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertEquals(42, (() => { |
| for (x of g()) { return 42; } |
| })()); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| assertEquals([], log); |
| |
| log = []; |
| assertEquals(42, eval('for (x of g()) { x; }')); |
| assertEquals([], log); |
| } |
| |
| |
| // Return method throws. |
| { |
| let log = []; |
| g.prototype.return = (...args) => { log.push(args); throw 23 }; |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g()) { break; } |
| }, 23); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (x of g()) { break; } |
| }, 23); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g()) { throw 42; } |
| }, 42); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (x of g()) { throw 42; } |
| }, 42); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g()) { return 42; } |
| }, 23); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (x of g()) { return 42; } |
| }, 23); |
| assertEquals([[]], log); |
| |
| log = []; |
| assertEquals(42, eval('for (let x of g()) { x; }')); |
| assertEquals([], log); |
| |
| log = []; |
| assertEquals(42, eval('for (x of g()) { x; }')); |
| assertEquals([], log); |
| } |
| |
| |
| // Next method throws. |
| { |
| g.prototype.next = () => { throw 666; }; |
| g.prototype.return = () => { assertUnreachable() }; |
| |
| assertThrowsEquals(() => { |
| for (let x of g()) {} |
| }, 666); |
| |
| assertThrowsEquals(() => { |
| for (x of g()) {} |
| }, 666); |
| } |
| |
| |
| // Nested loops. |
| { |
| function* g1() { yield 1; yield 2; throw 3; } |
| function* g2() { yield -1; yield -2; throw -3; } |
| |
| assertDoesNotThrow(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break; |
| } |
| if (x == 2) break; |
| } |
| }, -3); |
| |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| } |
| } |
| }, -3); |
| |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break; |
| } |
| } |
| }, 3); |
| |
| assertDoesNotThrow(() => { |
| l: for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break l; |
| } |
| } |
| }); |
| |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| throw 4; |
| } |
| } |
| }, 4); |
| |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) throw 4; |
| } |
| } |
| }, 4); |
| |
| let log = []; |
| g1.prototype.return = () => { log.push(1); throw 5 }; |
| g2.prototype.return = () => { log.push(2); throw -5 }; |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break; |
| } |
| if (x == 2) break; |
| } |
| }, -5); |
| assertEquals([2, 1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| } |
| } |
| }, -3); |
| assertEquals([1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break; |
| } |
| } |
| }, -5); |
| assertEquals([2, 1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| l: for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) break l; |
| } |
| } |
| }, -5); |
| assertEquals([2, 1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| throw 4; |
| } |
| } |
| }, 4); |
| assertEquals([2, 1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| for (let y of g2()) { |
| if (y == -2) throw 4; |
| } |
| } |
| }, 4); |
| assertEquals([2, 1], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| try { |
| for (let y of g2()) { |
| } |
| } catch (_) {} |
| } |
| }, 3); |
| assertEquals([], log); |
| |
| log = []; |
| assertThrowsEquals(() => { |
| for (let x of g1()) { |
| try { |
| for (let y of g2()) { |
| } |
| } catch (_) {} |
| if (x == 2) break; |
| } |
| }, 5); |
| assertEquals([1], log); |
| } |