eval of let, etc. Was: Re: restrictions on let declarations
I rather hate to say it, but I would've actually expected:
-
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...
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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/ad672ba8/attachment-0001.html>
I actually prefer #3. Given only knowledge of ES5 and of the rest of ES6, I find it least surprising. "var"s hoist out of blocks. In non-strict code, "function"s leak out of blocks in ways that are hard to explain. I can understand non-strict direct eval as being block-like, in that "var" and "function" leak out of them, but all the reliably block-local declarations stay within the direct eval.
Also, I buy the refactoring issue. It's like the problem with micro-modes: bizarre and unexpected non-local influences.
On Fri, Feb 14, 2014 at 7:40 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: [...] > > 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? > I actually prefer #3. Given only knowledge of ES5 and of the rest of ES6, I find it least surprising. "var"s hoist out of blocks. In non-strict code, "function"s leak out of blocks in ways that are hard to explain. I can understand non-strict direct eval as being block-like, in that "var" and "function" leak out of them, but all the reliably block-local declarations stay within the direct eval. Also, I buy the refactoring issue. It's like the problem with micro-modes: bizarre and unexpected non-local influences. -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/caa69bde/attachment.html>
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.
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 <jmar777 at 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 <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 > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/1d754e3b/attachment-0001.html>
How about "Keyword 'let' not allowed without 'use strict' or in a module". ?
How about "Keyword 'let' not allowed without 'use strict' or in a module". ? On Fri, Feb 14, 2014 at 8:18 AM, Mark S. Miller <erights at 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 <jmar777 at 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 < >> 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 >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > > -- > Cheers, > --MarkM > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/d8f7c5ab/attachment.html>
Mark S. Miller wrote:
I actually prefer #3. Given only knowledge of ES5 and of the rest of ES6, I find it least surprising. "var"s hoist out of blocks. In non-strict code, "function"s leak out of blocks in ways that are hard to explain. I can understand non-strict direct eval as being block-like, in that "var" and "function" leak out of them, but all the reliably block-local declarations stay within the direct eval.
Also, I buy the refactoring issue. It's like the problem with micro-modes: bizarre and unexpected non-local influences.
Yes, agree on #3 being best. My recollection from past TC39 meetings and discussion here is that #2 will not fly. We do not want some let buried in a large string to eval to contaminate the whole eval'ed program such that vars in it are confined, where they weren't before.
Just amplifying your refactoring point, but also noting your micro-mode/non-local comment. This is not going to win consensus.
Mark S. Miller wrote: > I actually prefer #3. Given only knowledge of ES5 and of the rest of > ES6, I find it least surprising. "var"s hoist out of blocks. In > non-strict code, "function"s leak out of blocks in ways that are hard > to explain. I can understand non-strict direct eval as being > block-like, in that "var" and "function" leak out of them, but all the > reliably block-local declarations stay within the direct eval. > > Also, I buy the refactoring issue. It's like the problem with > micro-modes: bizarre and unexpected non-local influences. Yes, agree on #3 being best. My recollection from past TC39 meetings and discussion here is that #2 will not fly. We do not want some let buried in a large string to eval to contaminate the whole eval'ed program such that vars in it are confined, where they weren't before. Just amplifying your refactoring point, but also noting your micro-mode/non-local comment. This is not going to win consensus. /be
On Fri, Feb 14, 2014 at 8:26 AM, John Barton <johnjbarton at 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:26 AM, John Barton <johnjbarton at 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 <erights at 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 <jmar777 at 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 < >>> 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 >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> >> >> -- >> Cheers, >> --MarkM >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/d203c8e3/attachment-0001.html>
As far as I can see, your #4 and my #1 are exactly the same. How do you think they differ?
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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/c566f21a/attachment.html>
On Feb 14, 2014, at 8:54 AM, Brendan Eich wrote:
Just amplifying your refactoring point, but also noting your micro-mode/non-local comment. This is not going to win consensus.
the various forms of eval are already micro-mode, so I'm not sure if those points are very relevant.
But, I agree that #3 is a better fit to sloppy mode (ie less surprising) than #2 and avoid more refactoring hazards.
Unless, I see the see the tide turning in some other direction #3 is what I'll put into the spec.
On Feb 14, 2014, at 8:54 AM, Brendan Eich wrote: > Mark S. Miller wrote: >> I actually prefer #3. Given only knowledge of ES5 and of the rest of ES6, I find it least surprising. "var"s hoist out of blocks. In non-strict code, "function"s leak out of blocks in ways that are hard to explain. I can understand non-strict direct eval as being block-like, in that "var" and "function" leak out of them, but all the reliably block-local declarations stay within the direct eval. >> >> Also, I buy the refactoring issue. It's like the problem with micro-modes: bizarre and unexpected non-local influences. > > Yes, agree on #3 being best. My recollection from past TC39 meetings and discussion here is that #2 will not fly. We do not want some let buried in a large string to eval to contaminate the whole eval'ed program such that vars in it are confined, where they weren't before. > > Just amplifying your refactoring point, but also noting your micro-mode/non-local comment. This is not going to win consensus. the various forms of eval are already micro-mode, so I'm not sure if those points are very relevant. But, I agree that #3 is a better fit to sloppy mode (ie less surprising) than #2 and avoid more refactoring hazards. Unless, I see the see the tide turning in some other direction #3 is what I'll put into the spec. Allen
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. :)
> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/222f568b/attachment-0001.html>
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).
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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140214/96ff04c0/attachment.html>
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 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>
Another consideration in the back of my mind is that there may be useful to implementors to knowing that let/const/class declaration are never dynamically added to a non-global environment.
On Feb 14, 2014, at 11:38 AM, Jeremy Martin wrote: > 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. Another consideration in the back of my mind is that there may be useful to implementors to knowing that let/const/class declaration are never dynamically added to a non-global environment. Allen
Allen Wirfs-Brock wrote:
the various forms of eval are already micro-mode, so I'm not sure if those points are very relevant.
No, the various forms of eval do not have non-local effects of the kind your #2 did!
Allen Wirfs-Brock wrote: > the various forms of eval are already micro-mode, so I'm not sure if those points are very relevant. No, the various forms of eval do not have non-local effects of the kind your #2 did! /be
Allen Wirfs-Brock wrote:
Another consideration in the back of my mind is that there may be useful to implementors to knowing that let/const/class declaration are never dynamically added to a non-global environment.
+lots, this should be front of mind.
In a block, we want the bindings local to that block to be statically analyzable. We want no non-local mode effects. So, #3 still wins.
Allen Wirfs-Brock wrote: > On Feb 14, 2014, at 11:38 AM, Jeremy Martin wrote: > >> > 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. > > Another consideration in the back of my mind is that there may be useful to implementors to knowing that let/const/class declaration are never dynamically added to a non-global environment. +lots, this should be front of mind. In a block, we want the bindings local to that block to be statically analyzable. We want no non-local mode effects. So, #3 still wins. /be
Strongly seconded.
On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: > Allen Wirfs-Brock wrote: >> >> On Feb 14, 2014, at 11:38 AM, Jeremy Martin wrote: >> >>> > 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. >> >> >> Another consideration in the back of my mind is that there may be useful >> to implementors to knowing that let/const/class declaration are never >> dynamically added to a non-global environment. > > +lots, this should be front of mind. > > In a block, we want the bindings local to that block to be statically > analyzable. We want no non-local mode effects. So, #3 still wins. Strongly seconded. /Andreas
And even thirded.
On 17/02/2014, at 13:42, Andreas Rossberg wrote: > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >> Allen Wirfs-Brock wrote: >>> >>> Another consideration in the back of my mind is that there may be useful >>> to implementors to knowing that let/const/class declaration are never >>> dynamically added to a non-global environment. >> >> +lots, this should be front of mind. >> >> In a block, we want the bindings local to that block to be statically >> analyzable. We want no non-local mode effects. So, #3 still wins. > > Strongly seconded. And even thirded. -- ( Jorge )();
Happy to concede to #3 on my end. Just wanted to be clear that it seems to be optimizing for future happiness vs. least surprising behavior (which isn't a bad thing).
Happy to concede to #3 on my end. Just wanted to be clear that it seems to be optimizing for future happiness vs. least surprising behavior (which isn't a bad thing). On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com>wrote: > On 17/02/2014, at 13:42, Andreas Rossberg wrote: > > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: > >> Allen Wirfs-Brock wrote: > >>> > >>> Another consideration in the back of my mind is that there may be > useful > >>> to implementors to knowing that let/const/class declaration are never > >>> dynamically added to a non-global environment. > >> > >> +lots, this should be front of mind. > >> > >> In a block, we want the bindings local to that block to be statically > >> analyzable. We want no non-local mode effects. So, #3 still wins. > > > > Strongly seconded. > > And even thirded. > > -- > ( Jorge )(); > _______________________________________________ > 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/d459eaee/attachment.html>
I'm also fine with 3.
I'm also fine with 3. On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> wrote: > Happy to concede to #3 on my end. Just wanted to be clear that it seems > to be optimizing for future happiness vs. least surprising behavior (which > isn't a bad thing). > > > On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com>wrote: > > On 17/02/2014, at 13:42, Andreas Rossberg wrote: > > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: > >> Allen Wirfs-Brock wrote: > >>> > >>> Another consideration in the back of my mind is that there may be > useful > >>> to implementors to knowing that let/const/class declaration are never > >>> dynamically added to a non-global environment. > >> > >> +lots, this should be front of mind. > >> > >> In a block, we want the bindings local to that block to be statically > >> analyzable. We want no non-local mode effects. So, #3 still wins. > > > > Strongly seconded. > > And even thirded. > > -- > ( Jorge )(); > > _______________________________________________ > 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 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/d61dd3d8/attachment.html>
So, #3 appears to be the winner.
Given that, can we also agree that this is throws (or at least that the delete does nothing):
eval ("let x=5; delete x;");
(bug ecmascript#1111 )
So, #3 appears to be the winner. Given that, can we also agree that this is throws (or at least that the delete does nothing): eval ("let x=5; delete x;"); (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) Allen On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: > I'm also fine with 3. > > On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> wrote: > Happy to concede to #3 on my end. Just wanted to be clear that it seems to be optimizing for future happiness vs. least surprising behavior (which isn't a bad thing). > > > On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com> wrote: > On 17/02/2014, at 13:42, Andreas Rossberg wrote: > > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: > >> Allen Wirfs-Brock wrote: > >>> > >>> Another consideration in the back of my mind is that there may be useful > >>> to implementors to knowing that let/const/class declaration are never > >>> dynamically added to a non-global environment. > >> > >> +lots, this should be front of mind. > >> > >> In a block, we want the bindings local to that block to be statically > >> analyzable. We want no non-local mode effects. So, #3 still wins. > > > > Strongly seconded. > > And even thirded. > > -- > ( Jorge )(); > _______________________________________________ > 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 > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/617172ae/attachment.html>
In this context, there are two things you might mean by "throws": a) That this delete is an early error within the evaled program, and therefore throws before any of the code in the evaled program executes. b) That the delete is a dynamic error that happens when the delete executes, and therefore that the evaled code prior to the delete has executed before the error is thrown.
-1 on #b.
Assuming you mean #a, between #a and silence, I'm torn. Here are pros and cons: pro #a: The program is wrong. Silence fails to bring it to anyone's attention, making the mistake less likely to be fixed. And making it more likely the program's execution deviates from author's intent. con #a: Silence on sloppy wrong programs are least surprise, and is arguably the most vivid different between sloppy and strict.
I doubt there's any sensible choices other than #a and silence.
In this context, there are two things you might mean by "throws": a) That this delete is an early error within the evaled program, and therefore throws before any of the code in the evaled program executes. b) That the delete is a dynamic error that happens when the delete executes, and therefore that the evaled code prior to the delete has executed before the error is thrown. -1 on #b. Assuming you mean #a, between #a and silence, I'm torn. Here are pros and cons: pro #a: The program is wrong. Silence fails to bring it to anyone's attention, making the mistake less likely to be fixed. And making it more likely the program's execution deviates from author's intent. con #a: Silence on sloppy wrong programs are least surprise, and is arguably the most vivid different between sloppy and strict. I doubt there's any sensible choices other than #a and silence. On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: > So, #3 appears to be the winner. > > Given that, can we also agree that this is throws (or at least that the > delete does nothing): > > eval ("let x=5; delete x;"); > > (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) > > Allen > > > > On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: > > I'm also fine with 3. > > On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> > wrote: > >> Happy to concede to #3 on my end. Just wanted to be clear that it seems >> to be optimizing for future happiness vs. least surprising behavior (which >> isn't a bad thing). >> >> >> On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com >> > wrote: >> >> On 17/02/2014, at 13:42, Andreas Rossberg wrote: >> > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >> >> Allen Wirfs-Brock wrote: >> >>> >> >>> Another consideration in the back of my mind is that there may be >> useful >> >>> to implementors to knowing that let/const/class declaration are never >> >>> dynamically added to a non-global environment. >> >> >> >> +lots, this should be front of mind. >> >> >> >> In a block, we want the bindings local to that block to be statically >> >> analyzable. We want no non-local mode effects. So, #3 still wins. >> > >> > Strongly seconded. >> >> And even thirded. >> >> -- >> ( Jorge )(); >> >> _______________________________________________ >> 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 >> >> _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/49996841/attachment.html>
See people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation
A better statement of the question would be can we agree that lexical bindings created by eval are always non-deletable binding. Where or not is throws which the various modes is already determined by the existing spec. for delete based upon whether or not the binding is deletable.
See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation A better statement of the question would be can we agree that lexical bindings created by eval are always non-deletable binding. Where or not is throws which the various modes is already determined by the existing spec. for delete based upon whether or not the binding is deletable. Allen On Feb 17, 2014, at 1:16 PM, Mark S. Miller wrote: > In this context, there are two things you might mean by "throws": > a) That this delete is an early error within the evaled program, and therefore throws before any of the code in the evaled program executes. > b) That the delete is a dynamic error that happens when the delete executes, and therefore that the evaled code prior to the delete has executed before the error is thrown. > > -1 on #b. > > Assuming you mean #a, between #a and silence, I'm torn. Here are pros and cons: > pro #a: The program is wrong. Silence fails to bring it to anyone's attention, making the mistake less likely to be fixed. And making it more likely the program's execution deviates from author's intent. > con #a: Silence on sloppy wrong programs are least surprise, and is arguably the most vivid different between sloppy and strict. > > I doubt there's any sensible choices other than #a and silence. > > > > On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: > So, #3 appears to be the winner. > > Given that, can we also agree that this is throws (or at least that the delete does nothing): > > eval ("let x=5; delete x;"); > > (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) > > Allen > > > > On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: > >> I'm also fine with 3. >> >> On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> wrote: >> Happy to concede to #3 on my end. Just wanted to be clear that it seems to be optimizing for future happiness vs. least surprising behavior (which isn't a bad thing). >> >> >> On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com> wrote: >> On 17/02/2014, at 13:42, Andreas Rossberg wrote: >> > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >> >> Allen Wirfs-Brock wrote: >> >>> >> >>> Another consideration in the back of my mind is that there may be useful >> >>> to implementors to knowing that let/const/class declaration are never >> >>> dynamically added to a non-global environment. >> >> >> >> +lots, this should be front of mind. >> >> >> >> In a block, we want the bindings local to that block to be statically >> >> analyzable. We want no non-local mode effects. So, #3 still wins. >> > >> > Strongly seconded. >> >> And even thirded. >> >> -- >> ( Jorge )(); >> _______________________________________________ >> 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 >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > > > > -- > Cheers, > --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/c5adc14f/attachment-0001.html>
+1.
+1. On Mon, Feb 17, 2014 at 2:06 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: > See > http://people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation > > > A better statement of the question would be can we agree that lexical > bindings created by eval are always non-deletable binding. Where or not is > throws which the various modes is already determined by the existing spec. > for delete based upon whether or not the binding is deletable. > > Allen > > > > > On Feb 17, 2014, at 1:16 PM, Mark S. Miller wrote: > > In this context, there are two things you might mean by "throws": > a) That this delete is an early error within the evaled program, and > therefore throws before any of the code in the evaled program executes. > b) That the delete is a dynamic error that happens when the delete > executes, and therefore that the evaled code prior to the delete has > executed before the error is thrown. > > -1 on #b. > > Assuming you mean #a, between #a and silence, I'm torn. Here are pros and > cons: > pro #a: The program is wrong. Silence fails to bring it to anyone's > attention, making the mistake less likely to be fixed. And making it more > likely the program's execution deviates from author's intent. > con #a: Silence on sloppy wrong programs are least surprise, and is > arguably the most vivid different between sloppy and strict. > > I doubt there's any sensible choices other than #a and silence. > > > > On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock <allen at wirfs-brock.com > > wrote: > >> So, #3 appears to be the winner. >> >> Given that, can we also agree that this is throws (or at least that the >> delete does nothing): >> >> eval ("let x=5; delete x;"); >> >> (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) >> >> Allen >> >> >> >> On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: >> >> I'm also fine with 3. >> >> On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> >> wrote: >> >>> Happy to concede to #3 on my end. Just wanted to be clear that it seems >>> to be optimizing for future happiness vs. least surprising behavior (which >>> isn't a bad thing). >>> >>> >>> On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro < >>> jorge at jorgechamorro.com> wrote: >>> >>> On 17/02/2014, at 13:42, Andreas Rossberg wrote: >>> > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >>> >> Allen Wirfs-Brock wrote: >>> >>> >>> >>> Another consideration in the back of my mind is that there may be >>> useful >>> >>> to implementors to knowing that let/const/class declaration are never >>> >>> dynamically added to a non-global environment. >>> >> >>> >> +lots, this should be front of mind. >>> >> >>> >> In a block, we want the bindings local to that block to be statically >>> >> analyzable. We want no non-local mode effects. So, #3 still wins. >>> > >>> > Strongly seconded. >>> >>> And even thirded. >>> >>> -- >>> ( Jorge )(); >>> >>> _______________________________________________ >>> 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 >>> >>> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > > -- > Cheers, > --MarkM > > > -- Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/b867a0ba/attachment.html>
I'm getting vary. Does that mean that you want to change the semantics since ES5.1?
I'm getting vary. Does that mean that you want to change the semantics since ES5.1? On Mon Feb 17 2014 at 5:12:24 PM, Mark S. Miller <erights at google.com> wrote: > +1. > > > On Mon, Feb 17, 2014 at 2:06 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote: > > See > http://people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation > > > A better statement of the question would be can we agree that lexical > bindings created by eval are always non-deletable binding. Where or not is > throws which the various modes is already determined by the existing spec. > for delete based upon whether or not the binding is deletable. > > Allen > > > > > On Feb 17, 2014, at 1:16 PM, Mark S. Miller wrote: > > In this context, there are two things you might mean by "throws": > a) That this delete is an early error within the evaled program, and > therefore throws before any of the code in the evaled program executes. > b) That the delete is a dynamic error that happens when the delete > executes, and therefore that the evaled code prior to the delete has > executed before the error is thrown. > > -1 on #b. > > Assuming you mean #a, between #a and silence, I'm torn. Here are pros and > cons: > pro #a: The program is wrong. Silence fails to bring it to anyone's > attention, making the mistake less likely to be fixed. And making it more > likely the program's execution deviates from author's intent. > con #a: Silence on sloppy wrong programs are least surprise, and is > arguably the most vivid different between sloppy and strict. > > I doubt there's any sensible choices other than #a and silence. > > > > On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock <allen at wirfs-brock.com > > wrote: > > So, #3 appears to be the winner. > > Given that, can we also agree that this is throws (or at least that the > delete does nothing): > > eval ("let x=5; delete x;"); > > (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) > > Allen > > > > On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: > > I'm also fine with 3. > > On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> > wrote: > > Happy to concede to #3 on my end. Just wanted to be clear that it seems > to be optimizing for future happiness vs. least surprising behavior (which > isn't a bad thing). > > > On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com>wrote: > > On 17/02/2014, at 13:42, Andreas Rossberg wrote: > > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: > >> Allen Wirfs-Brock wrote: > >>> > >>> Another consideration in the back of my mind is that there may be > useful > >>> to implementors to knowing that let/const/class declaration are never > >>> dynamically added to a non-global environment. > >> > >> +lots, this should be front of mind. > >> > >> In a block, we want the bindings local to that block to be statically > >> analyzable. We want no non-local mode effects. So, #3 still wins. > > > > Strongly seconded. > > And even thirded. > > -- > ( Jorge )(); > > _______________________________________________ > 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 > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > > > > -- > Cheers, > --MarkM > > > > > > -- > Cheers, > --MarkM > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/273585ac/attachment-0001.html>
No, absolutely not. By "lexical", I took Allen to mean the new reliably block-local binding forms: "let", "const", "class"
No, absolutely not. By "lexical", I took Allen to mean the new reliably block-local binding forms: "let", "const", "class" On Mon, Feb 17, 2014 at 2:17 PM, Erik Arvidsson <erik.arvidsson at gmail.com>wrote: > I'm getting vary. Does that mean that you want to change the semantics > since ES5.1? > > > On Mon Feb 17 2014 at 5:12:24 PM, Mark S. Miller <erights at google.com> > wrote: > >> +1. >> >> >> On Mon, Feb 17, 2014 at 2:06 PM, Allen Wirfs-Brock <allen at wirfs-brock.com >> > wrote: >> >> See >> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation >> >> >> A better statement of the question would be can we agree that lexical >> bindings created by eval are always non-deletable binding. Where or not is >> throws which the various modes is already determined by the existing spec. >> for delete based upon whether or not the binding is deletable. >> >> Allen >> >> >> >> >> On Feb 17, 2014, at 1:16 PM, Mark S. Miller wrote: >> >> In this context, there are two things you might mean by "throws": >> a) That this delete is an early error within the evaled program, and >> therefore throws before any of the code in the evaled program executes. >> b) That the delete is a dynamic error that happens when the delete >> executes, and therefore that the evaled code prior to the delete has >> executed before the error is thrown. >> >> -1 on #b. >> >> Assuming you mean #a, between #a and silence, I'm torn. Here are pros and >> cons: >> pro #a: The program is wrong. Silence fails to bring it to anyone's >> attention, making the mistake less likely to be fixed. And making it more >> likely the program's execution deviates from author's intent. >> con #a: Silence on sloppy wrong programs are least surprise, and is >> arguably the most vivid different between sloppy and strict. >> >> I doubt there's any sensible choices other than #a and silence. >> >> >> >> On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock < >> allen at wirfs-brock.com> wrote: >> >> So, #3 appears to be the winner. >> >> Given that, can we also agree that this is throws (or at least that the >> delete does nothing): >> >> eval ("let x=5; delete x;"); >> >> (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) >> >> Allen >> >> >> >> On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: >> >> I'm also fine with 3. >> >> On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> >> wrote: >> >> Happy to concede to #3 on my end. Just wanted to be clear that it seems >> to be optimizing for future happiness vs. least surprising behavior (which >> isn't a bad thing). >> >> >> On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com >> > wrote: >> >> On 17/02/2014, at 13:42, Andreas Rossberg wrote: >> > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >> >> Allen Wirfs-Brock wrote: >> >>> >> >>> Another consideration in the back of my mind is that there may be >> useful >> >>> to implementors to knowing that let/const/class declaration are never >> >>> dynamically added to a non-global environment. >> >> >> >> +lots, this should be front of mind. >> >> >> >> In a block, we want the bindings local to that block to be statically >> >> analyzable. We want no non-local mode effects. So, #3 still wins. >> > >> > Strongly seconded. >> >> And even thirded. >> >> -- >> ( Jorge )(); >> >> _______________________________________________ >> 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 >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >> >> >> -- >> Cheers, >> --MarkM >> >> >> >> >> >> -- >> Cheers, >> --MarkM >> > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -- Text by me above is hereby placed in the public domain Cheers, --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/4b0f95a4/attachment.html>
Right, let/const/class
Right, let/const/class Allen On Feb 17, 2014, at 2:19 PM, Mark Miller wrote: > No, absolutely not. By "lexical", I took Allen to mean the new reliably block-local binding forms: "let", "const", "class" > > > On Mon, Feb 17, 2014 at 2:17 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote: > I'm getting vary. Does that mean that you want to change the semantics since ES5.1? > > > On Mon Feb 17 2014 at 5:12:24 PM, Mark S. Miller <erights at google.com> wrote: > +1. > > > On Mon, Feb 17, 2014 at 2:06 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: > See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-delete-operator-runtime-semantics-evaluation > > A better statement of the question would be can we agree that lexical bindings created by eval are always non-deletable binding. Where or not is throws which the various modes is already determined by the existing spec. for delete based upon whether or not the binding is deletable. > > Allen > > > > > On Feb 17, 2014, at 1:16 PM, Mark S. Miller wrote: > >> In this context, there are two things you might mean by "throws": >> a) That this delete is an early error within the evaled program, and therefore throws before any of the code in the evaled program executes. >> b) That the delete is a dynamic error that happens when the delete executes, and therefore that the evaled code prior to the delete has executed before the error is thrown. >> >> -1 on #b. >> >> Assuming you mean #a, between #a and silence, I'm torn. Here are pros and cons: >> pro #a: The program is wrong. Silence fails to bring it to anyone's attention, making the mistake less likely to be fixed. And making it more likely the program's execution deviates from author's intent. >> con #a: Silence on sloppy wrong programs are least surprise, and is arguably the most vivid different between sloppy and strict. >> >> I doubt there's any sensible choices other than #a and silence. >> >> >> >> On Mon, Feb 17, 2014 at 12:52 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: >> So, #3 appears to be the winner. >> >> Given that, can we also agree that this is throws (or at least that the delete does nothing): >> >> eval ("let x=5; delete x;"); >> >> (bug https://bugs.ecmascript.org/show_bug.cgi?id=1111 ) >> >> Allen >> >> >> >> On Feb 17, 2014, at 8:02 AM, Erik Arvidsson wrote: >> >>> I'm also fine with 3. >>> >>> On Mon Feb 17 2014 at 10:39:47 AM, Jeremy Martin <jmar777 at gmail.com> wrote: >>> Happy to concede to #3 on my end. Just wanted to be clear that it seems to be optimizing for future happiness vs. least surprising behavior (which isn't a bad thing). >>> >>> >>> On Mon, Feb 17, 2014 at 10:26 AM, Jorge Chamorro <jorge at jorgechamorro.com> wrote: >>> On 17/02/2014, at 13:42, Andreas Rossberg wrote: >>> > On 15 February 2014 06:10, Brendan Eich <brendan at mozilla.com> wrote: >>> >> Allen Wirfs-Brock wrote: >>> >>> >>> >>> Another consideration in the back of my mind is that there may be useful >>> >>> to implementors to knowing that let/const/class declaration are never >>> >>> dynamically added to a non-global environment. >>> >> >>> >> +lots, this should be front of mind. >>> >> >>> >> In a block, we want the bindings local to that block to be statically >>> >> analyzable. We want no non-local mode effects. So, #3 still wins. >>> > >>> > Strongly seconded. >>> >>> And even thirded. >>> >>> -- >>> ( Jorge )(); >>> _______________________________________________ >>> 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 >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >> >> >> -- >> Cheers, >> --MarkM > > > > > -- > Cheers, > --MarkM > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > > > > -- > Text by me above is hereby placed in the public domain > > Cheers, > --MarkM -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140217/b21f2f88/attachment-0001.html>
On Feb 14, 2014, at 5:49 AM, André Bargull wrote:
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:
(function() { eval("let answer=42"); console.log(answer); // 42 })();
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?