| // |jit-test| error:done |
| |
| load(libdir + "iteration.js"); |
| |
| function *f1() { |
| yield 1; |
| yield 2; |
| } |
| |
| // Return after initial yield. |
| var it = f1(); |
| assertIteratorResult(it.return(3), 3, true); |
| assertIteratorResult(it.return(Math), Math, true); |
| assertIteratorResult(it.return(), undefined, true); |
| assertIteratorDone(it); |
| |
| // Return after other yield. |
| it = f1(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(null), null, true); |
| assertIteratorDone(it); |
| |
| // Finally blocks should run and can override the return value. |
| function *f2() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| return 9; |
| } |
| } |
| it = f2(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(3), 9, true); |
| assertIteratorDone(it); |
| |
| // Yield in finally block can override the return, but we should still |
| // return the correct value after that. |
| function *f3() { |
| try { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| yield 3; |
| } |
| } finally { |
| yield 4; |
| } |
| } |
| it = f3(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(9), 3, false); |
| assertIteratorNext(it, 4); |
| assertIteratorDone(it, 9); |
| assertIteratorDone(it, undefined); |
| |
| // Finally block can throw. |
| function *f4() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| throw 3; |
| } |
| } |
| it = f4(); |
| assertIteratorNext(it, 1); |
| assertThrowsValue(() => it.return(8), 3); |
| assertIteratorDone(it); |
| |
| function *f5() {} |
| it = f5(); |
| assertIteratorDone(it); |
| assertIteratorResult(it.return(3), 3, true); |
| assertIteratorDone(it); |
| |
| function *f6() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| try { |
| return 9; |
| } finally { |
| yield 3; |
| } |
| } |
| } |
| it = f6(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(5), 3, false); |
| assertIteratorDone(it, 9); |
| assertIteratorDone(it); |
| |
| // If we yield in a finally block, a second .return() can override |
| // the first one. |
| function *f7() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| try { |
| yield 3; |
| } finally { |
| yield 4; |
| } |
| } |
| } |
| it = f7(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(5), 3, false); |
| assertIteratorResult(it.return(6), 4, false); |
| assertIteratorDone(it, 6); |
| assertIteratorDone(it); |
| |
| // If we yield in a finally block, .throw() should work. |
| function *f8() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| yield 3; |
| } |
| } |
| it = f8(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(5), 3, false); |
| assertThrowsValue(() => it.throw(4), 4); |
| assertIteratorDone(it); |
| |
| // If the generator is already running, we should throw a TypeError. |
| function *f9() { |
| try { |
| yield 1; |
| yield 2; |
| } finally { |
| it.return(4); |
| yield 3; |
| } |
| } |
| it = f9(); |
| assertIteratorNext(it, 1); |
| assertThrowsInstanceOf(() => it.return(5), TypeError); |
| assertIteratorDone(it); |
| assertIteratorDone(it); |
| |
| // Second return overrides first one and closes the generator. |
| function *f10() { |
| try { |
| yield 1; |
| } finally { |
| yield 2; |
| } |
| } |
| it = f10(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(-1), 2, false); |
| assertIteratorResult(it.return(-2), -2, true); |
| assertIteratorDone(it); |
| |
| function *f11() { |
| try { |
| try { |
| yield 1; |
| } finally { |
| throw 2; |
| } |
| } catch(e) { |
| yield e; |
| } finally { |
| yield 3; |
| } |
| } |
| it = f11(); |
| assertIteratorNext(it, 1); |
| assertIteratorResult(it.return(9), 2, false); |
| assertIteratorNext(it, 3); |
| assertIteratorDone(it); |
| |
| throw "done"; |