Skip to content

compiler: drop with objects at a loop's continue landing - #721

Merged
nooga merged 1 commit into
mainfrom
fix/with-continue-through-finally
Oct 17, 2026
Merged

nooga merged 1 commit into
mainfrom
fix/with-continue-through-finally

Conversation

@nooga

@nooga nooga commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Closes the FIXME left by #719.

Problem: a continue that leaves a with body through a finally keeps the with objects enclosing the try pushed, so the finally body can still see them. Nothing dropped them afterwards, so they stayed in scope for the next iteration. A lookup inside a later with in that iteration then resolved through the leaked object:

var o = { x: "leak" }, x = "out";
for (var i = 0; i < 2; i++) {
  with ({}) seen.push(x);   // second iteration saw "leak"
  with (o) { try { continue; } finally {} }
}

Fix: each loop (while, for, do-while, for-in, for-of) now emits OpTruncateWith at its continue landing, as it already does at its break landing. Normal fall-through reaches the landing with nothing extra pushed, so the truncate is a no-op there. It is only emitted when the loop body contains a with.

Testing

  • New smoke test tests/scripts/with_continue_through_finally.ts. TestScripts is green.
  • A probe covering all five loop kinds leaked on main and passes with this change.
  • test262 (language + built-ins, vs main): no change. No test262 test covers this case.

🤖 Generated with Claude Code

A continue that leaves a with body through a finally keeps the with
objects enclosing the try pushed, so the finally body still sees them.
Nothing dropped them afterwards: the continue completion resumed at the
loop's continue target with those objects still pushed. The next
iteration's lookups inside a with then resolved through them.

Each loop now truncates the frame's with objects to the loop's own depth
at its continue landing, as it already did at its break landing. Normal
fall-through reaches the landing with nothing extra pushed, so the
truncate is a no-op there. It is only emitted when the loop body contains
a with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nooga
nooga merged commit de9ce96 into main Oct 17, 2026
8 checks passed
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