| // 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. |
| |
| |
| { // yield in try-catch |
| |
| let g = function*() { |
| try {yield 1} catch (error) {assertEquals("caught", error)} |
| }; |
| |
| assertThrowsEquals(() => g().throw("not caught"), "not caught"); |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.throw("caught")); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| assertThrowsEquals(() => x.throw("not caught"), "not caught"); |
| } |
| } |
| |
| |
| { // 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()); |
| } |
| } |
| |
| |
| { // return that doesn't close |
| let x; |
| let g = function*() { try {return 42} finally {x.throw(666)} }; |
| |
| { |
| x = g(); |
| assertThrows(() => x.next(), TypeError); // still executing |
| } |
| } |
| |
| |
| { // yield in try-finally, finally clause performs return |
| |
| let g = function*() { try {yield 42} finally {return 13} }; |
| |
| { // "return" closes at suspendedStart |
| let x = g(); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next(42)); |
| assertThrowsEquals(() => x.throw(43), 43); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| |
| { // "throw" closes at suspendedStart |
| let x = g(); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: undefined, done: true}, x.next(42)); |
| assertEquals({value: 43, done: true}, x.return(43)); |
| assertThrowsEquals(() => x.throw(44), 44); |
| } |
| |
| { // "next" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 13, done: true}, x.next(666)); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertThrowsEquals(() => x.throw(666), 666); |
| } |
| |
| { // "return" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 13, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| } |
| |
| { // "throw" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 13, done: true}, x.throw(666)); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| } |
| } |
| |
| |
| { // yield in try-finally, finally clause doesn't perform return |
| |
| let g = function*() { try {yield 42} finally {13} }; |
| |
| { // "return" closes at suspendedStart |
| let x = g(); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next(42)); |
| assertThrowsEquals(() => x.throw(43), 43); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| |
| { // "throw" closes at suspendedStart |
| let x = g(); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: undefined, done: true}, x.next(42)); |
| assertEquals({value: 43, done: true}, x.return(43)); |
| assertThrowsEquals(() => x.throw(44), 44); |
| } |
| |
| { // "next" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| |
| { // "return" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertThrowsEquals(() => x.throw(44), 44); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| |
| { // "throw" closes at suspendedYield |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: undefined, done: true}, x.next(666)); |
| assertThrowsEquals(() => x.throw(666), 666); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| } |
| |
| |
| { // yield in try-finally, finally clause yields and performs return |
| |
| let g = function*() { try {yield 42} finally {yield 43; return 13} }; |
| |
| { |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.return(666)); |
| assertEquals({value: 13, done: true}, x.next()); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next()); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| } |
| } |
| |
| |
| { // yield in try-finally, finally clause yields and doesn't perform return |
| |
| let g = function*() { try {yield 42} finally {yield 43; 13} }; |
| |
| { |
| let x = g(); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.return(666)); |
| assertEquals({value: 666, done: true}, x.next()); |
| assertEquals({value: 5, done: true}, x.return(5)); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| assertEquals({value: undefined, done: true}, x.next()); |
| assertEquals({value: 666, done: true}, x.return(666)); |
| } |
| } |
| |
| |
| { // yield*, finally clause performs return |
| |
| let h = function*() { try {yield 42} finally {yield 43; return 13} }; |
| let g = function*() { yield 1; yield yield* h(); }; |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.next(666)); |
| assertEquals({value: 13, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.return(666)); |
| assertEquals({value: 13, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.throw(666)); |
| assertEquals({value: 13, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| } |
| } |
| |
| |
| { // yield*, finally clause does not perform return |
| |
| let h = function*() { try {yield 42} finally {yield 43; 13} }; |
| let g = function*() { yield 1; yield yield* h(); }; |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.next(666)); |
| assertEquals({value: undefined, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.return(44)); |
| assertEquals({value: 44, done: false}, x.next()); |
| assertEquals({value: undefined, done: true}, x.next()); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 42, done: false}, x.next()); |
| assertEquals({value: 43, done: false}, x.throw(666)); |
| assertThrowsEquals(() => x.next(), 666); |
| } |
| } |
| |
| |
| { // yield*, .return argument is final result |
| |
| function* inner() { |
| yield 2; |
| } |
| |
| function* g() { |
| yield 1; |
| return yield* inner(); |
| } |
| |
| { |
| let x = g(); |
| assertEquals({value: 1, done: false}, x.next()); |
| assertEquals({value: 2, done: false}, x.next()); |
| assertEquals({value: 42, done: true}, x.return(42)); |
| } |
| } |