Throwing when symbol *wrappers* are converted to primitives

# Axel Rauschmayer (10 years ago)

This is current V8 behavior:

> let obj = {};
> obj[Object(Symbol())] = true;

TypeError: Cannot convert object to primitive value

> '' + Object(Symbol())

TypeError: Cannot convert a Symbol wrapper object to a primitive value

Both exceptions make a lot of sense, but I don’t see that in the spec. The way I’d expect it to happen is via Symbol.prototype[@@toPrimitive] – it would always throw. But that’s not the case.

people.mozilla.org/~jorendorff/es6-draft.html#sec-symbol.prototype-@@toprimitive

# Claude Pache (10 years ago)

I guess that V8 follows an old version of the spec draft. That particular behaviour was modified in Rev 28. See ecmascript#3252

# Axel Rauschmayer (10 years ago)

Interesting, thanks! Can you explain the rationale behind that decision? To me, it seems like V8’s behavior is preferable – if I accidentally created instances of Symbol, I would want to get errors as early as possible.

# Gary Guo (10 years ago)

The first one makes no sense to me, since a symbol can be used as a property key. The latter one makes sense but the error should be "Cannot convert a Symbol value to a string".

# Claude Pache (10 years ago)

In fact, that bug was for the particular case of wrapped symbol used as property key. For the more general case of converting a Symbol wrapper object back into a primitive value, I believe that behaviour also changed during the life in the spec draft, but I am too lazy to find when. (Note that the current draft defines Symbol.prototype[@@toPrimitive], and AFAIK, V8 doesn't implement @@toPrimitive yet.)

# Claude Pache (10 years ago)

Here is a more complete answer. In fact, the behaviour should be different in each your two cases. More inline.

Le 27 déc. 2014 à 08:17, Axel Rauschmayer <axel at rauschma.de> a écrit :

This is current V8 behavior:

> let obj = {};
> obj[Object(Symbol())] = true;
TypeError: Cannot convert object to primitive value

That should convert back the wrapper object into the wrapped symbol (using ToPrimitive). The rationale is that you obtained the same behaviour when you used Object("some string") as property key. For how it works technically, see in that order:

> '' + Object(Symbol())
TypeError: Cannot convert a Symbol wrapper object to a primitive value

That should attempt to convert Object(Symbol()) to a string, and that should throw a TypeError. If I recall correctly (and I might not), the order of operations is:

  1. apply ToPrimitive on the second operand, which produces the wrapped symbol;
  2. decide a string is needed, apply ToString() on the symbol produced in step 1, which throws a TypeError.

Anyway, whenever + represents addition of numbers or concatenation of strings, that would throw. See:

people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring

and

people.mozilla.org/~jorendorff/es6-draft.html#sec-tonumber

# Isiah Meadows (10 years ago)

From: Claude Pache <claude.pache at gmail.com>

(Note that the current draft defines Symbol.prototype[@@toPrimitive], and AFAIK, V8 doesn't implement @@toPrimitive yet.)

AFAICT from the GitHub mirror, V8 does not.