Skip to content

[codex] fix uncurried hasOwnProperty on builtin prototypes#4279

Merged
proggeramlug merged 1 commit into
PerryTS:mainfrom
andrewtdiz:codex/node-compat-call-bind-builtin-prototypes
Jun 3, 2026
Merged

[codex] fix uncurried hasOwnProperty on builtin prototypes#4279
proggeramlug merged 1 commit into
PerryTS:mainfrom
andrewtdiz:codex/node-compat-call-bind-builtin-prototypes

Conversation

@andrewtdiz
Copy link
Copy Markdown
Contributor

@andrewtdiz andrewtdiz commented Jun 3, 2026

Summary

  • route Object.prototype.hasOwnProperty thunk calls directly through js_object_has_own
  • add a globals parity fixture for Function.prototype.call.bind(Object.prototype.hasOwnProperty) on builtin prototype receivers

Fixes #4276.

Root Cause

The uncurried Function.prototype.call.bind(Object.prototype.hasOwnProperty) path eventually invokes the installed Object.prototype.hasOwnProperty thunk with IMPLICIT_THIS set to the requested receiver. That thunk re-entered js_native_call_method(this, "hasOwnProperty", ...). For receivers like Object.prototype and Error.prototype, the method tower found the receiver own hasOwnProperty field first and recursed until the depth guard returned an object.

Calling js_object_has_own directly matches the existing HIR rewrite for Object.prototype.hasOwnProperty.call(obj, key) and avoids the recursive method lookup.

Why this cluster

This PR is limited to one receiver dispatch path: Function.prototype.call.bind(method) forwarding the call receiver into an Object.prototype builtin thunk. Error descriptor shape work stays on the separate descriptor-focused branch.

Validation

  • npm exec --yes --package=node@26 -- node --version (v26.3.0)
  • PERRY_NO_AUTO_OPTIMIZE=1 npm exec --yes --package=node@26 -- bash -lc './run_parity_tests.sh --suite node-suite --module globals --filter function-call-bind-builtin-prototypes'
  • PERRY_NO_AUTO_OPTIMIZE=1 npm exec --yes --package=node@26 -- bash -lc './run_parity_tests.sh --suite node-suite --module globals --filter builtin-constructor-own-name-length'
  • PERRY_NO_AUTO_OPTIMIZE=1 npm exec --yes --package=node@26 -- bash -lc './run_parity_tests.sh --suite node-suite --module globals --filter reflective-builtins'
  • cargo check -p perry-runtime
  • cargo fmt --all -- --check
  • git diff --check
  • ./scripts/check_file_size.sh

@proggeramlug proggeramlug marked this pull request as ready for review June 3, 2026 18:47
@proggeramlug proggeramlug merged commit 50c51c9 into PerryTS:main Jun 3, 2026
11 checks passed
proggeramlug added a commit that referenced this pull request Jun 3, 2026
)

#4276 was fixed by #4279 (proto thunks call their ops directly, no
re-dispatch). This adds a wider regression fixture for the uncurry-this
idiom Function.prototype.call.bind(Object.prototype.<method>) on builtin
prototype receivers: also exercises TypeError/RangeError prototypes,
isPrototypeOf, propertyIsEnumerable, typeof-of-result, and the direct
.call form. Verified byte-identical to node --experimental-strip-types
on main.

Co-authored-by: Ralph Küpper <ralph@skelpo.com>
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.

runtime: Function.prototype.call.bind(fn) returns receiver instead of result for builtin-prototype receivers (gates verifyProperty)

2 participants