Skip to content

Decline for-loop environment reuse when a pattern default embeds a closure#2739

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/for-loop-pattern-capture
Jul 22, 2026
Merged

Decline for-loop environment reuse when a pattern default embeds a closure#2739
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/for-loop-pattern-capture

Conversation

@lahma

@lahma lahma commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Pre-release review find in the same eligibility-scan family as #2709. ForLoopMayCapture scanned the init declarators' initializers (plus test/update/body) for capturing closures, but never the declarator binding patterns themselves. A destructuring default embeds an expression the scan missed:

const fns = [];
for (let i = 0, { f = () => i } = {}; i < 3; i++) { fns.push(f); }
fns[0]();  // V8/spec: 0 — Jint before this fix: 3

With the closure invisible to the scan, the loop reused/pooled its per-iteration environment in place, so the escaped closure observed the final i — and with environment pooling, re-entering the loop could reset the binding the closure captured. The fix runs the existing escape visitor over non-identifier declarator ids; the gate only declines an optimization, so generic per-iteration semantics take over.

Repro verified against V8 before/after. Full suite plus Test262 green.

🤖 Generated with Claude Code

https://claude.ai/code/session_0115tQFNyyQqc1HQGPLUgZND

…osure

ForLoopMayCapture scanned init declarator initializers, test, update and
body for capturing closures, but never the declarator binding patterns
themselves — a destructuring default like

    for (let i = 0, { f = () => i } = {}; i < 3; i++) { fns.push(f); }

embeds a closure the scan missed, so the per-iteration environment was
reused/pooled in place and the escaped closure observed the final value
of i (3) instead of the captured iteration's (0, matching V8), or a
reset binding after the loop re-entered.

Same eligibility-scan family as the for-header TDZ fix (sebastienros#2709); the
gate only declines an optimization, generic per-iteration semantics
take over.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115tQFNyyQqc1HQGPLUgZND
@lahma
lahma merged commit 26e9408 into sebastienros:main Jul 22, 2026
4 checks passed
@lahma
lahma deleted the fix/for-loop-pattern-capture branch July 22, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant