Skip to content

fix(globals): complete Node parity#6853

Open
TheHypnoo wants to merge 3 commits into
mainfrom
fix/node-globals-parity
Open

fix(globals): complete Node parity#6853
TheHypnoo wants to merge 3 commits into
mainfrom
fix/node-globals-parity

Conversation

@TheHypnoo

@TheHypnoo TheHypnoo commented Jul 26, 2026

Copy link
Copy Markdown
Member

Summary

Complete Node 26.5.0 parity for node:globals.

Changes

  • Match EventTarget, navigator, Promise, package scope, and node:path behavior.
  • Route dynamic Proxy stores through [[Set]] and restore runtime handles when exceptions unwind.
  • Run failed import-free globals scripts as temporary CommonJS .cts files for both Node and Perry.

Related issue

Closes #6780

Test plan

  • ./run_parity_tests.sh --suite node-suite --module globals
    • 122 PASS, 0 FAIL, 0 COMPILE_FAIL, 0 CRASH, 0 NODE_FAIL, 0 SKIP
  • cargo test -p perry-runtime js_throw_path_restores_runtime_handles_across_unwound_frames --lib
  • cargo test -p perry-codegen path_slash_submodules_install_the_path_dispatch_bucket --lib
  • bash -n run_parity_tests.sh
  • shellcheck run_parity_tests.sh (not installed locally)

Checklist

  • I have NOT bumped the workspace version or edited CLAUDE.md / CHANGELOG.md (maintainer handles these at merge)
  • My commits follow the loose feat: / fix: / docs: / chore: prefix convention used in the log
  • I've read CONTRIBUTING.md and agree to the Code of Conduct

Summary by CodeRabbit

  • Bug Fixes
    • Fixed module resolution so the nearest package.json scope governs ESM vs CommonJS.
    • Improved proxy-backed property writes and index setting to follow correct [[Set]] semantics.
    • Corrected Promise.prototype.then errors for null/undefined receivers and aligned the non-callable then message.
    • Preserved GC runtime-handle stack state during exception unwinding.
    • Added support for additional node:path submodule variants and ensured EventTarget.length resolves to 0.
  • Improvements
    • navigator.language/navigator.languages now reflect system locale settings when available.
    • Enhanced Node globals parity tests by retrying certain CommonJS fixtures.

@TheHypnoo TheHypnoo added the bug Confirmed defect or regression label Jul 26, 2026
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0bbdb193-f16d-4cd5-a87a-6655f6ea88aa

📥 Commits

Reviewing files that changed from the base of the PR and between d698514 and 816f6e4.

📒 Files selected for processing (8)
  • crates/perry-codegen/src/nm_install.rs
  • crates/perry-hir/src/analysis/builtins.rs
  • crates/perry-parser/src/lib.rs
  • crates/perry-runtime/src/exception.rs
  • crates/perry-runtime/src/intl.rs
  • crates/perry-runtime/src/navigator.rs
  • crates/perry-runtime/src/promise/then.rs
  • crates/perry-runtime/src/value/dyn_index.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • crates/perry-parser/src/lib.rs
  • crates/perry-runtime/src/value/dyn_index.rs
  • crates/perry-runtime/src/promise/then.rs
  • crates/perry-runtime/src/navigator.rs
  • crates/perry-hir/src/analysis/builtins.rs
  • crates/perry-runtime/src/exception.rs

📝 Walkthrough

Walkthrough

The changes update runtime exception handle restoration, proxy and Promise behavior, navigator locale reporting, constructor metadata, package resolution, native-module dispatch, and parity test retries for CommonJS-compatible globals tests.

Changes

Runtime behavior

Layer / File(s) Summary
Exception runtime-handle restoration
crates/perry-runtime/src/exception.rs, crates/perry-runtime/src/gc/roots.rs, crates/perry-runtime/src/gc/roots/runtime_handles.rs
Exception unwinding records and restores runtime-handle stack depth alongside shadow-stack state, with regression coverage.
Runtime compatibility semantics
crates/perry-runtime/src/navigator.rs, crates/perry-runtime/src/intl.rs, crates/perry-runtime/src/object/global_this_tables.rs, crates/perry-runtime/src/object/polymorphic_index.rs, crates/perry-runtime/src/value/dyn_index.rs, crates/perry-runtime/src/promise/then.rs
Navigator locales use environment variables; EventTarget has zero constructor arity; proxy writes use proxy dispatch; and Promise receiver errors handle null, undefined, and non-callable then values.

Parity harness

Layer / File(s) Summary
CommonJS retry flow
run_parity_tests.sh, changelog.d/6853-node-globals-parity.md
Import-free TypeScript globals tests can be retried through temporary .cts files, with Perry compiling the same selected file; the changelog records the parity result.

Compiler and module resolution

Layer / File(s) Summary
Module and package resolution
crates/perry-codegen/src/nm_install.rs, crates/perry-parser/src/lib.rs
Slash-form path native modules map to the path install bucket, and the nearest package.json determines ESM context.
EventTarget constructor metadata
crates/perry-hir/src/analysis/builtins.rs
HIR constructor-length analysis reports EventTarget as having zero declared parameters and tests the mapping.

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

Suggested labels: parity

Suggested reviewers: proggeramlug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: completing Node parity for globals.
Description check ✅ Passed The description follows the template with summary, changes, related issue, test plan, and checklist.
Linked Issues check ✅ Passed The changes address the listed node:globals failures for node:path, EventTarget, reviver proxies, Promise behavior, and package scope.
Out of Scope Changes check ✅ Passed All changes stay within node:globals parity work and related test/runtime support; no clearly unrelated code paths were introduced.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/node-globals-parity

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/perry-runtime/src/value/dyn_index.rs (1)

388-399: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Dispatch Proxies before the Symbol fast path.

For proxy[symbol] = value, js_dyn_index_set currently calls js_object_set_symbol_property and returns before js_proxy_set runs, bypassing the Proxy set trap for Symbol keys. Check js_proxy_is_proxy(obj) first, mirroring the proxy fast-path behavior used elsewhere.

🤖 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-runtime/src/value/dyn_index.rs` around lines 388 - 399, Move the
js_proxy_is_proxy check in js_dyn_index_set before the Symbol-key branch, so
proxy targets—including proxy[symbol] assignments—always dispatch through
js_proxy_set before any direct property fast path. Preserve the existing direct
js_object_set_symbol_property behavior for non-proxy objects.
🧹 Nitpick comments (1)
crates/perry-parser/src/lib.rs (1)

563-566: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a regression test for nearest-package precedence.

This correctly prevents a nested { "type": "commonjs" } package from falling through to an ancestor ESM package. Add a fixture covering that hierarchy so this compatibility behavior remains protected.

🤖 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-parser/src/lib.rs` around lines 563 - 566, Add a regression
fixture and test for the package-resolution logic around
package_json_declares_esm_context, covering an ancestor package declaring ESM
and a nearer nested package declaring CommonJS. Assert that the nearest package
takes precedence and the nested file is treated as CommonJS.
🤖 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 `@crates/perry-runtime/src/exception.rs`:
- Around line 505-520: The regression test’s NaN-box pattern is being
numerically converted instead of preserving its bit representation. Update the
`_orphaned` initialization in
`js_throw_path_restores_runtime_handles_across_unwound_frames` to construct the
value with `f64::from_bits(...)`; keep the existing tagged payload unchanged.

In `@crates/perry-runtime/src/navigator.rs`:
- Around line 60-68: Update navigator_language to strip POSIX locale modifiers
such as “@...” before converting underscores to hyphens, and validate the
resulting value as a language tag rather than relying only on contains('-').
Preserve the existing LC_ALL/LANG fallback order and en-US default while
rejecting malformed locale values.

---

Outside diff comments:
In `@crates/perry-runtime/src/value/dyn_index.rs`:
- Around line 388-399: Move the js_proxy_is_proxy check in js_dyn_index_set
before the Symbol-key branch, so proxy targets—including proxy[symbol]
assignments—always dispatch through js_proxy_set before any direct property fast
path. Preserve the existing direct js_object_set_symbol_property behavior for
non-proxy objects.

---

Nitpick comments:
In `@crates/perry-parser/src/lib.rs`:
- Around line 563-566: Add a regression fixture and test for the
package-resolution logic around package_json_declares_esm_context, covering an
ancestor package declaring ESM and a nearer nested package declaring CommonJS.
Assert that the nearest package takes precedence and the nested file is treated
as CommonJS.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aec0e5c8-07bc-42d4-bbbe-1a021155af69

📥 Commits

Reviewing files that changed from the base of the PR and between 6899e75 and bdb4ed5.

📒 Files selected for processing (12)
  • crates/perry-codegen/src/nm_install.rs
  • crates/perry-hir/src/analysis/builtins.rs
  • crates/perry-parser/src/lib.rs
  • crates/perry-runtime/src/exception.rs
  • crates/perry-runtime/src/gc/roots.rs
  • crates/perry-runtime/src/gc/roots/runtime_handles.rs
  • crates/perry-runtime/src/navigator.rs
  • crates/perry-runtime/src/object/global_this_tables.rs
  • crates/perry-runtime/src/object/polymorphic_index.rs
  • crates/perry-runtime/src/promise/then.rs
  • crates/perry-runtime/src/value/dyn_index.rs
  • run_parity_tests.sh

Comment thread crates/perry-runtime/src/exception.rs
Comment thread crates/perry-runtime/src/navigator.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Confirmed defect or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[parity] node:globals — 5 failing node-suite tests (2026-07-22 baseline)

1 participant