On Fri, Feb 14, 2014 at 8:26 AM, John Barton <johnjbar...@google.com> wrote:

> How about "Keyword 'let' not allowed without 'use strict' or in a module".
> ?
>


I wish. I argued strongly that sloppy mode be maintained only to continue
to serve the purpose of being an ES3 compatibility mode, and that we stop
adding new ES6 language features to it. In particular, that we not add
"let" since we could not even specify that "let" be *simply* a declaration
keyword in sloppy mode. Instead, TC39 decided that "let" in sloppy mode is
sometimes a variable, and sometimes indicates a "let" declaration. This is
long decided and TC39 is not going to revisit the admission of "let" into
sloppy mode.

For this and many other reasons, new code should consider sloppy mode to be
WTF toxic waste, to be avoided under all normal circumstances.
Nevertheless, we still need to settle outstanding questions as
non-toxically as possible, given the toxic waste we've already dumped into
sloppy mode. Hence this thread.



>
>
> On Fri, Feb 14, 2014 at 8:18 AM, Mark S. Miller <erig...@google.com>wrote:
>
>> I agree that this is in some sense the least surprising. But it is so
>> unpleasant that I think we should instead opt for the additional surprise
>> of #3 -- that a direct sloppy eval is block-like, even though there aren't
>> any curlies.
>>
>>
>> On Fri, Feb 14, 2014 at 8:03 AM, Jeremy Martin <jmar...@gmail.com> 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
>>>
>>>
>>
>>
>> --
>>     Cheers,
>>     --MarkM
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>


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

Reply via email to