Skip to content

Call namespace class statics through values when no native entry matches - #12022

Merged
proggeramlug merged 1 commit into
mainfrom
fix/namespace-class-statics
Oct 5, 2026
Merged

proggeramlug merged 1 commit into
mainfrom
fix/namespace-class-statics

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem: ns.URL.canParse, ns.KeyObject.from, and ns.Stream.getMaxListeners can build an undispatched native class call and return undefined despite an existing function on the exported constructor.

Cause and fix: retain native entries with either a matching class filter or a module-wide filter; otherwise use ordinary member access and call lowering. Preserve main's existing value routes, HTTP Server.call, spread behavior and the unknown-export gate. This keeps inherited events/cluster direct getMaxListeners calls at 10. Runtime static values missing on main are documented in a follow-up list of statics perry lacks for separate fixes.

Tests: seven HIR units, the focused built-in and user-module gaps, existing builtin-values/native function-method gaps, 29 module probes plus compatibility probes, and five source sabotage checks.

Gap fixture main vs Node head vs Node
test_gap_namespace_class_statics FAIL PASS
test_gap_namespace_class_statics_user PASS PASS
test_gap_builtin_values PASS PASS
test_gap_11268_native_module_function_methods PASS PASS

Results: all 14 programs match Node 26.5.1. CPU/RSS medians of five; instructions minimum of three; exact executable bytes.

Program Instructions min main/head Delta CPU median main/head (s) Peak RSS median main/head (KiB) Binary main/head (B)
nbody-ts 13,547,578,392/13,547,562,987 -0.0001% 1.40/1.41 28,884/28,872 13,959,184/13,959,184
nbody-js 53,052,693,926/53,052,700,705 +0.0000% 4.93/4.82 28,900/28,876 14,007,568/14,007,568
spectral-ts 19,815,149,101/19,815,149,895 +0.0000% 1.76/1.75 16,160/16,108 13,746,000/13,746,000
spectral-js 35,650,876,086/35,650,873,625 -0.0000% 3.35/3.36 15,720/16,032 13,746,000/13,746,000
fannkuch-ts 78,835,225,843/78,835,280,994 +0.0001% 8.78/8.87 18,188/18,164 13,758,208/13,758,208
fannkuch-js 78,835,219,240/78,835,225,448 +0.0000% 8.47/8.81 18,208/17,840 13,758,208/13,758,208
bintrees-ts 26,785,210,271/26,785,246,496 +0.0001% 3.57/3.53 204,208/205,144 13,762,384/13,762,384
bintrees-js 35,203,270,665/35,203,258,712 -0.0000% 4.23/4.18 205,516/205,424 13,758,288/13,758,288
strs-ts 10,057,494,227/10,057,488,603 -0.0001% 1.17/1.19 39,472/39,176 13,803,408/13,803,408
strs-js 28,406,897,015/28,406,921,531 +0.0001% 3.33/3.18 39,712/39,600 13,803,408/13,803,408
hello-ts 1,218,467/1,219,132 +0.0546% 0.00/0.00 15,620/15,712 13,709,056/13,709,056
hello-js 1,216,490/1,218,819 +0.1915% 0.00/0.00 15,748/15,644 13,709,056/13,709,056
tsc 10,282,948,657/10,282,909,973 -0.0004% 2.05/1.99 221,308/228,936 138,775,928/138,775,928
zod 816,406,399/816,383,844 -0.0028% 0.15/0.15 56,752/56,468 17,877,456/17,877,456

Gates: fmt and full HIR tests pass; all six per-arm GC root-dominance audits pass. Full lint remains red with identical main/head failure names and no head-only red. See report.md for the baseline proof, full probe table, controls, tz2 results and sabotage table.

The required initial table contains CPU/RSS/instruction increases, so targeted controls were run rather than declaring it regression-free. Fannkuch JS CPU moves from 8.47/8.81s (+4.01%) to 8.77/8.84s (+0.80%) on the pinned control, with overlapping ranges. Tsc RSS reverses from 221,308/228,936 KiB (+3.45%) to 219,376/219,140 KiB, with overlapping control ranges. Strings JS initially has a small instruction increase with disjoint ranges; a second control remains slightly positive, then six further pinned pairs have five negative deltas and one positive delta, with overlapping pooled ranges. The two strings JS .text sections have identical SHA-256 0760949b581838d4e028934e34b84971a5d082c5f37bdaaa46ecba56b77a8e15. The controls do not reproduce an increase beyond observed variability. All 14 sizes are exactly equal. No demonstrated regression beyond noise remains on these requested programs; the initial results and every control are retained, not replaced or waived.

Risks: this change fixes namespace routing where an actual static value exists; it does not guarantee every built-in static exists. Existing absent methods/getters and unrelated static behavior remain separate. A demonstrated performance or main-to-head Node-parity regression is a blocker.

Base: 4c87719
Head: 1c5e85d39f71960323a5bbf0559433d1443a6cad

Summary by CodeRabbit

  • Bug Fixes
    • Fixed static method calls on Node.js classes accessed through namespaces, including URL.canParse, KeyObject.from, and inherited listener-limit methods.
    • Improved handling of static properties, getters, extracted methods, computed access, and spread arguments so these calls behave more consistently.
    • Corrected static method and property behavior for exported classes, including inherited classes, aliases, and default exports.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aa42542a-a815-45c5-91bf-6e494fb3d630
📥 Commits

Reviewing files that changed from the base of the PR and between 5074b5b and b8eaef7.

📒 Files selected for processing (7)
  • changelog.d/nsstatics-namespace-class-statics.md
  • crates/perry-hir/src/lower/expr_call/mod.rs
  • crates/perry-hir/src/lower/expr_call/module_class_static.rs
  • crates/perry-hir/src/lower/expr_call/module_class_static_tests.rs
  • test-files/nsstatics/classes.ts
  • test-files/test_gap_namespace_class_statics.ts
  • test-files/test_gap_namespace_class_statics_user.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Native-module class static call lowering now checks module exports and manifest entries before emitting native dispatch. Compiler tests and runtime test files cover Node namespace statics and user-defined class statics.

Changes

Namespace Class Static Calls

Layer / File(s) Summary
Native-module static lowering
crates/perry-hir/src/lower/expr_call/module_class_static.rs, changelog.d/nsstatics-namespace-class-statics.md
Native class-call lowering now requires identifier properties and compatible manifest entries. Value exports, subnamespaces, spreads, and unmatched methods can use ordinary lowering. HTTP and HTTPS server-call handling remains. The changelog records the changed dispatch cases.
Compiler lowering regression tests
crates/perry-hir/src/lower/expr_call/mod.rs, crates/perry-hir/src/lower/expr_call/module_class_static_tests.rs
HIR tests cover native dispatch, namespace value access, getters, spreads, computed members, ethers statics, server calls, missing exports, and named-import member chains.
Namespace static runtime coverage
test-files/nsstatics/classes.ts, test-files/test_gap_namespace_class_statics.ts, test-files/test_gap_namespace_class_statics_user.ts
Runtime cases cover Node namespace static calls and user-defined class statics, including extracted and bound methods, getters, inheritance, spread arguments, and reassignment.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to b8eae

The namespace static-call change is mergeable after normal checks; no concrete regression remains identified.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to b8eae

The change restores calls to existing exported functions while retaining unsupported-export checks. The reviewed call paths do not grant new privileges or expose capabilities beyond call forms already available.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected exposure is source code compiled into calls on existing native-module exports. An attacker able to supply that source already had literal-computed or value-based call forms that avoided the base recognizer. Restoring identifier-shaped calls does not establish an additional independently attackable authority scope.

Trust Boundaries and Controls

  • observed — Unknown namespace exports still reach refusal or deferred runtime-error handling. Ordinary member lowering retains its availability checks and configurable nonliteral stdlib-dispatch guard. That guard is policy-dependent and must not be treated as universally enabled sandboxing.
  • observed — The HTTP(S) Server.call path retains its existing instance argument, argument shaping, and construction externs. Although moved before the export check, Server remains declared in both unchanged manifests, so this ordering change does not bypass that check for an otherwise unknown export.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes routing namespace class static calls through exported values when no native entry matches.
Description check ✅ Passed The description explains the problem, cause, fix, risks, and detailed verification results. It omits the template’s Related issue and Checklist sections, but the substantive summary, changes, and test…
Full details: Docstring Coverage

Explanation

Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@proggeramlug
proggeramlug force-pushed the fix/namespace-class-statics branch from b8eaef7 to 8713d6e Compare October 5, 2026 12:08
@proggeramlug
proggeramlug merged commit 23e3d00 into main Oct 5, 2026
23 of 25 checks passed
@proggeramlug
proggeramlug deleted the fix/namespace-class-statics branch October 5, 2026 12:10
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