Skip to content

runtime: Function.prototype.call.bind(method) (uncurry-this) returns undefined — gates test262 verifyProperty harness #3716

Description

@proggeramlug

Summary

Function.prototype.call.bind(someMethod) — the "uncurry-this" idiom —
returns a function that ignores its bound this and yields undefined when
called. This happens even for plain objects, so it's not a builtin-descriptor
issue.

const hop = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
hop({a:1}, "a");        // Perry: undefined   | Node: true

const slice = Function.prototype.call.bind(Array.prototype.slice);
slice([1,2,3], 1);      // Perry: undefined   | Node: [2,3]

Diagnostics:

const call = Function.prototype.call;
typeof call            // "function"  ✓
typeof call.bind       // Perry: undefined  | Node: "function"   ✗ (reading .bind as a value)
const b = call.bind(x) // typeof b === "function" (the .bind(...) call form is special-cased)
b(obj, "a")            // undefined  ✗ — the bound `this` (the target method) is never applied

So Function.prototype.call is reified as a callable, but:

  1. reading .bind as a value off it returns undefined, and
  2. the special-cased call.bind(target) produces a bound function that does
    not invoke target with the forwarded (thisArg, ...args).

Why it's high-leverage

This is the exact shape test262's harness/propertyHelper.js uses:

var __hasOwnProperty   = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
var __getOwnPropertyDescriptor = ...;
var __join = Function.prototype.call.bind(Array.prototype.join);

verifyProperty (and verifyCallableProperty, verifyAccessorProperty)
call __hasOwnProperty(obj, name) as their first assertion, so every
verifyProperty-based positive test262 case fails here before checking
anything else — independent of whether the underlying descriptor is correct.
Fixing this unblocks the entire propertyHelper.js-based slice of the suite
at once (the ~131 "name/length should be an own property" cluster from #3655
and many more).

Repro

const hop = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
console.log(hop({a: 1}, "a"));   // expected: true

Notes

  • The direct forms already work after runtime: complete own name/length descriptors on builtins (follow-on to closed #3143) #3655's constructor PR:
    Object.prototype.hasOwnProperty.call(obj, k) and obj.hasOwnProperty(k)
    are correct. Only the Function.prototype.call.bind(method) re-curry is broken.
  • User-function .bind works (f.bind({v:10})(5) is correct); the gap is
    specifically binding the reified Function.prototype.call / .apply
    native methods and reading .bind/.call/.apply off them as values.

Found while implementing #3655 (built-in name/length descriptors).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions