Forged well-known symbols

# Jordan Harband (10 years ago)

Should a JS engine retain a reference to the original value of well-known symbols (like Symbol.iterator), or should steps that use well-known-Symbol-valued properties (like for..of iteration) always do a dynamic lookup on that value?

jsfiddle.net/hzzo10dm/2 is a proof of concept that demonstrates in Chrome 40 that by replacing Symbol.iterator with another symbol, I can create some weird behavior.

What is specified to happen to built-in and custom iterables if I do Symbol.iterator = Symbol()?

What I would expect is that either:

  • the original value of Symbol.iterator would forever be the only value in a realm that could be used to provide an iterator
  • or, that whatever the current value of Symbol.iterator, at that moment that would be the only way to retrieve an iterator on an object, thus overwriting Symbol.iterator should break all iteration.
# Claude Pache (10 years ago)

I've looked at your fiddle. The following assignment in line 5:

Symbol.iterator = Symbol('Symbol.iterator')

should fail (silently if you are not in strict mode), because the "iterator" property of the Symbol object is not writable.

Therefore, in the rest of the fiddle, Symbol.iterator should refer to the original @@iterator symbol, not to the replaced one. (Your fiddle is a good illustration of why one should always run code in strict mode.)

But to answer to the specific question: the spec always uses the original @@iterator symbol, not the current value of Symbol.iterator.

# Jordan Harband (10 years ago)

Ah, good catch :-) it's late. With strict mode on, it definitely fails, and since the property descriptor is nonconfigurable and nonwritable, this is a non-issue.

Don't mind me, I'll just go sit in the corner.

# Andreas Rossberg (10 years ago)

On 6 February 2015 at 10:19, Jordan Harband <ljharb at gmail.com> wrote:

Should a JS engine retain a reference to the original value of well-known symbols (like Symbol.iterator), or should steps that use well-known-Symbol-valued properties (like for..of iteration) always do a dynamic lookup on that value?

The language never looks up any intrinsics dynamically. Given JavaScript's unreliable library semantics, that would break left and right.

jsfiddle.net/hzzo10dm/2 is a proof of concept that demonstrates in Chrome 40 that by replacing Symbol.iterator with another symbol, I can create some weird behavior.

What is specified to happen to built-in and custom iterables if I do Symbol.iterator = Symbol()?

This is not having the effect you think it does:

d8> var s = Symbol.iterator

undefined d8> Symbol.iterator = Symbol("bla")

Symbol(bla) d8> s === Symbol.iterator

true

It's just sloppy mode semantics not complaining. What you can do, however, is:

d8> Symbol = {iterator: Symbol("bla")} {iterator: Symbol(bla)} d8> s === Symbol.iterator

false

But that's just general JavaScript craziness. Fortunately, it still does not change the actual iterator symbol.