blob: 94785de51f48f516a658f4de91c2f05b50e35da0 [file] [log] [blame]
// 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.
// Flags: --harmony-iterator-close
function* g() { yield 42; return 88 };
// Return method is "undefined".
{
g.prototype.return = null;
assertEquals(undefined, (() => {
for (let x of g()) { break; }
})());
assertEquals(undefined, (() => {
for (x of g()) { break; }
})());
assertThrowsEquals(() => {
for (let x of g()) { throw 42; }
}, 42);
assertThrowsEquals(() => {
for (x of g()) { throw 42; }
}, 42);
assertEquals(42, (() => {
for (let x of g()) { return 42; }
})());
assertEquals(42, (() => {
for (x of g()) { return 42; }
})());
assertEquals(42, eval('for (let x of g()) { x; }'));
assertEquals(42, eval('for (let x of g()) { x; }'));
}
// Return method is not callable.
{
g.prototype.return = 666;
assertThrows(() => {
for (let x of g()) { break; }
}, TypeError);
assertThrows(() => {
for (x of g()) { break; }
}, TypeError);
assertThrows(() => {
for (let x of g()) { throw 666; }
}, TypeError);
assertThrows(() => {
for (x of g()) { throw 666; }
}, TypeError);
assertThrows(() => {
for (let x of g()) { return 666; }
}, TypeError);
assertThrows(() => {
for (x of g()) { return 666; }
}, TypeError);
assertEquals(42, eval('for (let x of g()) { x; }'));
assertEquals(42, eval('for (let x of g()) { x; }'));
}
// Return method does not return an object.
{
g.prototype.return = () => 666;
assertThrows(() => {
for (let x of g()) { break; }
}, TypeError);
assertThrows(() => {
for (x of g()) { break; }
}, TypeError);
assertThrows(() => {
for (let x of g()) { throw 666; }
}, TypeError);
assertThrows(() => {
for (x of g()) { throw 666; }
}, TypeError);
assertThrows(() => {
for (let x of g()) { return 666; }
}, TypeError);
assertThrows(() => {
for (x of g()) { return 666; }
}, TypeError);
assertEquals(42, eval('for (let x of g()) { x; }'));
assertEquals(42, eval('for (x of g()) { x; }'));
}
// Return method returns an object.
{
let log = [];
g.prototype.return = (...args) => { log.push(args); return {} };
log = [];
for (let x of g()) { break; }
assertEquals([[]], log);
log = [];
for (x of g()) { break; }
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (let x of g()) { throw 42; }
}, 42);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (x of g()) { throw 42; }
}, 42);
assertEquals([[]], log);
log = [];
assertEquals(42, (() => {
for (let x of g()) { return 42; }
})());
assertEquals([[]], log);
log = [];
assertEquals(42, (() => {
for (x of g()) { return 42; }
})());
assertEquals([[]], log);
log = [];
assertEquals(42, eval('for (let x of g()) { x; }'));
assertEquals([], log);
log = [];
assertEquals(42, eval('for (x of g()) { x; }'));
assertEquals([], log);
}
// Return method throws.
{
let log = [];
g.prototype.return = (...args) => { log.push(args); throw 23 };
log = [];
assertThrowsEquals(() => {
for (let x of g()) { break; }
}, 23);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (x of g()) { break; }
}, 23);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (let x of g()) { throw 42; }
}, 42);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (x of g()) { throw 42; }
}, 42);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (let x of g()) { return 42; }
}, 23);
assertEquals([[]], log);
log = [];
assertThrowsEquals(() => {
for (x of g()) { return 42; }
}, 23);
assertEquals([[]], log);
log = [];
assertEquals(42, eval('for (let x of g()) { x; }'));
assertEquals([], log);
log = [];
assertEquals(42, eval('for (x of g()) { x; }'));
assertEquals([], log);
}
// Next method throws.
{
g.prototype.next = () => { throw 666; };
g.prototype.return = () => { assertUnreachable() };
assertThrowsEquals(() => {
for (let x of g()) {}
}, 666);
assertThrowsEquals(() => {
for (x of g()) {}
}, 666);
}
// Nested loops.
{
function* g1() { yield 1; yield 2; throw 3; }
function* g2() { yield -1; yield -2; throw -3; }
assertDoesNotThrow(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break;
}
if (x == 2) break;
}
}, -3);
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
}
}
}, -3);
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break;
}
}
}, 3);
assertDoesNotThrow(() => {
l: for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break l;
}
}
});
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
throw 4;
}
}
}, 4);
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) throw 4;
}
}
}, 4);
let log = [];
g1.prototype.return = () => { log.push(1); throw 5 };
g2.prototype.return = () => { log.push(2); throw -5 };
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break;
}
if (x == 2) break;
}
}, -5);
assertEquals([2, 1], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
}
}
}, -3);
assertEquals([1], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break;
}
}
}, -5);
assertEquals([2, 1], log);
log = [];
assertThrowsEquals(() => {
l: for (let x of g1()) {
for (let y of g2()) {
if (y == -2) break l;
}
}
}, -5);
assertEquals([2, 1], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
throw 4;
}
}
}, 4);
assertEquals([2, 1], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
for (let y of g2()) {
if (y == -2) throw 4;
}
}
}, 4);
assertEquals([2, 1], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
try {
for (let y of g2()) {
}
} catch (_) {}
}
}, 3);
assertEquals([], log);
log = [];
assertThrowsEquals(() => {
for (let x of g1()) {
try {
for (let y of g2()) {
}
} catch (_) {}
if (x == 2) break;
}
}, 5);
assertEquals([1], log);
}