As far as I can see, your #4 and my #1 are exactly the same.  How do you think 
they differ?

Allen

On Feb 14, 2014, at 8:03 AM, Jeremy Martin wrote:

> I rather hate to say it, but I would've actually expected:
> 
> 4) Given that the eval'd string doesn't create anything typically considered 
> a "block", the let binding would survive past the completion of the eval in 
> non-strict mode:
> 
>     (function() {     
>           eval("
>               var answer=42;
>               let localToEval = true;
>            ");
>           console.log(answer);  // 42
>           console.log(localToEval);  // true
>     )();
> 
>     (function() {
>           "use strict";
>           eval("
>               var answer=42;
>               let localToEval = true;
>            ");
>           console.log(answer);  // ReferenceError: answer is not defined
>           console.log(localToEval);  // ReferenceError: localToEval is not 
> defined
>     )();
> 
> I'm not necessarily arguing for that behavior, but weighing in since that's 
> the behavior I would have expected based on existing ES5 
> strict/non-strict/eval and ES6 let semantics...
> 
> 
> On Fri, Feb 14, 2014 at 10:40 AM, Allen Wirfs-Brock <al...@wirfs-brock.com> 
> wrote:
> 
> On Feb 14, 2014, at 5:49 AM, André Bargull wrote:
>>> How about this? 
>>> 
>>> let x= 0;
>>> if (1) eval("let x= 42; alert(x);"); //Is this in its own block?
>>> alert(x);
>> 
>> `eval()` hasn't yet been updated to work with the new lexical declaration 
>> forms, but I hope the example from above will be evaluated in a new block. 
>> See https://bugs.ecmascript.org/show_bug.cgi?id=1788 for a related bug 
>> report.
> 
> Goood point and this is something I need to specify in the next couple weeks 
> so let's look at the alternatives.
> 
> First a quick refresher on ES5 era eval.
> 
> In ES5, the binding behavior of direct eval differs between strict and 
> non-strict modes.
> 
> In strict mode, each eval instantiates all declarations in a new environment 
> that is immediately nested within the current LexicalEnvironment. The scoping 
> behavior is essentially the same as if the eval code was the body of an iife 
> that occurred at the same place as the eval call.  Bindings introduced by the 
> eval code disappear after completion of the eval.
> 
> In non-strict mode, each eval instantiates all declarations in the current 
> VariableEnvironment; that is the most immediately enclosing function or 
> global environment.  Bindings introduced by the eval code remain accessible 
> from that VariableEnvironment after completion of the eval.
> 
> For example:
> (function() {
>       "use strict";
>       eval("var answer=42");
>       console.log(answer);  // ReferenceError: answer is not defined
> })();
> 
> (function() {     
>       eval("var answer=42");
>       console.log(answer);  // 42
> })();
> 
> For ES6, it makes sense for strict mode evals to behave in this exact same 
> way. Each eval takes place in its own environment and no bindings survive the 
> completion of the eval.
> 
> For ES6, non-strict evals of code containing only var or function 
> declarations must  have exactly the ES5 behavior  in order to maintain 
> compatibility.  But what about eval code that contains new declaration forms 
> (let/const/class) exclusively or in combination with var/function 
> declarations? Three possibilities come to mind:
> 
> 1) Extend the ES5 semantics to include the new declaration forms.  For 
> example:
> 
> (function() {     
>       eval("let answer=42");
>       console.log(answer);  // 42
> })();
> 
> 2) Use the strict mode binding semantics  if the eval code directly contains 
> any of the new declaration forms:
> 
> (function() {     
>       eval("
>           var answer=42;
>           let forceSeprateEnvironment = true;
>        ");
>       console.log(answer);  // ReferenceError: answer is not defined
> })();
> 
> 3) Combination.  use ES5 non-strict binding semantics for var/function 
> declarations but place let/const/class bindings into a per eval environment:
> 
> (function() {     
>       eval("
>           var answer=42;
>           let localToEval = true;
>        ");
>       console.log(answer);  // 42
>       console.log(localToEval);  // ReferenceError: localToEval is not defined
> )();
> 
> 
> It would certainly be possible to specify #1, but I don't like it. Other than 
> for the global environment it would be cleaner if the new block scope-able 
> declarations  were never dynamically added to the environment.
> 
> I think either #2 or #3 is plausible.  #2 is a simpler story but introduces a 
> refactoring hazard. If you have some existing eval code that  defines some 
> "global" functions or variables, then simply adding a let/const/class 
> declaration to the eval code ruins those global declarations. 
> 
> I prefer the simplicity of #2, but I also worry about the WTF impact it might 
> have on evolving existing code.
> 
> Can we get away with #2, or are we going to have to go with #3?  Are there 
> other alternatives?
> 
> Allen
> 
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> 
> 
> -- 
> Jeremy Martin
> 661.312.3853
> http://devsmash.com
> @jmar777

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to