Which engine is right about with statement and Symbol.unscopables?

Boris Zbarsky bzbarsky at mit.edu
Mon Feb 20 16:00:22 UTC 2017


On 2/20/17 10:00 AM, Michał Wadas wrote:
> http://stackoverflow.com/questions/40595389/why-does-browser-get-symbol-unscopables-twice
>
> Which implementation is bugged? Can someone familiar specification
> details fill bug in proper engine?
>
>
>   var a, b, flag = true
>
>   with (a = { x: 7 })
>     with (b = { x: 4, get [Symbol.unscopables]() { return { x: flag=!flag } } })
>       x++
>
>                    // Chrome   FF
>   console.log(a)   // {x:5}    {x:7}
>   console.log(b)   // {x:4}    {x:8}

TL;DR: both are buggy.  The correct output is {x:7}, {x:5}.  I have 
filed https://bugzilla.mozilla.org/show_bug.cgi?id=1341061 and 
https://bugs.chromium.org/p/v8/issues/detail?id=5992

I think we come into 
https://tc39.github.io/ecma262/#sec-postfix-increment-operator-runtime-semantics-evaluation 
here.  The first question is what "lhs" ends up being.

I'm pretty sure that evaluating "x" will call 
https://tc39.github.io/ecma262/#sec-getidentifierreference which will 
start with envRc being the object Environment Record created by the 
"with (b)" and start looking for the binding for "x".  Specifically, it 
will call HasBinding() on envRec, which will call 
https://tc39.github.io/ecma262/#sec-object-environment-records-hasbinding-n 
which will check @@unscopables.  It will get x: false, I think (assuming 
that none of the bareword lookups used in defining "b" end up looking up 
things in the "with (b)" environment.  So we will get back a Reference 
whose base is the object Environment Record for "with (b)".  This claim 
could use double-checking.

Anyway, if that's correct, then 
https://tc39.github.io/ecma262/#sec-postfix-increment-operator-runtime-semantics-evaluation 
step 2 does https://tc39.github.io/ecma262/#sec-getvalue which in step 
6a goes to 
https://tc39.github.io/ecma262/#sec-object-environment-records-getbindingvalue-n-s 
which will return the value "4" afaict, without ever checking @@unscopables.

And then 
https://tc39.github.io/ecma262/#sec-postfix-increment-operator-runtime-semantics-evaluation 
step 4 will call https://tc39.github.io/ecma262/#sec-putvalue which in 
step 7a will call 
https://tc39.github.io/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s 
which will set b.x to 5.

So as far as I can tell from the spec, the output should be: {x:7}, 
{x:5}, and there should be one single call to the getter.  And both of 
the browsers tested are buggy.

In Safari, for what it's worth, I get the output I expect: {x:7}, {x:5}.

-Boris


More information about the es-discuss mailing list