Implementing an identical JSON.stringify
Isiah Meadows
isiahmeadows at gmail.com
Sun Aug 5 03:55:17 UTC 2018
It's very subtle, but no, that's correct per spec, and any engine that
doesn't do that is buggy. When `JSON.stringify` is invoked on a
number, it first performs ToNumber on number objects (which each of
these are) to get the number value, which itself indirectly calls
`valueOf`. The first calls `Number.prototype.valueOf` with a number,
which makes sense. The second creates an object with a [[NumberData]]
internal slot, as expected, but it tries to call
`String.prototype.valueOf` because the prototype of the object is set
to `new.target.prototype === String.prototype` on creation. And by
spec, that throws if the object doesn't have a [[StringData]] slot
(which the `Number` constructor doesn't set, of course).
It's a similar situation with the third, but it's a little more
indirect. First it calls `Object.prototype.valueOf` because
`new.target.prototype === Object.prototype` when constructing the
number. But this returns an object, not a primitive. in the ToNumber
algorithm, if `valueOf` returns a non-primitive, it falls back to
`Object.prototype.toString()`, and in either case, recursively coerces
*that*. The result of coercing that result, `"[object Number]"`, to a
number is `NaN`, and `JSON.stringify(NaN)` returns `null` due to step
9.a/9.b in the SerializeJSONProperty algorithm (`NaN` is not a finite
number).
-----
Isiah Meadows
contact at isiahmeadows.com
www.isiahmeadows.com
On Sat, Aug 4, 2018 at 10:50 PM, Claude Pache <claude.pache at gmail.com> wrote:
>
>
> Le 5 août 2018 à 01:43, Michael Theriot <michael.lee.theriot at gmail.com> a
> écrit :
>
>> Try `Number.prototype.valueOf.call(obj)`: it will throw a TypeError if and
>> only if `obj` has no [[NumberData]] internal slot. Ditto for String, Boolean
>> and Symbol.
>
>
> I already mention this and demonstrate why it is not sufficient in my
> example.
>
> Reiterated plainly:
> ```js
> JSON.stringify(Reflect.construct(Number, [], Number)); // "0"
> JSON.stringify(Reflect.construct(Number, [], String)); // TypeError
> JSON.stringify(Reflect.construct(Number, [], Object)); // null
> ```
>
>
> Per spec, the three expressions should produce `"0"`, as the three objects
> have a [[NumberData]] internal slot (step 4 of [1]). I guess there is some
> discrepancy between implementation and spec for those exotic edge cases?
>
> [1]: https://tc39.github.io/ecma262/#sec-serializejsonproperty
>
> —Claude
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
More information about the es-discuss
mailing list