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