Fix for-loop update closure environments#676
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughRestructures lexical ChangesFor-Loop Update-Phase Scoping
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Suite TimingTest Runner (interpreted: 9,744 passed; bytecode: 9,744 passed)
MemoryGC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.
Benchmarks (interpreted: 407; bytecode: 407)
MemoryGC rows aggregate the main thread plus all worker thread-local GCs. Benchmark runner performs explicit between-file collections, so collection and collected-object counts can be much higher than the test runner.
Measured on ubuntu-latest x64. |
Benchmark Results407 benchmarks Interpreted: 🟢 21 improved · 🔴 331 regressed · 55 unchanged · avg -5.6% arraybuffer.js — Interp: 🟢 1, 🔴 12, 1 unch. · avg -7.3% · Bytecode: 🟢 2, 12 unch. · avg +1.2%
arrays.js — Interp: 🔴 16, 3 unch. · avg -6.1% · Bytecode: 🟢 3, 🔴 7, 9 unch. · avg -2.4%
async-await.js — Interp: 🔴 3, 3 unch. · avg -6.4% · Bytecode: 6 unch. · avg -0.9%
async-generators.js — Interp: 🔴 2 · avg -9.6% · Bytecode: 2 unch. · avg -0.9%
base64.js — Interp: 🟢 6, 🔴 3, 1 unch. · avg +1.3% · Bytecode: 🔴 3, 7 unch. · avg -0.8%
classes.js — Interp: 🔴 29, 2 unch. · avg -6.0% · Bytecode: 🟢 1, 🔴 3, 27 unch. · avg -1.7%
closures.js — Interp: 🔴 11 · avg -9.2% · Bytecode: 🔴 1, 10 unch. · avg -1.7%
collections.js — Interp: 🔴 11, 1 unch. · avg -8.4% · Bytecode: 🔴 2, 10 unch. · avg -0.9%
csv.js — Interp: 🔴 13 · avg -8.8% · Bytecode: 13 unch. · avg +0.0%
destructuring.js — Interp: 🔴 22 · avg -5.9% · Bytecode: 🔴 1, 21 unch. · avg +0.2%
fibonacci.js — Interp: 🔴 8 · avg -8.0% · Bytecode: 8 unch. · avg +1.2%
float16array.js — Interp: 🔴 27, 5 unch. · avg -6.1% · Bytecode: 🟢 2, 🔴 15, 15 unch. · avg -4.2%
for-of.js — Interp: 🔴 6, 1 unch. · avg -4.4% · Bytecode: 🔴 1, 6 unch. · avg -2.4%
generators.js — Interp: 🔴 4 · avg -8.2% · Bytecode: 🔴 2, 2 unch. · avg -2.8%
iterators.js — Interp: 🔴 31, 11 unch. · avg -4.8% · Bytecode: 🟢 3, 🔴 12, 27 unch. · avg -2.1%
json.js — Interp: 🔴 20 · avg -10.0% · Bytecode: 🔴 5, 15 unch. · avg -2.4%
jsx.jsx — Interp: 🔴 21 · avg -6.2% · Bytecode: 🔴 6, 15 unch. · avg -2.6%
modules.js — Interp: 🔴 5, 4 unch. · avg -3.7% · Bytecode: 9 unch. · avg +1.3%
numbers.js — Interp: 🔴 9, 2 unch. · avg -6.6% · Bytecode: 🔴 4, 7 unch. · avg -2.1%
objects.js — Interp: 🔴 7 · avg -6.4% · Bytecode: 🔴 3, 4 unch. · avg -1.6%
promises.js — Interp: 🔴 6, 6 unch. · avg -2.8% · Bytecode: 🟢 1, 🔴 3, 8 unch. · avg -0.8%
regexp.js — Interp: 🟢 6, 🔴 3, 2 unch. · avg +3.1% · Bytecode: 🟢 2, 9 unch. · avg +3.2%
strings.js — Interp: 🔴 19 · avg -10.3% · Bytecode: 🟢 3, 🔴 2, 14 unch. · avg +0.2%
tsv.js — Interp: 🔴 5, 4 unch. · avg -5.2% · Bytecode: 🔴 2, 7 unch. · avg -2.1%
typed-arrays.js — Interp: 🟢 4, 🔴 16, 2 unch. · avg -5.5% · Bytecode: 🟢 5, 🔴 6, 11 unch. · avg +9.4%
uint8array-encoding.js — Interp: 🟢 1, 🔴 13, 4 unch. · avg -7.0% · Bytecode: 🔴 14, 4 unch. · avg -26.9%
weak-collections.js — Interp: 🟢 3, 🔴 9, 3 unch. · avg +6.2% · Bytecode: 🟢 9, 6 unch. · avg +38.8%
Deterministic profile diffclasses
Measured on ubuntu-latest x64. Benchmark ranges compare cached main-branch min/max ops/sec with the PR run; overlapping ranges are treated as unchanged noise. Percentage deltas are secondary context. |
test262 Conformance
Areas closest to 100%
Per-test deltas (+3 / -0)Newly passing (3):
Steady-state failures are non-blocking; regressions vs the cached main baseline (lower total pass count, or any PASS → non-PASS transition) fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@source/units/Goccia.Compiler.Statements.pas`:
- Around line 2557-2563: The synthetic per-iteration locals created in the loop
(PerIterNames -> BodySlots and later UpdateSlots) only copy register values but
not the original binding metadata, so type hints, strict flags and annotations
are lost; after each ACtx.Scope.DeclareLocal(Name, PerIterIsConst) call in the
PerIterNames loop (and the analogous loop at the 2592–2598 region), copy/clone
the source binding's metadata (type hint, strictness flag, annotation metadata)
from the original binding (the corresponding OuterSlots entry / source binding
object) onto the newly returned local slot (BodySlots[I] and UpdateSlots[I]) so
the synthetic locals carry the same metadata for proper typing and strict
enforcement. Ensure you do this immediately after DeclareLocal(...) for both
BodySlots and UpdateSlots.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fbf8af15-6660-4601-b34f-91c56c0b4937
📒 Files selected for processing (4)
source/units/Goccia.Compiler.Statements.passource/units/Goccia.Evaluator.passource/units/Goccia.Generator.Continuation.pastests/language/for-loop/let-per-iteration.js
- Preserve strict type metadata on synthetic for-loop per-iteration locals.\n- Close anonymous class-expression super upvalues before freeing their register.\n- Add regression coverage for strict for-loop metadata and class-expression super construction.\n\nFixes #678.
Summary
forloops in interpreter and bytecode mode.continue, and test-expression captures.Testing
./build/GocciaTestRunner tests --asi --unsafe-ffi --no-progress./build/GocciaTestRunner tests --asi --unsafe-ffi --mode=bytecode --no-progress./build/GocciaTestRunner tests/language/for-loop/let-per-iteration.js --asi --unsafe-ffi --mode=bytecode./build/GocciaTestRunner tests/language/for-loop --asi --unsafe-ffi./build/GocciaTestRunner tests/language/for-loop --asi --unsafe-ffi --mode=bytecode./build/GocciaTestRunner tests/language/for-loop-var --asi --unsafe-ffi./build/GocciaTestRunner tests/language/for-loop-var --asi --unsafe-ffi --mode=bytecodeAdditional checks:
./format.pas --check./build.pas clean testrunner./build.pas bundlerprintf '%s\n' 'const fns = []; for (let i = 0; i < 3; i++, fns.push(() => i)) {} fns.map(fn => fn());' | ./build/GocciaBundler --compat-traditional-for-loop --output=/tmp/issue539-update-closures.gbc