Comments on Meeting Notes
Kevin Smith wrote:
=== @names ===
I think punting on @name syntax until ES7 is a wise move. I would like to sneak in a word of clarification on my modular @name proposal, though. In my proposal, @names are not "implicitly declared" variables. They are namespaced identifiers, where the namespace container is the module URL. They are static in the sense that all @names can be mapped to a globally unique string (module URL + identifier) prior to execution.
Modular @names are not simply veneer over symbols. They provide a separate facility (non-conflicting property names) which happens to use unique symbols as an implementation strategy. It could perhaps also use globally unique strings...
In my opinion, we should not go with bracketed, computed property names solely for the support of the iterator protocol. Ultimately, I would +1 recommend a more conservative approach for ES6: use the plain string "iterator" as the protocol hook. Once the syntactic issues have been
I'd say not "iterator". This is a special identifier, so to speak "instead-of-symbol-internal-name", so I would go for iterator. Same for other few examples which may have benefited from symbols but cannot.
It would create consistent legacy realm where each member should be obsoleted by evangelizing the right way once it appears (proto won't have one, it is too stuck; {define|lookup}{Getter|Setter} already have the right way; it can be same for iterator, create, hasInstance etc.).
addressed in ES7, future language hooks can use unique symbols. Give the user base some time to digest symbols, and see where the cows roam before adding syntax directing them. There is more than enough new "stuff" in ES6, without having to rewrite everything in terms of symbols (just yet).
=== let ===
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Leave non-strict as is, and let users opt-in to "let". An excellent carrot.
I would agree. But there would be a fight of what else should only be strict-mode, since it is simpler to do it that way. Then there comes 1JS, and refactoring concerns, and a lot more, probably.
On Tue, Dec 4, 2012 at 8:54 AM, Kevin Smith <khs4473 at gmail.com> wrote:
=== Modules ===
Perhaps I'm misreading the notes, but I am concerned about the amount of churn that I'm seeing in module discussions. Particularly worrisome to me is the suggestion that the default loading behavior should map:
import x from "foo";
to:
System.baseURL + "foo" + ".js"
This is contrary to all url resolution algorithms on the web, and involves way too much magic.
[sorry Kevin, sent this to you directly when meant to sent to list, so sending again]
This is what AMD loaders use. For me, it seems straightforward, not much magic on its own. The old dojo one did too, except it used dots instead of slashes in IDs, but it was effectively baseUrl + id + '.js'. I believe it has held up well.
What other ID-to-URL resolution algorithms are used on the web that have decent adoption, besides just plain URLs? Alternatively, what problems do you see with that algorithm?
It is important to use an ID type vs a plain URL to allow sharing of code between environments that may have different path resolution logic. For example, for node, it may choose to check a few file paths for a given ID. For networked loading though it is good to have a reasonable one IO lookup rule per ID.
James
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there.
Strict mode has a bad rep for two other important causes:
-
It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
-
It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
Leave non-strict as is, and let users opt-in to "let". An excellent carrot.
The problem is precisely that users cannot opt into "let" alone by its novel syntax. Opting into strict mode may or may not win but it has added costs and benefits, and that means let adoption will suffer.
1JS wants new syntax to be its own opt-in. The only issue with making let work in non-strict code is the obscure let[i] = j; pattern. If no one actually wrote such code (it's possible; public web searches by big search-engine companies, or at least one so far, found nothing), then we should not risk reduced let adoption by yoking it to the heavier burden of strict mode.
1JS wants new syntax to be its own opt-in.
Right - except of course let[i] = j;
isn't new syntax. In non-strict,
let
is either an identifier, or it isn't. If it's an identifier, then
let it be a full-fledged identifier, not some half-man, half-beast. I
think it's best to avoid situations where we have to say things like "it
is, except when it's not".
And while I agree that let
is nice, in my personal experience it's by far
not the most important new feature of ES6. In fact, for me it ends up way
down on the list behind arrows, classes, object literal shortcuts,
templates, comprehensions, destructuring, modules, const, etc. It's above
proxies though ; ). In short, I don't think we need to put quite such a
high priority on let
adoption.
On Dec 4, 2012, at 8:54 AM, Kevin Smith <khs4473 at gmail.com> wrote:
Particularly worrisome to me is the suggestion that the default loading behavior should map:
import x from "foo";
to:
System.baseURL + "foo" + ".js"
This is contrary to all url resolution algorithms on the web, and involves way too much magic.
As James says, it's not contrary to AMD, and it's also similar to NPM. And it's similar to systems like YUI, but in a slightly different way: instead of the nesting structure of modules being expressed as nested objects, it's expressed as nested logical names.
This came about as a result of a couple things: First, James raised a concern that there's a kind of impedance mismatch between the string/filesystem nesting and the dotted sub-module nesting, and it wasn't clear how to decide between them, or how the naming of a filesystem structure should map to the naming of dot-paths as the result of a build tool.
But second, we realized that the whole initial design of binding module names to identifiers (as opposed to string names) no longer solved the problem it was initially supposed to solve. An application needs to set up a configuration or registry where components can get at other components by some sort of naming convention. Originally this was achieved by binding modules to variables that were globally accessible and implicitly shared in scope with other modules. This was problematic for various reasons and removed, but now it was no longer possible to use variables to create a shared registry of the modules in the system. And yet, at the same time, the loader did contain such a registry.
Finally, this makes for a more straightforward equivalence between modules in separate files and modules concatenated together into a single file; they can be given names that match the names that would match the logical names that map to the filesystem, so the code that uses them doesn't have to change.
In general, I would like to see more updates and more convergence regarding the modules specification, as many of us are now aiming at a (seemingly) wildly moving target.
Well, the standard isn't out yet, so to some degree this is part of the process. But I take the blame for this stuff not happening sooner. I am actively working on modules, and trying to nail this all down as soon as possible.
David Herman wrote:
In general, I would like to see more updates and more convergence regarding the modules specification, as many of us are now aiming at a (seemingly) wildly moving target.
Well, the standard isn't out yet, so to some degree this is part of the process. But I take the blame for this stuff not happening sooner. I am actively working on modules, and trying to nail this all down as soon as possible.
I would like to defend Dave against Kevin's "wildly". Sam's writeup from the minutes gives the history:
STH: Yes, that was the way, but there was a realization that much of the earlier approach was flawed and these updates lead to revisions.
One important use case for modules is to configure module references, so that libraries can import jQuery (for example), and get the appropriate version of jQuery specified by the page. Further, it's desirable to be able to use different code for the same library name in different context. Originally, the modules proposal managed this via lexical scope, as follows:
module M1 { module jquery = "jquery.js"; module something = "something_that_uses_jquery.js" }
module M2 { module jquery = "zepto.js"; module something_else = "something_else_that_uses_jquery.js" }
However, this has two major problems: Inheriting scope across references to external files is potentially confusing, and disliked by a number of people Once we decided to share instances of the same module, the "parent scope" of a module is no longer well-defined
Therefore, we abandoned the idea of inheriting scope across external references. However, this had two consequences that we did not immediately appreciate. First, we no longer had a method for managing this configuration between module names and source code. Second, scoped module names no longer had nearly as much use as originally.
Thus, Dave and I revisited the design, abandoning the use of lexical scope for managing module names, and introducing module names that could be configured on a per-Loader basis.
Now, there's no "wildness" here (things too a while, OTOH). The main trajectory is from second class modules with lexical scope and no memoization of shared instance by MRL, to memoization for sharing, to lose the nested lexical scope when modules are not inlined, to more manageable module names that actually match existing practice pretty well.
(Oh, and we gave up on lexical-only all the way up, and kept the global object as top scope, but (separate from modules per se) with a new, single lexical contour populated by script elements based on let/const/class/module bindings.)
That the default loader knows about pathnames and ".js" is a good thing in my view. You want something else, write another loader.
Kevin Smith wrote:
1JS wants new syntax to be its own opt-in.
Right - except of course
let[i] = j;
isn't new syntax.
Of course, you cited only one sentence I wrote and cut the rest where I adverted to the problem. But is it a real problem?
In non-strict,
let
is either an identifier, or it isn't. If it's an identifier, then let it be a full-fledged identifier, not some half-man, half-beast. I think it's best to avoid situations where we have to say things like "it is, except when it's not".
What if we just say "use let in ES6"? The incompatible change is nasty in theory, but in practice it may be a tree falling in a forest.
This is the argument, which you did not engage because you assumed a conclusion or just preferred not to have to worry. I sympathize! But the position we arrived at does not require assuming anything. Implementations and search engines can try this out and see if it bites back.
Of course, you cited only one sentence I wrote and cut the rest where I adverted to the problem.
Sorry - I get creative with my cuts sometimes : )
But is it a real problem?
Probably not, but my POV is that if let is an identifier (and in non-strict mode, it will be), then let it have all the rights and privileges thereto pertaining.
It's like let
is that annoying uncle at your Christmas dinner. Nobody
wants him there but he's entitled to his egg-nog just like everyone else.
: )
I would like to defend Dave against Kevin's "wildly".
Yeah - it was a little inflammatory. Sorry, Dave. I think you rock, of course : )
That the default loader knows about pathnames and ".js" is a good thing in
my view. You want something else, write another loader.
Actually, I feel like I'm arguing from a position of ignorance at this point, so I'll wait until Dave gives us a more complete picture before abusing anyone further on this subject.
Herby Vojčík wrote:
recommend a more conservative approach for ES6: use the plain string "iterator" as the protocol hook. Once the syntactic issues have been
I'd say not "iterator". This is a special identifier, so to speak "instead-of-symbol-internal-name", so I would go for iterator. Same for other few examples which may have benefited from symbols but cannot.
TC39 probably will barf, but you make a good point -- so good it's what I implemented in JS1.7 and up in SpiderMonkey.
It would create consistent legacy realm where each member should be obsoleted by evangelizing the right way once it appears (proto won't have one, it is too stuck; {define|lookup}{Getter|Setter} already have the right way; it can be same for iterator, create, hasInstance etc.).
We hope to skip this legacy and leave it in the multiverse of alternative realities. Can we do it? If not now, why do you think we could do it later, when the dunder-names are sucking all the oxygen out of the "use symbols" room?
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich <brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there.
Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function. For any portion of code being actively maintained, the non-strict semantics are a hazard. Admittedly, today with the co-existence of ES3 and ES5, the forking issue does create an additional problem, because strict code has to work non-strict as well in old browsers. But pre-ES5 browsers are finally starting to fade away for real. By the time ES6 rolls out, I don't expect much ES6 code to be concerned about also running on ES3.
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed.
Leave non-strict as is, and let users opt-in to "let". An excellent carrot.
The problem is precisely that users cannot opt into "let" alone by its novel syntax. Opting into strict mode may or may not win but it has added costs and benefits, and that means let adoption will suffer.
From what was said at the TC39 meeting, the main "cost" is simply that
strict mode has a bad rep with the community. This bad rep, to the extent it still exists, is largely superstition. However, the committee, in fear of this irrationality among the community, is about to make some bad decisions. This es-discuss list is, perhaps, adequately representative of the community that if there's an outcry, not to further cruft up the language for the sake of making ES6 features available in strict mode at all costs, then perhaps we can get the committee to revisit some of those decisions.
1JS wants new syntax to be its own opt-in. The only issue with making let work in non-strict code is the obscure let[i] = j; pattern. If no one actually wrote such code (it's possible; public web searches by big search-engine companies, or at least one so far, found nothing), then we should not risk reduced let adoption by yoking it to the heavier burden of strict mode.
By the time ES6 is a reality, there won't be anything heavy about strict mode, except the committee's fear of lingering superstition among developers.
On Tue, Dec 4, 2012 at 1:04 PM, Mark S. Miller <erights at google.com> wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich <brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there.
Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function. For any portion of code being actively maintained, the non-strict semantics are a hazard. Admittedly, today with the co-existence of ES3 and ES5, the forking issue does create an additional problem, because strict code has to work non-strict as well in old browsers. But pre-ES5 browsers are finally starting to fade away for real. By the time ES6 rolls out, I don't expect much ES6 code to be concerned about also running on ES3.
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed.
Leave non-strict as is, and let users opt-in to "let". An excellent carrot.
The problem is precisely that users cannot opt into "let" alone by its novel syntax. Opting into strict mode may or may not win but it has added costs and benefits, and that means let adoption will suffer.
From what was said at the TC39 meeting, the main "cost" is simply that strict mode has a bad rep with the community. This bad rep, to the extent it still exists, is largely superstition. However, the committee, in fear of this irrationality among the community, is about to make some bad decisions. This es-discuss list is, perhaps, adequately representative of the community that if there's an outcry, not to further cruft up the language for the sake of making ES6 features available in strict mode at all costs, then perhaps we can
Obviously, that should have been "...available in non-strict mode at all costs"
Brendan Eich wrote:
Herby Vojčík wrote:
recommend a more conservative approach for ES6: use the plain string "iterator" as the protocol hook. Once the syntactic issues have been
I'd say not "iterator". This is a special identifier, so to speak "instead-of-symbol-internal-name", so I would go for iterator. Same for other few examples which may have benefited from symbols but cannot.
TC39 probably will barf, but you make a good point -- so good it's what I implemented in JS1.7 and up in SpiderMonkey.
I didn't know, really. :-)
It would create consistent legacy realm where each member should be obsoleted by evangelizing the right way once it appears (proto won't have one, it is too stuck; {define|lookup}{Getter|Setter} already have the right way; it can be same for iterator, create, hasInstance etc.).
We hope to skip this legacy and leave it in the multiverse of alternative realities. Can we do it? If not now, why do you think we could do it later, when the dunder-names are sucking all the oxygen out of the "use symbols" room?
I am convinced it is doable (to have legacy names but move to use the better way once it is present) with the example of defineGetter & Co. I confess I don't know how this is in the wild, just me being here makes me a kind of early adopter with bias for using the new/right way, but I feel those (defineGetter and company) are of little use now and the world successfully moved to Object.defineProperty / {get,set} x() in literals. So why this wouldn't be possible for others?
/be
Herby
P.S.: And even proto could be changed to use @parent or similar syntax later. I already proposed it here on the list a few weeks ago. Every legacy could have its note in spec, saying what should be used instead. And just wait until it catches up (while pushing it constantly).
Mark S. Miller wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich<brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function.
Real world problem: concatenation.
For any portion of code being actively maintained, the non-strict semantics are a hazard. Admittedly, today with the co-existence of ES3 and ES5, the forking issue does create an additional problem, because strict code has to work non-strict as well in old browsers. But pre-ES5 browsers are finally starting to fade away for real. By the time ES6 rolls out, I don't expect much ES6 code to be concerned about also running on ES3.
Hard to say what IE8's share will be, but IE9 did not implement strict mode IIRC. IE10 did.
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed.
Right, that's what I tried to say by "could use the arguments object". Nothing to do with hated f.arguments.
So every strict function that uses arguments pays a copying price on entry in a naive implementation. Pushing the copies out till just before there might be an aliasing store is an optimization that could be done in a more sophisticated implementation, but engines don't do it currently and feel little pressure to do so. Chicken and egg.
Leave non-strict as is, and let users opt-in to "let". An excellent carrot. The problem is precisely that users cannot opt into "let" alone by its novel syntax. Opting into strict mode may or may not win but it has added costs and benefits, and that means let adoption will suffer.
From what was said at the TC39 meeting, the main "cost" is simply that strict mode has a bad rep with the community. This bad rep, to the extent it still exists, is largely superstition.
No, see above.
On Dec 4, 2012, at 1:28 PM, Brendan Eich wrote:
Mark S. Miller wrote:
...
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed.
Right, that's what I tried to say by "could use the arguments object". Nothing to do with hated f.arguments.
So every strict function that uses arguments pays a copying price on entry in a naive implementation. Pushing the copies out till just before there might be an aliasing store is an optimization that could be done in a more sophisticated implementation, but engines don't do it currently and feel little pressure to do so. Chicken and egg.
The timing of copying is only an issue if the function actually assigns to a formal parameter. Such assignments should be pretty easy to (conservatively) statically check for.
So, you should be able to avoid copying on entry if there is no direct eval and no assignments to formal parameters. A pretty common case.
If there is a reference to arguments (and no assignment to formals), you should only need to copy if a Put is actually made to the arguments object. This is also rare and potentially optimizable in various ways.
So, I guess I agree with Mark on this one. Implementations could do a pretty good job of optimizing strict mode function parameters if they thought it was necessary. It probably needs to be driven by benchmarks.
On Tue, Dec 4, 2012 at 2:18 PM, Mark S. Miller <erights at google.com> wrote:
docs.google.com/spreadsheet/viewform?formkey=dGhXODJIWEFDVjA2RlNwSlF5amVVSVE6MQ
I have received private email complaining about the biased language in this poll, and that as a result it is merely a push poll en.wikipedia.org/wiki/Push_poll. I agree. I encourage someone
who is capable of writing a proper poll to do so and post it. In anticipation of a proper poll, I withdraw this one. Thanks.
My apologies to those who have already taken the time to answer this one.
Allen Wirfs-Brock wrote:
On Dec 4, 2012, at 1:28 PM, Brendan Eich wrote:
Mark S. Miller wrote:
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object. This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed. Right, that's what I tried to say by "could use the arguments object". Nothing to do with hated f.arguments.
So every strict function that uses arguments pays a copying price on entry in a naive implementation. Pushing the copies out till just before there might be an aliasing store is an optimization that could be done in a more sophisticated implementation, but engines don't do it currently and feel little pressure to do so. Chicken and egg.
The timing of copying is only an issue if the function actually assigns to a formal parameter. Such assignments should be pretty easy to (conservatively) statically check for.
I'm telling you what engines do. Not what they might do. I did assignment analysis in SpiderMonkey for Firefox 3.6, it was helpful in its day. I think a bunch has been ripped out because modern JITs don't need it.
So, I guess I agree with Mark on this one. Implementations could do a pretty good job of optimizing strict mode function parameters if they thought it was necessary. It probably needs to be driven by benchmarks.
You are not responding to the point I made, cited above: " engines don't do it currently and feel little pressure to do so. Chicken and egg."
Benchmarks won't cut it if there's no organic developer pressure.
Herby Vojčík wrote:
I am convinced it is doable (to have legacy names but move to use the better way once it is present) with the example of defineGetter & Co.
I suggest those are bad precedents. They never were implemented in IE, which led to ES5's meta-object APIs.
I confess I don't know how this is in the wild, just me being here makes me a kind of early adopter with bias for using the new/right way, but I feel those (defineGetter and company) are of little use now and the world successfully moved to Object.defineProperty / {get,set} x() in literals.
The Object.defineProperty required ES5 and was also predicated on IE never adopteding dunder-define/lookup.
The object literal notation came from SpiderMonkey long ago, BTW -- it was not new and invented only in ES5.
So why this wouldn't be possible for others?
Because of the above, at least. Note how proto also never made it to IE but was more frequently used than __define/lookup, especially on the "mobile web" (post-iPhone, because WebKit reverse-engineered proto). One size does not fit all but we have particular precedents from which to reason, and the particulars do matter.
We cannot have legacy in ES6 and hope to get rid of it "later" IMHO. We'll be committing to it as normative API for the indefinite future.
On Tue, Dec 4, 2012 at 3:57 PM, Brendan Eich <brendan at mozilla.org> wrote:
Benchmarks won't cut it if there's no organic developer pressure.
That is not the behavior I've observed in response to benchmarks, either among JS implementors, or in the industry as a whole. Developer pressure and actual usage patterns should trump benchmarks. What I've generally seen is the opposite.
Could you specify more? If you mean SunSpider (2007) or V8/Octane, I have some well-known bones to pick. These have sucked up a lot (not all) of the oxygen available for the brain cells developers and casually interested parties use to track "JS performance", but due to a who's-on-first effect, not just because "benchmarks".
IOW, good luck making new strict-mode benchmarks that displace these.
Also, good luck getting SunSpider or V8/Octane to enable "use strict"! Paging Dr. Rossberg on the latter :-P.
On Dec 4, 2012, at 4:03 PM, Brendan Eich <brendan at mozilla.org> wrote:
We cannot have legacy in ES6 and hope to get rid of it "later" IMHO. We'll be committing to it as normative API for the indefinite future.
+1
You don't build web functionality with the intention of removing it. It just doesn't work that way.
I suppose it's worth noting I have an implementation of the ES6 standard lib implemented using many ES6 features. Notably a significant amount of @names. At least it's a useful example of them in actual use. Benvie/continuum/tree/gh-pages/modules
Brendan Eich wrote:
Hard to say what IE8's share will be, but IE9 did not implement strict mode IIRC. IE10 did.
IE10 sort of did. The following code: (function(){ 'use strict'; return !this; })(); returns false in IE10. Who knows what other deviations from the standard there are...
Brendan Eich wrote: Hard to say what IE8's share will be, but IE9 did not implement strict mode IIRC. IE10 did.
Michał Z. Gołębiowski wrote: IE10 sort of did. The following code: (function(){ 'use strict'; return !this; })(); returns false in IE10. Who knows what other deviations from the standard there are...
That code returns true in IE10 standards mode. See test262.ecmascript.org for tests validating this and other ES5 implementation compatibility. If you see things not covered there, open bugs suggesting new tests: bugs.ecmascript.org/enter_bug.cgi?product=Test262.
Luke
Le 4 déc. 2012 à 22:28, Brendan Eich <brendan at mozilla.org> a écrit :
Mark S. Miller wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich<brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function.
Real world problem: concatenation.
If we allow "let" and destructuring assignment in non-strict mode, a developer will happily use "let" as variable name, then one day they will write "let[i] = j" (Murphy's law), and get an incomprehensible failure. Moreover, strict and non-strict mode, will not be very different, and people will continue to accidentally swap between them, which will lead to occasional and sometimes insidious bugs.
On the other hand, if we disallow "let" and/or destructuring assignment in non-strict mode, whenever some code using these features is accidentally run as non-strict, it is almost guaranteed that there will be an immediate and loud failure. Because this hazard will happen relatively often, it will help to make generally known that strict and non-strict are indeed incompatible, and, in turn, reduce the chance of incompatible concatenation of strict and non-strict scripts.
As developer, I prefer a loud failure over a smart engine which might silently misinterpret my code in an apparently non-regular way. It is much easier to debug. Please, do not add too smart parsing rules into the language.
Claude
Claude Pache wrote:
Le 4 déc. 2012 à 22:28, Brendan Eich<brendan at mozilla.org> a écrit :
Mark S. Miller wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich<brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times. I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function. Real world problem: concatenation.
If we allow "let" and destructuring assignment in non-strict mode,
(I'm not sure why anything I wrote about strict mode problems was cited, since you did not repond to the "strict mode has a bad rep for these reasons" points...)
a developer will happily use "let" as variable name, then one day they will write "let[i] = j" (Murphy's law), and get an incomprehensible failure.
This could happen, but did the developer forget to declare "let" (assign an implicit global)? The odds shrink. All uses of 'let' as an identifier have abbreviated "letter" and stored a unit-length string value, so have not indexed into the value.
We talked about making 'var let' in combination with 'let[i] = j' an error, but we did not want parsing to depend on binding. OTOH we did talk about warnings.
Murphy's Law does govern us, I agree. It says that anything that can go wrong, will go wrong. But this applies to let underutilization if yoked to strict mode. Deciding between the alternative paths is not a matter of simple logic, since it depends on human factors.
On 5 December 2012 02:46, Brendan Eich <brendan at mozilla.org> wrote:
Also, good luck getting SunSpider or V8/Octane to enable "use strict"! Paging Dr. Rossberg on the latter :-P.
Octane actually contains two benchmarks running in strict mode, namely PDF/JS and GameBoy. (Unfortunately, I just realised that we screwed it up for the latter by file concatentation -- but I'll make sure to get that fixed for the next release.)
For the rest, introducing strict mode would kind of go against the spirit of Octane running "real world" applications as is. But I'd love to see new benchmarks using strict mode in future releases. I don't mind suggestions. :)
On Dec 5, 2012, at 8:49 AM, Andreas Rossberg <rossberg at google.com> wrote:
On 5 December 2012 02:46, Brendan Eich <brendan at mozilla.org> wrote:
Also, good luck getting SunSpider or V8/Octane to enable "use strict"! Paging Dr. Rossberg on the latter :-P.
Octane actually contains two benchmarks running in strict mode, namely PDF/JS
Yay us.
and GameBoy. (Unfortunately, I just realised that we screwed it up for the latter by file concatentation -- but I'll make sure to get that fixed for the next release.)
Zing!
For the rest, introducing strict mode would kind of go against the spirit of Octane running "real world" applications as is. But I'd love to see new benchmarks using strict mode in future releases. I don't mind suggestions. :)
Will try to get you more Iike PDF.js.
Le 5 déc. 2012 à 15:28, Brendan Eich <brendan at mozilla.org> a écrit :
Claude Pache wrote:
Le 4 déc. 2012 à 22:28, Brendan Eich<brendan at mozilla.org> a écrit :
Mark S. Miller wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich<brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times. I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function. Real world problem: concatenation.
If we allow "let" and destructuring assignment in non-strict mode,
(I'm not sure why anything I wrote about strict mode problems was cited, since you did not repond to the "strict mode has a bad rep for these reasons" points...)
(I was probably responding to the wrong message of this thread, sorry.)
a developer will happily use "let" as variable name, then one day they will write "let[i] = j" (Murphy's law), and get an incomprehensible failure.
This could happen, but did the developer forget to declare "let" (assign an implicit global)? The odds shrink. All uses of 'let' as an identifier have abbreviated "letter" and stored a unit-length string value, so have not indexed into the value. "Iet" as abbreviation of "letter", yes ; or maybe some Norwegian developer has once used "let" as an array of colour values? (see en.wiktionary.org/wiki/let ), I don't know.
We talked about making 'var let' in combination with 'let[i] = j' an error, but we did not want parsing to depend on binding. OTOH we did talk about warnings.
If we have indeed warnings when using "let" as identifier, it mitigates the problem. And I think it is a must, for the proposed interpretation of "var let = []; let[i]=j" is really awkward and bizarre (from a human POV).
Murphy's Law does govern us, I agree. It says that anything that can go wrong, will go wrong. But this applies to let underutilization if yoked to strict mode. Deciding between the alternative paths is not a matter of simple logic, since it depends on human factors.
/be (I guess that "let" will be underused anyway in the next six or eight years, because the small value it brings is not worth the cost of being incompatible with older browsers.)
Claude
On Tue, Dec 4, 2012 at 1:28 PM, Brendan Eich <brendan at mozilla.org> wrote:
Mark S. Miller wrote:
On Tue, Dec 4, 2012 at 10:48 AM, Brendan Eich<brendan at mozilla.org> wrote:
Kevin Smith wrote:
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there.
Strict mode has a bad rep for two other important causes:
- It forks runtime semantics, which requires careful testing in pre-ES5-strict implementations. This has been a real-world problem, multiple times.
I buy this for old code that needs to just keep working, bugs and all, without human attention. But strict mode can be opted into incrementally, per program or even per function.
Real world problem: concatenation.
By reaching out to the few concatenation engines it might be possible to reduce this problem in practice.
From what was said at the TC39 meeting, the main "cost" is simply that strict mode has a bad rep with the community. This bad rep, to the extent it still exists, is largely superstition.
I suggest an alternative analysis: developers likely to adopt 'use strict' are likely to know of its benefits. They are unlikely to realize significant benefits exactly because they are aware of the pitfalls the feature prevents. Thus when they become aware of the costs (cited by Brendan), their cost/benefit flips easily to the other side. Thus use-strict-deniers are not 'superstitious': only zealots stick to a technology after the cost/benefit gets out of whack. Mitigating the costs is important to improve adoption.
jjb
Luke Hoban <lukeh at microsoft.com> wrote:
IE10 sort of did. The following code: (function(){ 'use strict'; return !this; })(); returns false in IE10. Who knows what other deviations from the standard there are...
That code returns true in IE10 standards mode. See test262.ecmascript.orgfor tests validating this and other ES5 implementation compatibility. If you see things not covered there, open bugs suggesting new tests: bugs.ecmascript.org/enter_bug.cgi?product=Test262.
Indeed, it must have been an earlier IE10 preview version then. I apologize for the accusation.
On 12/04/2012 03:57 PM, Brendan Eich wrote:
Allen Wirfs-Brock wrote:
The timing of copying is only an issue if the function actually assigns to a formal parameter. Such assignments should be pretty easy to (conservatively) statically check for.
I'm telling you what engines do. Not what they might do. I did assignment analysis in SpiderMonkey for Firefox 3.6, it was helpful in its day. I think a bunch has been ripped out because modern JITs don't need it.
[...]the point I made, cited above: " engines don't do it currently and feel little pressure to do so. Chicken and egg."
SpiderMonkey's implementation of the arguments object functions exactly as described here for functions with strict mode code -- actually for all functions, I think. Regarding the strict mode semantics specifically, it was fairly easy to make those optimizations when I was implementing the various strict mode arguments semantics, so I did them. There hasn't been a time where SpiderMonkey's had strict mode arguments semantics, without these optimizations.
Jeff Walden wrote:
On 12/04/2012 03:57 PM, Brendan Eich wrote:
Allen Wirfs-Brock wrote:
The timing of copying is only an issue if the function actually assigns to a formal parameter. Such assignments should be pretty easy to (conservatively) statically check for. I'm telling you what engines do. Not what they might do. I did assignment analysis in SpiderMonkey for Firefox 3.6, it was helpful in its day. I think a bunch has been ripped out because modern JITs don't need it.
Just to be clear, that assignment analysis was not used to optimize arguments copying for strict mode.
[...]the point I made, cited above: " engines don't do it currently and feel little pressure to do so. Chicken and egg."
SpiderMonkey's implementation of the arguments object functions exactly as described here for functions with strict mode code -- actually for all functions, I think. Regarding the strict mode semantics specifically, it was fairly easy to make those optimizations when I was implementing the various strict mode arguments semantics, so I did them. There hasn't been a time where SpiderMonkey's had strict mode arguments semantics, without these optimizations.
I don't see this. Firefox 3 era (pre-ES5):
js> function f(x) { if (0) arguments; return x }
js> dis(f)
main: 00000: getarg 0 00003: return 00004: stop
Source notes:
Latest SpiderMonkey:
js> function f(x) { if (0) arguments; return x }
js> dis(f)
flags: loc op
00000: arguments 00001: setlocal 0 00004: pop main: 00005: getarg 0 00008: return 00009: stop
Source notes: ofs line pc delta desc args
0: 1 5 [ 5] colspan 34 2: 1 9 [ 4] colspan 8
js> function g(x) { "use strict"; if (0) arguments; return x }
js> dis(g)
flags: loc op
00000: arguments 00001: setlocal 0 00004: pop main: 00005: getarg 0 00008: return 00009: stop
Source notes: ofs line pc delta desc args
0: 3 5 [ 5] colspan 16 2: 3 5 [ 0] colspan 32 4: 3 9 [ 4] colspan 8
True, no difference due to "use strict"; but both paths rely on the JIT to optimize away the useless arguments op. That op is emitted even though no code (live or dead) assigns to the formal parameter x.
Now let's go back to rev ba4d04033cd8 in the tracemonkey repo at hg.mozilla.org, and make the function assign to a formal somewhere in its control flow:
js> function f(x) { if (1) arguments; else x = 42; return x }
js> dis(f)
flags: NULL_CLOSURE loc op
main: 00000: getarg 0 00003: return 00004: stop
Source notes: off line pc delta desc args
0: 10 0 [ 0] colspan 54 2: 10 4 [ 4] colspan 1
This is optimized to avoid reifying the arguments object, which is in a useless expression statement so not needed.
This state of SpiderMonkey supported strict mode, as demonstrated by the corresponding function g:
js> function g(x) { "use strict"; if (1) arguments; else x = 42; return x }
js> dis(g)
flags: NULL_CLOSURE loc op
00000: arguments 00001: pop main: 00002: getarg 0 00005: return 00006: stop
Source notes: off line pc delta desc args
0: 8 2 [ 2] colspan 68 2: 8 6 [ 4] colspan 1
Here arguments is reified because the formal x is assigned and the parser saw 'arguments' used albeit in a useless expression statement.
(The colspan source notes, for column index in source maps, shows I have a patch pushed:
$ hg log -r tip changeset: 73898:ba4d04033cd8 tag: bug568142-big-srcnote-fun tag: qbase tag: qtip tag: tip user: Brendan Eich <brendan at mozilla.org>
date: Tue Oct 18 17:40:58 2011 -0700 summary: imported patch bug568142-big-srcnote-fun
from 2011 in this old workarea, but it doesn't affect code generation.)
Some of this evolution shows how interpreter performance has mattered less and less (for the popular benchmarks, anyway). But it also shows that what I wrote was true: SpiderMonkey used to do more analysis in order to avoid reifying arguments objects, and ES5 strict mode in a function that assigns a formal required reifying on entry, to copy the actuals into arguments before any could be clobbered.
Other implementors should pipe up about strict mode effects on function code. I remember Oliver (JavaScriptCore) pointing out the arguments-copying requirement of strict mode as a deoptimization. See
mail.mozilla.org/pipermail/es5-discuss/2009-August/003144.html
and others in that thread.
- It deoptimizes, e.g. a strict-mode function must be optimized to copy actual parameter values into arguments if it could use the arguments object.
This one I just don't buy at all. In a strict function f, f.arguments is poisoned. f's arguments would only need to be reified if f statically mentions "arguments" or if f has a statically apparent use of the direct eval operator. For all other cases, no arguments object need be created, and therefore no copying is needed.
Right, that's what I tried to say by "could use the arguments object". Nothing to do with hated f.arguments.
So every strict function that uses arguments pays a copying price on entry in a naive implementation. Pushing the copies out till just before there might be an aliasing store is an optimization that could be done in a more sophisticated implementation, but engines don't do it currently and feel little pressure to do so. Chicken and egg.
Can you explain? What is this copying price and why don’t non-strict functions have to pay it?
Thanks!
Axel
Axel Rauschmayer wrote:
Can you explain? What is this copying price and why don’t non-strict functions have to pay it?
Strict functions have an arguments object that does not alias formal parameters:
js> function f(x) { print(x); arguments[0] = 42; return x; }
js> f(99)
99 42 js> function g(x) { "use strict"; print(x); arguments[0] = 42; return x; }
js> g(99)
99 99
For non-strict functions, formal parameters and the argument object can share the same storage on the processor stack. Strict functions require a copy, if either a formal or an args object element is modified. The conserative implementation is to always copy.
AllenBrendan Eich <brendan at mozilla.com> wrote:Axel Rauschmayer wrote:
Can you explain? What is this copying price and why don’t non-strict functions have to pay it?
Strict functions have an arguments object that does not alias formal parameters:
js> function f(x) { print(x); arguments[0] = 42; return x; }
js> f(99)
99 42 js> function g(x) { "use strict"; print(x); arguments[0] = 42; return x; }
js> g(99)
99 99
=== @names ===
I think punting on @name syntax until ES7 is a wise move. I would like to sneak in a word of clarification on my modular @name proposal, though. In my proposal, @names are not "implicitly declared" variables. They are namespaced identifiers, where the namespace container is the module URL. They are static in the sense that all @names can be mapped to a globally unique string (module URL + identifier) prior to execution.
Modular @names are not simply veneer over symbols. They provide a separate facility (non-conflicting property names) which happens to use unique symbols as an implementation strategy. It could perhaps also use globally unique strings...
In my opinion, we should not go with bracketed, computed property names solely for the support of the iterator protocol. Ultimately, I would recommend a more conservative approach for ES6: use the plain string "iterator" as the protocol hook. Once the syntactic issues have been addressed in ES7, future language hooks can use unique symbols. Give the user base some time to digest symbols, and see where the cows roam before adding syntax directing them. There is more than enough new "stuff" in ES6, without having to rewrite everything in terms of symbols (just yet).
=== let ===
I recommend allowing let declarations only in strict mode. This is the simple, backwards-compatible path. Strict mode only has a bad reputation because, in ES5, it is restrictive-only. There are (almost) no carrots leading users there. Leave non-strict as is, and let users opt-in to "let". An excellent carrot.
=== Modules ===
Perhaps I'm misreading the notes, but I am concerned about the amount of churn that I'm seeing in module discussions. Particularly worrisome to me is the suggestion that the default loading behavior should map:
to:
This is contrary to all url resolution algorithms on the web, and involves way too much magic.
In general, I would like to see more updates and more convergence regarding the modules specification, as many of us are now aiming at a (seemingly) wildly moving target.