Summary
A class that implements *[Symbol.iterator]() as a generator method, when iterated via for…of, runs an infinite loop allocating until OOM. Surfaced by test-files/test_gap_symbols.ts — the binary climbs to 5+ GB RSS before being killed.
Minimal repro
class Fibonacci {
limit: number;
constructor(limit: number) { this.limit = limit; }
*[Symbol.iterator](): Generator<number> {
let a = 0;
let b = 1;
let count = 0;
while (count < this.limit) {
yield a;
[a, b] = [b, a + b];
count++;
}
}
}
const fibs: number[] = [];
for (const f of new Fibonacci(7)) {
fibs.push(f);
}
console.log(fibs.join(","));
Expected (node --experimental-strip-types): 0,1,1,2,3,5,8
Observed: hangs forever, RSS climbs to 5+ GB before kill.
Notes
- Plain top-level generator functions iterated via
for…of work fine — only the class-method form with *[Symbol.iterator]() triggers the loop.
- Plausibly related to v0.5.503's class-method dispatch work (
#446) but verified to also hang on v0.5.498 (git checkout HEAD~5 -- crates/), so this is pre-existing.
- The full test (
test-files/test_gap_symbols.ts) reproduces; lines 1–50 (Symbol creation, Symbol.for, computed property keys) all work — only the Fibonacci block at lines 51–73 hangs.
Why this matters
The class implements iterable via *[Symbol.iterator]() pattern is the canonical way to make user classes work with for…of, spread, destructuring, and Array.from. It's listed in CLAUDE.md as a supported feature.
Summary
A class that implements
*[Symbol.iterator]()as a generator method, when iterated viafor…of, runs an infinite loop allocating until OOM. Surfaced bytest-files/test_gap_symbols.ts— the binary climbs to 5+ GB RSS before being killed.Minimal repro
Expected (
node --experimental-strip-types):0,1,1,2,3,5,8Observed: hangs forever, RSS climbs to 5+ GB before kill.
Notes
for…ofwork fine — only the class-method form with*[Symbol.iterator]()triggers the loop.#446) but verified to also hang on v0.5.498 (git checkout HEAD~5 -- crates/), so this is pre-existing.test-files/test_gap_symbols.ts) reproduces; lines 1–50 (Symbol creation,Symbol.for, computed property keys) all work — only the Fibonacci block at lines 51–73 hangs.Why this matters
The
class implements iterable via *[Symbol.iterator]()pattern is the canonical way to make user classes work withfor…of, spread, destructuring, andArray.from. It's listed in CLAUDE.md as a supported feature.