ef8fa8521c
The for-of-finalization CL incorrectly removed the input argument from BuildIteratorClose. I'm reverting this, adding a regression test, and fixing an existing test that was wrong. BUG= R=rossberg Review URL: https://codereview.chromium.org/1750543002 Cr-Commit-Position: refs/heads/master@{#34384}
273 lines
7.9 KiB
JavaScript
273 lines
7.9 KiB
JavaScript
// 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));
|
|
}
|
|
}
|