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