Skip to content

fix(#774): resolve super.<prop> value form via parent vtable lookup - #780

Merged
proggeramlug merged 1 commit into
mainfrom
fix/774-super-property-override
May 15, 2026
Merged

fix(#774): resolve super.<prop> value form via parent vtable lookup#780
proggeramlug merged 1 commit into
mainfrom
fix/774-super-property-override

Conversation

@TheHypnoo

Copy link
Copy Markdown
Member

Summary

Closes #774. Value-form super.<prop> was lowered to this.<prop> in PR #754 (crates/perry-hir/src/lower/expr_misc.rs::lower_super_prop), so a child override silently shadowed the parent. Strict JS resolves the read through the parent's prototype.

What changed

  • HIR: new Expr::SuperPropertyGet { property } variant. Ident-form super.foo lowers to it; computed super[expr] keeps its this[expr] fallback (out of scope here).
  • Codegen (Expr::SuperPropertyGet in crates/perry-codegen/src/expr.rs): walks the parent class chain in ctx.classes / ctx.methods. When a parent declares a method <prop>, materializes it as a closure value via js_closure_alloc_singleton (mirroring Expr::FuncRef); otherwise returns undefined.
  • Method closure wrappers: emits __perry_wrap_<method> for every class instance method in compile_module, alongside the existing hir.functions wrapper loop. Forwards to perry_method_<…>(this_box, args) with this=undefined, matching strict-JS plain-invocation semantics for const fn = super.greet; fn(arg).

Call-form super.method(args) continues to route through Expr::SuperMethodCall unchanged — the rxjs / NestJS canaries from PR #754 are unaffected.

Validation

  • node --experimental-strip-types test-files/test_super_property_override.tsundefined
  • ./target/release/perry test-files/test_super_property_override.ts -o /tmp/t && /tmp/tundefined
  • ./run_parity_tests.sh --filter test_decorators — all NestJS decorator canaries from PR Add legacy TypeScript decorator metadata support #754 PASS (test_decorators_nest_js_common_canary is a pre-existing compile failure unrelated to this PR).
  • ./run_parity_tests.sh --filter test_super / --filter test_inherit — all PASS.
  • cargo fmt --check

Test plan

  • CI parity job green.
  • CI cargo-test green.

Value-form `super.<prop>` was lowered to `this.<prop>` in PR #754
(crates/perry-hir/src/lower/expr_misc.rs::lower_super_prop), so a
child override silently shadowed the parent. Strict JS resolves the
read through the parent's prototype.

- Adds `Expr::SuperPropertyGet { property }` HIR variant; ident-form
  `super.foo` now lowers to it. Computed form `super[expr]` keeps the
  existing `this[expr]` fallback (out of scope; tracked as follow-up).
- Codegen walks the parent class chain in `ctx.classes` / `ctx.methods`.
  When a parent declares a method named `<prop>`, materializes it as
  a closure value via `js_closure_alloc_singleton` mirroring
  `Expr::FuncRef`; otherwise returns `undefined`.
- Emits closure-call wrappers for class instance methods alongside the
  existing `hir.functions` wrapper loop in `compile_module`, so the
  singleton allocator has a `__perry_wrap_<method>` to bind. Wrappers
  forward to `perry_method_<...>(this_box, args)` with `this=undefined`,
  matching strict-JS plain-invocation semantics for `const fn =
  super.greet; fn(arg)`.

Call-form `super.method(args)` continues to route through
`Expr::SuperMethodCall` unchanged, so the rxjs / NestJS canaries from
PR #754 are unaffected.

Adds `test-files/test_super_property_override.ts` as a parity test
pinning the new behavior (expected: `undefined`).
@proggeramlug
proggeramlug merged commit 84cb6d7 into main May 15, 2026
9 checks passed
@proggeramlug
proggeramlug deleted the fix/774-super-property-override branch May 15, 2026 01:53
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.

super.<prop> value-form lowering silently returns child override instead of parent

2 participants