Skip to content

runtime: Number/Boolean/Symbol/BigInt prototype methods don't brand-check this (reflective call returns [object Object] instead of TypeError) (#3662) #4100

@proggeramlug

Description

@proggeramlug

Part of the #3662 cluster (builtins must throw the spec error on an incompatible this).

The primitive-wrapper prototype methods do not perform the spec this brand
check when invoked reflectively on an incompatible receiver. Instead the call
falls back to Object.prototype and returns "[object Object]" rather than
throwing a TypeError.

Affected (each should throw TypeError on a non-matching receiver):

  • Number.prototype.valueOf, Number.prototype.toLocaleString
  • Boolean.prototype.toString, Boolean.prototype.valueOf
  • Symbol.prototype.toString, Symbol.prototype.valueOf
  • BigInt.prototype.toString, BigInt.prototype.valueOf

(Number.prototype.toFixed/toString/toExponential/toPrecision already throw via
the computed-key dispatch.)

Repro

Number.prototype.valueOf.call({});      // Perry: "[object Object]"  Node: TypeError
Boolean.prototype.toString.call({});    // Perry: "[object Object]"  Node: TypeError
Symbol.prototype.toString.call({});     // Perry: "[object Object]"  Node: TypeError
BigInt.prototype.valueOf.call({});      // Perry: "[object Object]"  Node: TypeError

Related wrong-value bug

Even on a valid receiver, the reflective toString returns the wrong value
(the generic Object.prototype.toString is used):

Symbol.prototype.toString.call(Symbol("x")); // Perry: "[object Symbol]"  Node: "Symbol(x)"
BigInt.prototype.toString.call(5n, 2);       // Perry: "[object BigInt]"  Node: "101"

Suggested fix

Install dedicated brand-checking thunks on Number/Boolean/Symbol/BigInt
.prototype (mirror object/collection_proto_thunks.rs): read IMPLICIT_THIS,
verify it is the matching primitive (or its boxed wrapper), throw TypeError
otherwise, and re-dispatch to the existing per-type logic via
js_native_call_method — which also fixes the wrong-value reflective toString.

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