A fun little spec deviation in the major JS engines

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

A fun little spec deviation in the major JS engines

Jeff Walden-6
At least, if you consider |with| and |eval| fun (and who doesn't?):

   js> var x = "outer"; function f() { with({ x: 17 }) eval("var x"); return x; } typeof f()
   "undefined"

This seems to be the behavior in every engine out there.  But according to the last ES5 errata for 10.5, and in the latest ES6 draft, since "x" has a binding in the object environment record created when executing the |with| statement's substatement, and the object supplied to the |with| isn't the global object, the |var x| should do nothing whatsoever.  Presumably given this implementation unanimity the spec should change on this point.

In a certain sense this was flagged in <https://mail.mozilla.org/pipermail/es5-discuss/2011-January/003882.html> in acknowledging the current language to be narrowly scoped to the exact problem at hand.  I'm just pointing it out so it gets addressed in the likely future changes that happen to 10.5.

Jeff
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A fun little spec deviation in the major JS engines

Felix-54
On Sat, Jan 28, 2012 at 7:13 PM, Jeff Walden <[hidden email]> wrote:

> At least, if you consider |with| and |eval| fun (and who doesn't?):
>
>  js> var x = "outer"; function f() { with({ x: 17 }) eval("var x"); return
> x; } typeof f()
>  "undefined"
>
> This seems to be the behavior in every engine out there.  But according to
> the last ES5 errata for 10.5, and in the latest ES6 draft, since "x" has a
> binding in the object environment record created when executing the |with|
> statement's substatement, and the object supplied to the |with| isn't the
> global object, the |var x| should do nothing whatsoever.  Presumably given
> this implementation unanimity the spec should change on this point.

It seems to me the behavior you observe conforms to spec.

12.10, the with statement changes the Lexical Environment, but not the
Variable Environment.

10.4.2, the eval is a direct eval, and it's not strict, so the Lexical
Environment for the eval comes from the with, but the Variable
Environment for the eval comes from the f function scope.

10.5 and 12.2, the var in the eval adds a binding for x in the current
Variable Environment, which is the f function scope, but an assignment
to x in the eval would modify the x in the Lexical Environment, which
is the x established by the 'with'.  12.2 has a sentence noting this
irregularity.

since the x created in f's Variable Environment by the eval is never
assigned any value, the result returned from f is undefined.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A fun little spec deviation in the major JS engines

Jeff Walden-6
On 01/28/2012 08:20 PM, felix wrote:
> It seems to me the behavior you observe conforms to spec.

Hmm, yes, on second look I think you're right.  I guess I was reading overfast and missed the variable environment/lexical environment distinction there.  That, or it's been too long since I looked at this stuff.  Probably both.

Jeff
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: A fun little spec deviation in the major JS engines

Andreas Rossberg-4
In reply to this post by Jeff Walden-6
On 29 January 2012 04:13, Jeff Walden <[hidden email]> wrote:
> At least, if you consider |with| and |eval| fun (and who doesn't?):
>
>  js> var x = "outer"; function f() { with({ x: 17 }) eval("var x"); return
> x; } typeof f()
>  "undefined"

This is really just an instance of JavaScript's, er, creative rules
for var-hoisting. You need neither `eval' nor `with' to witness them,
the same happens with

var x = "outer"; function f() { with({ x: 17 }) { var x } return x; } typeof f()

or

var x = "outer"; function f() { try { throw 17 } catch(x) { var x }
return x; } typeof f()

That's why you will want to use `let' in the future. :)

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss