Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| --fast-warmup; --no-threads
function* forOf(a) {
let s = 0;
for (const v of a) {
s += v;
yield s;
}
return s;
}
// for-of over a custom iterator.
function* forOfCustom(n) {
const iterable = {
[Symbol.iterator]() {
let i = 0;
return { next: () => (i < n ? { value: i++, done: false }
: { value: undefined, done: true }) };
}
};
let s = 0;
for (const v of iterable) {
s += v;
yield s;
}
return s;
}
// Nested iterator loops.
function* nestedForOf(a, b) {
let s = "";
for (const x of a) {
for (const y of b) {
s += x + y;
yield s;
}
}
return s;
}
// for-in nested inside for-of.
function* mixed(a, o) {
let s = "";
for (const v of a) {
for (const k in o) {
s += v + k;
yield s;
}
}
return s;
}
// Breaking out of a for-of runs the iterator close while suspended values are
// still live.
function* earlyBreak(a) {
let s = 0;
for (const v of a) {
s += v;
yield s;
if (v >= 2) {
break;
}
}
return s;
}
function drive(g) {
let out = [], r;
while (!(r = g.next()).done) {
out.push(String(r.value));
}
out.push(String(r.value));
return out.join(",");
}
const cases = [
["forOf", () => forOf([1, 2, 3]), "1,3,6,6"],
["forOfCustom", () => forOfCustom(3), "0,1,3,3"],
["nestedForOf", () => nestedForOf(["a", "b"], ["x", "y"]),
"ax,axay,axaybx,axaybxby,axaybxby"],
["mixed", () => mixed(["p", "q"], { m: 1, n: 2 }),
"pm,pmpn,pmpnqm,pmpnqmqn,pmpnqmqn"],
["earlyBreak", () => earlyBreak([1, 2, 3, 4]), "1,3,3"],
];
for (let i = 0; i < 200; i++) {
for (const [name, mk, expected] of cases) {
assertEq(drive(mk()), expected, name);
}
}
// Abandoning a suspended for-of must still close the iterator.
let closed = 0;
function* closes(n) {
const iterable = {
[Symbol.iterator]() {
let i = 0;
return {
next: () => (i < n ? { value: i++, done: false }
: { value: undefined, done: true }),
return: () => { closed++; return { done: true }; },
};
}
};
for (const v of iterable) {
yield v;
}
}
for (let i = 0; i < 200; i++) {
const g = closes(5);
assertEq(g.next().value, 0);
assertEq(g.next().value, 1);
assertEq(g.return("stop").value, "stop");
}
assertEq(closed, 200);