Skip to content

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

@proggeramlug

Description

@proggeramlug

Summary

Function.prototype.call.bind(fn)(receiver, ...args) — the "uncurry-this" idiom —
returns the wrong value ([object Object], i.e. the receiver itself) instead of
invoking fn with that receiver, when the receiver is a builtin prototype
object
such as Object.prototype or Error.prototype. Plain objects,
Array.prototype, and Math work correctly.

This idiom is the backbone of test262's propertyHelper.js
(__hasOwnProperty = Function.prototype.call.bind(Object.prototype.hasOwnProperty)),
so it gates verifyProperty for every test whose subject is Object.prototype /
Error.prototype / other affected prototypes — a large cross-category blocker.

Repro

var bc = Function.prototype.call.bind(Object.prototype.hasOwnProperty);

bc({a:1}, "a");                 // Node: true   Perry: true
bc(Array.prototype, "push");    // Node: true   Perry: true
bc(Math, "abs");                // Node: true   Perry: true
bc(Object.prototype, "toString"); // Node: true   Perry: [object Object]  <-- BUG
bc(Error.prototype, "message");   // Node: true   Perry: [object Object]  <-- BUG

Narrowing — the direct form works; only the .call.bind indirection breaks, and
only for these receivers:

Object.prototype.hasOwnProperty.call(Object.prototype, "toString"); // true (ok)
var bc = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
var r = bc(Object.prototype, "toString");
typeof r;  // Node: "boolean"   Perry: "object"  (r === Object.prototype)

So the bound-call machinery, when the eventual receiver IS a builtin prototype,
returns the receiver instead of the method's result — it appears to confuse the
this/return slot in the Function.prototype.call.bind(method) → invoke path for
that receiver class.

Impact

  • Blocks verifyProperty-based test262 cases on Object.prototype /
    Error.prototype (e.g. all built-ins/Error/prototype/* and
    built-ins/NativeErrors/* descriptor tests — ~57 NativeErrors+Error cases stay
    red even though the underlying getOwnPropertyDescriptor / delete /
    hasOwnProperty operations are all individually correct and Node-identical).
  • Likely affects other categories that subject Object.prototype to verifyProperty.

Note

A companion branch (fix-error-descriptors, unpushed) makes Error instance +
prototype getOwnPropertyDescriptor / getOwnPropertyNames / delete fully
Node-identical, but those gains are unobservable through test262 until this
dispatch bug is fixed. Recommend fixing this first, then that work lands the
Error cluster.


Filed from the parity-fix loop. Root cause localized to the Function.prototype.call.bind(method) invoke path for builtin-prototype receivers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions