ES6 opt-in, reloaded
brendan at mozilla.org
Mon Jan 16 10:35:01 PST 2012
> Andreas Rossberg <mailto:rossberg at google.com>
> January 16, 2012 8:09 AM
> Some of the recent discussion regarding ES6 opt-in has been rather...
It's es-discuss, don't be scared. Just working through a
thought-experiment, however misguided in someone's view, is low-cost and
needs a forum for discussion. Occasionally we are all mistaken about an
idea being misguided, and the experiment will prove worth the cost of
> I would like to step back a bit, and try to identify the goals
> that we actually want to achieve. I think these are:
> 1. Make ES6 opt-in as convenient as possible.
Yes. We need to talk about what actually has happened on the web with
opt-in attributes and modifiers, though -- not just try to build a
minimized logic system that we think is convenient (mostly because it is
> 2. Avoid reliance on external features like script tags or mime types.
> (Not all JS is on web pages anyway!)
Just to be clear, the RFC4329 version parameter was never proposed as
sufficient. It or something equivalent in the script type attribute is
necessary on the web to hide new script from old browsers.
> 3. Provide as many incentives for switching to ES6 as possible.
This is a job for ES6 itself, not just its opt-in system.
> 4. Minimize necessary changes in programming style.
Taken one way, this excludes new semantics, since people have to build
everything today using objects and closures. Making a virtue of
necessity could kill almost any proposal (destructuring, generators,
modules -- even let).
It's not clear how listing several variables to minimize helps if we
don't have a trade-off formula against opportunity costs and cost of
building everything more or less in today's style.
> 5. Minimize ES5-ES6 transitioning pitfalls.
Five fingers of fate. Only one used right now.
> 6. Avoid maintenance or refactoring pitfalls in ES6 itself. Avoid that
> ES6 programmers have to think about modes or feature sets at all.
> (This particularly should apply to non-savvy programmers!)
Amen -- this is the impetus for the "scary" discussion.
> 7. Minimize semantic complications (which tend to harm both
> implementations and programmers).
The Harmony page talks about doing this by desugaring where possible,
extending kernel semantics only where necessary and with primitives that
This implies that a new, consolidated Harmony-era spec must define how
extended semantics interact with strict semantics at least. But we may
have assumed that we didn't need to define interactions with non-strict
semantics. That raises the question of opt-in before us.
My point is that *if* opt-in usability demands defining extended vs.
non-strict complications, then so be it. We should take the hit. Again
minimizing all of 4 or 7 variables is impossible. There are trade-offs.
Judging them well is an art and it does depend on usability in the large
(your goals 1 and 6 may well trump 7).
> 8. Obviously, achieve full backwards compatibility.
We've considered marginally breaking changes, e.g. completion reform. We
should discuss this one more if necessary.
> The various proposals in the thread were primarily aimed at (1), but
> AFAICS all fail on (6), to different extent. (There were mixed results
> for the other points.)
Agree that 1 vs. 6 is the fight to focus on here.
> Consequently, programmers would have to be
> aware which features put them into ES6 (and thus strict mode), and
> which are only available there, and that local changes could subtly
> change the meaning of unrelated program parts (due to strict mode), or
> even the whole program. Moving code could subtly change its internal
You made some good points already in the thread against this, phrased in
terms of those strict-vs.non-strict semantic shifts (eval of var,
arguments aliasing, a few others -- not terribly many). I'm happy to
concede (I thought I did already) that was a mortal blow to "tainting"
implicit opt-in where a Harmony feature at the last line of 60,000 would
put the whole large program in strict mode.
Let's agree on this if we can (Allen may not).
> It's also worth noting that backporting
That is a loaded verb-form ("backporting"). Who says there is a separate
older spec or implementation to which to port?
Yes, analyzing interactions requires reading the ES5 spec in non-strict
mode. No, the result is not necessarily a port -- it's a patch (if you
insist on hacking metaphors).
> new ES6 features to classic
> mode, as has been proposed by several people, clearly works against
I object. 3 is misstated to assume "switching" means all-or-nothing. If
ES6 has new features and they are worth using, developers will want to
use them piecewise and conveniently. Assuming they will do so at the
price of a leading "use version 6" or equivalent pragma is debatable. We
shouldn't just assume this conclusion.
I think 3 should be stated as "Provide as many incentives for using ES6
as possible". Here "using" does not demote making use of every last
feature in every script. There's no need to require "switching" and it
may be user-hostile to do so.
> and consequently, also against (5/6).
This does not follow. Users transitioning to use new features may be
helped, not hindered, by we spec and implementation editors working
harder. In particular allowing, e.g., destructuring in non-strict code
may be boon to developers, whereas requiring them to maintain explicit
opt-in pragmas before doing so simply to convenience spec editors and
implementors may be a global loss.
The game theory is multi-party and the moral hazard for us as spec and
implementation people is to optimize for our own convenience or assert
that it's identical to developer usability. It's not.
> Similarly, opting in at
> smaller scope, as has also been discussed, is a blatant violation of
> (6) and (7), and works against (3), too.
Let's agree, based on your earlier arguments and also on Dave's point
that lexical scope (free variable error analysis) won't work if opt-in
is too local. This still does not mean that all extensions must be
supported only under all-or-nothing early opt-in.
> So I have plea: let's keep it simple. Start from the simplest of all
> possible ideas and optimize from there. That is, opting into ES6
> through one simple declaration on the top of a program (and nowhere
> else). Otherwise it's ES5 unchanged.
You are arguing based on "simplest" without considering real-world
usability. Too much a-priori system building makes a crashed sky castle,
I've seen this over and over. On the web, a-posteriori wins.
On the web, people lose version opt-in pragmas and MIME type versions
(Larry Masinter made this point about the latter but it applies to the
former). On the web, we have "use strict"; in the middle of
concatenations. We have Unicode BOMs in the middle. We have
<!-- hide script from old browsers
in the middle of .js files!
No plan survives contact with the enemy (Moltke) comes to mind.
Meanwhile, JS1 grew via ES1-5 and various implementations (SpiderMonkey
and Rhino) without any such opt-in, *except* for two keywords we
couldn't reserve (and some incompatible change attempts that failed, vs.
goal 8 -- one example: I tried to make == and != strict in JS1.2 to get
ES1 to switch, but that broke the web, wherefore === and !==).
> As far as I can see, that clearly
> wins, or is no worse than other proposals, on anything but (1).
I'm sure it wins for spec authors and implementors -- forking large
parts of the spec might even "win" in the short term. These would all be
bad for users, IMHO.
> Compared to Dave's original proposal, the only scenario on which it
> loses re (1) is if the program already consists of a module, in which
> case you'd still have to write the opt-in declaration. One can
> probably argue whether this is worth adding an extra rule (personally,
> I don't think so).
So I'd have to write
use version 6;
instead of just
even though there's no backward compatibility issue? That's just mean! :-|
> If so, it would be enough to say that a module
> declaration as the _first_ statement in the program also opts in _all_
> of the program.
Why first if (as Dave's proposal in its minimal form did) a later module
cannot affect earlier non-strict top level semantics? Again there is no
backward compatibility issue. Why, as spec writer or implementor, do you
care whether it's
// non-strict top level code
or the concatenation?
// non-strict top level code
Nothing in the spec or an optimizing implementation, if we assume module
M is its own opt-in such that ... is in ES6, should care when processing
the non-strict top level code.
> In either case:
> 1. You always opt in all of the program consistently.
> 2. It is obvious from the first line that you do.
First lines get lost or moved down all the time.
Making this an early error helps only assuming diligent testing in new
implementations. That's not safe to assume.
> 3. This truly opts-in the toplevel (for whatever that means in detail).
> 4. A future ES programmer just needs to know one rule: start your
> program with _____.
> (I'm intentionally avoiding bike-shedding a concrete syntax for ____
Yeah, it's ok -- but let's not keep cleaning the slate. We have RFC4329
and browsers do hide new version= values. We have a proposal lurking
about for "use version 6". Avoiding bikeshedding is one thing, avoiding
usability testing and assuming the first-line selector wins is not
> And before somebody brings it up: I do not fear that this will share
> the fate of strict mode, because there actually is plenty of incentive
> for using ES6 (especially, if we do _not_ extend classic mode).
Another assumption. There may be more carrots this time, but if the
explicit opt-in requirement is too unusable in practice, then ES6 may
bounce, or simply have slower adoption that we'd like, ceteris paribus
(many variables here, hard to project -- let's avoid arguing based on
our favored speculations).
My non-speculative argument rests on experience on the web. Version
marks and other separators are mangled and lost all the time.
I believe we should offer well-defined <script type=...;version=...>
opt-in for script content hiding from old UAs, and *in addition*
belt-and-braces in-script-content version opt-in at a minimum, via some
pragma such as |use version 6;|.
But I also believe these will be lost or simply not used, and adoption
will be better if we define sensible (per your arguments against
tainting from small to large extent) new-syntax-is-its-own-opt-in rules,
per Dave's o.p.
The reason I believe this is our experience in past edition shifts and
experimental extensions. Usability wins should tax spec-editors (if not
implementors -- let's not assume the implementation costs of implicit
opt-in are too high [*]) for the greater good of the JS developers.
[*] SpiderMonkey has no runtime tests based on <script type="...;
version=X"> values, if I'm not mistaken, and very few compile-time. And
this is with quite a few extensions, including standard ones such as
E4X. Yes, we learned some lessons at non-trivial cost, but these need
not be re-learned from scratch by TC39.
-------------- next part --------------
An HTML attachment was scrubbed...
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 770 bytes
Desc: not available
More information about the es-discuss