fix(deforest): exclude super-using class member bodies from call-site rewrite (#5780 cluster A) - #5788
Conversation
… rewrite (#5780 cluster A) Class methods / constructors / accessors that reference `super` now act as bail-out bodies in the deforest pass. Commit 5d47364 (#5772) extended the DEFOREST phase-3 call-site rewriter to class member bodies to fix the arity-mismatch SIGSEGV (#5136-class). A member body that also uses `super.x`, `super[e]`, or `super(…)` had its [[HomeObject]] setup corrupted by the synthetic-local introduction, causing a `TypeError: Cannot convert undefined or null to object` at runtime (~24 test262 cases, cluster A of #5780). Fix (detect.rs): `body_has_super` walks a member-body statement list for any `Expr::SuperPropertyGet / SuperCall / SuperMethodCall / ObjectSuper*` variant. In the third (unsafe-call-site) detection pass any producer called from a super-using body is added to the `unsupported_call` exclusion set, so the producer is dropped from the candidate map before the rewrite phase begins. Belt-and-suspenders (mod.rs): the phase-3 rewriter skips any class member body for which `body_has_super` returns true, ensuring the [[HomeObject]] frame is never disturbed even if the detect exclusion were somehow bypassed. Super-free class methods continue to be deforested as before (#5772 fix preserved); only bodies that actually use `super` take the bail path — a missed optimisation, not a correctness loss. Tests: two new unit tests in deforest/tests.rs — `rejects_deforest_when_class_method_uses_super` (the regression) and `still_deforests_when_method_has_no_super` (control / #5772 guard).
📝 WalkthroughWalkthroughAdds Deforestation super-body guard
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/perry-transform/src/deforest/tests.rs (2)
494-579: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert the rewritten call-site arity here too.
This control only checks that
helpergained the synthetic param. It would still pass ifrun()rewrote the producer signature but left the class-method call ashelper(), which is the original arity-mismatch regression. Mirror theargs.len() == 1assertion fromdeforests_producer_called_from_class_methodor reuse that helper.🤖 Prompt for 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. In `@crates/perry-transform/src/deforest/tests.rs` around lines 494 - 579, The new control test in still_deforests_when_method_has_no_super only verifies that helper gains the synthetic accumulator parameter, but it does not confirm the call site was rewritten. Update this test to also assert the rewritten Expr::Call inside the class method now has one argument, mirroring deforests_producer_called_from_class_method, so run() cannot regress by changing the producer signature while leaving helper() at the old arity.
400-492: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winBroaden this regression beyond
super.fooon an instance method.The implementation changes also guard constructors, accessors, static methods, and other
superforms, but this test only coversExpr::SuperPropertyGetin one method body. A bug in those newly touched branches would still merge untested.🤖 Prompt for 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. In `@crates/perry-transform/src/deforest/tests.rs` around lines 400 - 492, Broaden the regression in rejects_deforest_when_class_method_uses_super to cover all super-using class contexts, not just Expr::SuperPropertyGet in a single instance method. Add cases for constructors, getters/setters, and static methods (and any other super forms handled by the new logic), then assert detect_producers still excludes the producer and run() leaves the helper signature unchanged for each case. Use the existing make_simple_producer, detect_producers, and run setup to keep the test focused while exercising the newly touched branches.
🤖 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.
Nitpick comments:
In `@crates/perry-transform/src/deforest/tests.rs`:
- Around line 494-579: The new control test in
still_deforests_when_method_has_no_super only verifies that helper gains the
synthetic accumulator parameter, but it does not confirm the call site was
rewritten. Update this test to also assert the rewritten Expr::Call inside the
class method now has one argument, mirroring
deforests_producer_called_from_class_method, so run() cannot regress by changing
the producer signature while leaving helper() at the old arity.
- Around line 400-492: Broaden the regression in
rejects_deforest_when_class_method_uses_super to cover all super-using class
contexts, not just Expr::SuperPropertyGet in a single instance method. Add cases
for constructors, getters/setters, and static methods (and any other super forms
handled by the new logic), then assert detect_producers still excludes the
producer and run() leaves the helper signature unchanged for each case. Use the
existing make_simple_producer, detect_producers, and run setup to keep the test
focused while exercising the newly touched branches.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 70218386-cdc5-4a2b-b59d-7d281b940ac2
📒 Files selected for processing (3)
crates/perry-transform/src/deforest/detect.rscrates/perry-transform/src/deforest/mod.rscrates/perry-transform/src/deforest/tests.rs
Root cause
Commit 5d47364 (#5772) extended the DEFOREST pass to cover class member bodies (constructors, methods, getters, setters, static methods) as valid call-site rewrite targets — fixing the arity-mismatch SIGSEGV where a producer called from a class method had its signature rewritten but the call site was never updated (#5136-class).
A member body that also uses
super(super.x,super[e],super(…)) had its[[HomeObject]]setup corrupted by the synthetic-local introduction done by the call-site rewriter, causing:at runtime for ~24 test262 cases (cluster A of #5780).
Fix
detect.rs —
body_has_super(stmts)walks a member body for anysuperexpression variant (SuperPropertyGet,SuperCall,SuperMethodCall,SuperMethodCallSpread,SuperCallSpread,ObjectSuper*). In the third detection pass (unsafe-call-site scan) any class member body for whichbody_has_superreturnstruehas all its producer calls flagged as unsafe, removing those producers from the candidate set before the rewrite phase. A producer whose only callers are super-using bodies is therefore excluded entirely; one with callers in both super-using and super-free bodies is also excluded (conservative but correct).mod.rs — belt-and-suspenders guard: phase-3 skips
rewrite_call_sites_in_stmtsfor any class member body wherebody_has_superis true, ensuring[[HomeObject]]is never disturbed even if the detect exclusion were somehow bypassed.Before / after
class C extends B { m() { super.x; } }near a deforestablehelper()super.xthrowsTypeErrorclass C { m() { const v = helper(); return v.length; } }(no super)Tests
Two new unit tests in
crates/perry-transform/src/deforest/tests.rs:rejects_deforest_when_class_method_uses_super— producer called from a super-using method is excluded from deforestation; signature unchanged afterrun().still_deforests_when_method_has_no_super— control: same producer called from a super-free method is still deforested (fix(deforest): rewrite producer call sites in class member bodies #5772 guard).All 11 deforest unit tests pass;
cargo fmt --all -- --checkandbash scripts/check_file_size.shclean.Closes #5780 (cluster A —
super.prop/super[expr]/super()in class methods adjacent to deforestable helpers).Generated by Claude Code
Summary by CodeRabbit
super, preventing producer calls in those bodies from being rewritten.super.supercontinue to be optimized as before.