Implementing an identical JSON.stringify

Isiah Meadows isiahmeadows at
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 ` === 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
` === 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


Isiah Meadows
contact at

On Sat, Aug 4, 2018 at 10:50 PM, Claude Pache <claude.pache at> wrote:
> Le 5 août 2018 à 01:43, Michael Theriot <michael.lee.theriot at> a
> écrit :
>> Try ``: 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]:
> —Claude
> _______________________________________________
> es-discuss mailing list
> es-discuss at

More information about the es-discuss mailing list