Michael Theriot (2018-08-04T22:16:10.000Z)
`JSON.stringify` has unintuitive behavior regarding interal slots.

```js
// Number with    [[NumberData]]
// "0"
JSON.stringify(Object(Number(0)));

// Number without [[NumberData]]
// "{}"
JSON.stringify(Reflect.construct(Object, [], Number));

// Number without [[NumberData]]
// Number with    [[StringData]]
// throws TypeError
JSON.stringify(Reflect.construct(String, [], Number));

// String with    [[StringData]]
// ""
JSON.stringify(Object(String()));

// String without [[StringData]]
// "{}"
JSON.stringify(Reflect.construct(Object, [], String));

// String without [[StringData]]
// String with    [[NumberData]]
// throws TypeError
JSON.stringify(Reflect.construct(Number, [], String));

// Object with    [[StringData]]
// "[object String]"
JSON.stringify(Reflect.construct(String, [], Object));

// Object with    [[NumberData]]
// null
JSON.stringify(Reflect.construct(Number, [], Object));
```

Weird, but not impossible to implement.

* You can detect class with instanceof
* You can detect internal slots by try-catching `<class>.prototype.valueOf`

e.g.
```js
const isNumberInstance = (item) => item instanceof Number;
const isStringInstance = (item) => item instanceof String;

const hasNumberData = (item) => {
  try { Number.prototype.valueOf.call(item); } catch { return false; }
  return true;
};
const hasStringData = (item) => {
  try { String.prototype.valueOf.call(item); } catch { return false; }
  return true;
};
```

Since this relies on having a reference to the classes, it will not work
with an instance of `Number` from another realm for example.

```js
const item = Reflect.construct(iframe.contentWindow.String, [],
iframe.contentWindow.Number);

iframe.contentWindow.Number !== Number;
```

I think this is related to `Array.isArray`. Is there an equivalent
`Number.isNumber`? Or is this just something only `JSON.stringify` can do?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180804/e2ac7da6/attachment.html>
michael.lee.theriot at gmail.com (2018-08-04T22:18:51.220Z)
`JSON.stringify` has unintuitive behavior regarding interal slots.

```js
// Number with    [[NumberData]]
// "0"
JSON.stringify(Object(Number(0)));

// Number without [[NumberData]]
// "{}"
JSON.stringify(Reflect.construct(Object, [], Number));

// Number without [[NumberData]]
// Number with    [[StringData]]
// throws TypeError
JSON.stringify(Reflect.construct(String, [], Number));

// String with    [[StringData]]
// ""
JSON.stringify(Object(String()));

// String without [[StringData]]
// "{}"
JSON.stringify(Reflect.construct(Object, [], String));

// String without [[StringData]]
// String with    [[NumberData]]
// throws TypeError
JSON.stringify(Reflect.construct(Number, [], String));

// Object with    [[StringData]]
// "[object String]"
JSON.stringify(Reflect.construct(String, [], Object));

// Object with    [[NumberData]]
// null
JSON.stringify(Reflect.construct(Number, [], Object));
```

Weird, but not impossible to implement.

* You can detect class with instanceof
* You can detect internal slots by try-catching `<class>.prototype.valueOf`

e.g.
```js
const isNumberInstance = (item) => item instanceof Number;

const isStringInstance = (item) => item instanceof String;

const hasNumberData = (item) => {
  try { Number.prototype.valueOf.call(item); } catch { return false; }
  return true;
};
const hasStringData = (item) => {
  try { String.prototype.valueOf.call(item); } catch { return false; }
  return true;
};
```

Since this relies on having a reference to the classes, it will not work
with an instance of `Number` from another realm for example.

```js
const item = Reflect.construct(iframe.contentWindow.String, [], iframe.contentWindow.Number);

iframe.contentWindow.Number !== Number;
```

I think this is related to `Array.isArray`. Is there an equivalent
`Number.isNumber`? Or is this just something only `JSON.stringify` can do?