Jeremy Martin (2014-02-14T19:38:10.000Z)
On further reflection, #3 does feel like trying to rewrite the past.  For
better or worse, non-strict mode allows declarations to persist past the
eval().  And while strict mode provides a license-to-kill on behavior like
that, I don't really see strong justification for that kind of surprise
factor for let in non-strict mode.

If you're not using strict mode AND you're using eval(), the damage is
arguably already done (or at least the danger already exists).  Changing
the behavior of let in this case feels like removing an arbitrary* foot-gun
when we're already in the armory, so to speak.

* Granted it's not completely arbitrary, since `let` is new whereas `var`
is not, but hopefully you get my point...


On Fri, Feb 14, 2014 at 2:23 PM, Erik Arvidsson <erik.arvidsson at gmail.com>wrote:

> 1 or 3. We have already shot down similiar situations to 2 before. I don't
> think it is worth bringing this up again.
>
> 1 is the least surprise. It is just bad practice, but so is eval and non
> strict mode in the first place.
>
> 3 is fine if you think as if there was a block around the whole thing
> (except for functions in block in non strict mode).
>
> On Fri Feb 14 2014 at 1:42:13 PM, Jeremy Martin <jmar777 at gmail.com> wrote:
>
>> > As far as I can see, your #4 and my #1 are exactly the same.  How do
>> you think they differ?
>>
>> Actually, on a second read, I don't think they are.  I was perhaps more
>> explicit regarding strict mode, but I think the behavior there was already
>> clear enough to everyone. :)
>>
>>
>> On Fri, Feb 14, 2014 at 12:14 PM, Allen Wirfs-Brock <
>> allen at wirfs-brock.com> wrote:
>>
>> 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 <
>> allen at 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 at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>>
>> --
>> Jeremy Martin
>> 661.312.3853
>> http://devsmash.com
>> @jmar777
>>
>>
>>
>>
>>
>> --
>> Jeremy Martin
>> 661.312.3853
>> http://devsmash.com
>> @jmar777
>>
>


-- 
Jeremy Martin
661.312.3853
http://devsmash.com
@jmar777
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/a86c7d0f/attachment-0001.html>
domenic at domenicdenicola.com (2014-02-20T01:19:00.961Z)
On further reflection, #3 does feel like trying to rewrite the past.  For
better or worse, non-strict mode allows declarations to persist past the
eval().  And while strict mode provides a license-to-kill on behavior like
that, I don't really see strong justification for that kind of surprise
factor for let in non-strict mode.

If you're not using strict mode AND you're using eval(), the damage is
arguably already done (or at least the danger already exists).  Changing
the behavior of let in this case feels like removing an arbitrary* foot-gun
when we're already in the armory, so to speak.

\* Granted it's not completely arbitrary, since `let` is new whereas `var`
is not, but hopefully you get my point...