`ToNumber` and `ToString` invoking `toString`/`valueOf` for number/string objects? (Was: Re: Re: Implementing an identical JSON.stringify)

Isiah Meadows isiahmeadows at gmail.com
Sun Aug 5 05:20:10 UTC 2018

This makes me wonder: for objects with [[NumberData]] and
[[StringData]], why do they call `valueOf`/`toString`/@@toPrimitive to
coerce them instead of simply accessing the boxed data directly? It
seems like a pointless waste to check.


Isiah Meadows
contact at isiahmeadows.com

On Sun, Aug 5, 2018 at 12:30 AM, Michael Theriot
<michael.lee.theriot at gmail.com> wrote:
>> Regarding cases like Reflect.construct(Number, [], String), the reason
>> this throws is because the ToNumber algorithm calls ToPrimitive if its
>> operand is an object. This in turn will call String.prototype.valueOf on the
>> object which does not have [[StringData]]. There’s nothing funny going on,
>> it’s just a weird effect in aggregate. You would just need to implement all
>> the steps here — internal ops like ToNumber, ToPrimitive, etc. It’s not that
>> it "considers type", but rather that these algorithms will call methods by
>> specific names on objects they receive. String.prototype and
>> Object.prototype both implement "valueOf", but only the former will fail the
>> slot check.
> Thanks for demystifying this. I never realized it was just ducktyping
> .valueOf on the object.
> ```js
> Number.prototype.valueOf = () => 0;
> JSON.stringify(1); // 1
> JSON.stringify(new Number(1)); // 0
> ```
> I guess what confused me is that it would detect a [[NumberData]] internal
> slot, but instead of unboxing to that value it tries to ducktype call
> .valueOf on the object. So the presence of [[NumberData]] changes the
> behavior even if it does not actually use this value.
> On Sat, Aug 4, 2018 at 10:14 PM Darien Valentine <valentinium at gmail.com>
> wrote:
>> Is this a question about how/if one could replicate its behavior in theory
>> from ES code, or are you suggesting a change to the existing behavior for
>> these exotic cases?
>> Assuming the former:
>> The relevant steps are
>> [here](https://tc39.github.io/ecma262/#sec-serializejsonproperty). The
>> `instanceof` a value isn’t significant in this algorithm, just its slots (if
>> it is an object) or its primitive type. So one can handle number and string
>> by leveraging branded checks as you’ve shown — nothing more is needed than
>> branded methods and typeof to manage that one.
>> However it is ultimately not possible to replicate because there is no
>> possible brand test for [[BooleanData]].
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

More information about the es-discuss mailing list