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 [email protected] www.isiahmeadows.com On Sat, Aug 4, 2018 at 10:50 PM, Claude Pache <[email protected]> wrote: > > > Le 5 août 2018 à 01:43, Michael Theriot <[email protected]> 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 > [email protected] > https://mail.mozilla.org/listinfo/es-discuss > _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

