v8/test/mjsunit/harmony/generators.js
neis ef8fa8521c Fix accidental bug in yield* desugaring.
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}
2016-03-01 09:39:18 +00:00

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));
}
}