| // Copyright 2014 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. |
| |
| // Test generator states. |
| |
| function Foo() {} |
| function Bar() {} |
| |
| function assertIteratorResult(value, done, result) { |
| assertEquals({ value: value, done: done}, result); |
| } |
| |
| function assertIteratorIsClosed(iter) { |
| assertIteratorResult(undefined, true, iter.next()); |
| // Next and throw on a closed iterator. |
| assertDoesNotThrow(function() { iter.next(); }); |
| assertThrows(function() { iter.throw(new Bar); }, Bar); |
| } |
| |
| var iter; |
| function* nextGenerator() { yield iter.next(); } |
| function* throwGenerator() { yield iter.throw(new Bar); } |
| |
| // Throw on a suspendedStart iterator. |
| iter = nextGenerator(); |
| assertThrows(function() { iter.throw(new Foo) }, Foo) |
| assertIteratorIsClosed(iter); |
| assertThrows(function() { iter.throw(new Foo) }, Foo) |
| assertIteratorIsClosed(iter); |
| |
| // The same. |
| iter = throwGenerator(); |
| assertThrows(function() { iter.throw(new Foo) }, Foo) |
| assertThrows(function() { iter.throw(new Foo) }, Foo) |
| assertIteratorIsClosed(iter); |
| |
| // Next on an executing iterator raises a TypeError. |
| iter = nextGenerator(); |
| assertThrows(function() { iter.next() }, TypeError) |
| assertIteratorIsClosed(iter); |
| |
| // Throw on an executing iterator raises a TypeError. |
| iter = throwGenerator(); |
| assertThrows(function() { iter.next() }, TypeError) |
| assertIteratorIsClosed(iter); |
| |
| // Next on an executing iterator doesn't change the state of the |
| // generator. |
| iter = (function* () { |
| try { |
| iter.next(); |
| yield 1; |
| } catch (e) { |
| try { |
| // This next() should raise the same exception, because the first |
| // next() left the iter in the executing state. |
| iter.next(); |
| yield 2; |
| } catch (e) { |
| yield 3; |
| } |
| } |
| yield 4; |
| })(); |
| assertIteratorResult(3, false, iter.next()); |
| assertIteratorResult(4, false, iter.next()); |
| assertIteratorIsClosed(iter); |
| |
| |
| // A return that doesn't close. |
| { |
| let g = function*() { try {return 42} finally {yield 43} }; |
| |
| let x = g(); |
| assertEquals({value: 43, done: false}, x.next()); |
| assertEquals({value: 42, done: true}, x.next()); |
| } |
| { |
| let x; |
| let g = function*() { try {return 42} finally {x.throw(666)} }; |
| |
| x = g(); |
| assertThrows(() => x.next(), TypeError); // Still executing. |
| } |
| { |
| let x; |
| let g = function*() { |
| try {return 42} finally {try {x.throw(666)} catch(e) {}} |
| }; |
| |
| x = g(); |
| assertEquals({value: 42, done: true}, x.next()); |
| } |