Repro:
const fns: (() => number)[] = [];
for (let i = 0; i < 3; i++, fns.push(() => i)) {}
return fns.map(f => f());
Expected: [1, 2, 3]
Actual: [3, 3, 3]
Per ECMA-262 CreatePerIterationEnvironment (invoked from the for statement's LabelledEvaluation), let in a for creates a fresh binding per iteration, and the update expression runs inside that per-iteration environment. We emit a single shared local i and run the update in the outer scope, so closures built in the update clause all capture the same variable. A per-iteration body wrapper isn't enough; the update expression must also run inside the per-iteration scope.
Repro:
Expected:
[1, 2, 3]Actual:
[3, 3, 3]Per ECMA-262 CreatePerIterationEnvironment (invoked from the
forstatement's LabelledEvaluation),letin aforcreates a fresh binding per iteration, and the update expression runs inside that per-iteration environment. We emit a single sharedlocal iand run the update in the outer scope, so closures built in the update clause all capture the same variable. A per-iteration body wrapper isn't enough; the update expression must also run inside the per-iteration scope.