While I like the idea of not having multiple versions of ES very much,
I fear that this proposal comes with a danger similar to the problems
people have with concatenated source files and the "use strict"
pragma. While modules nicely solve the problem of tools doing the
wrong thing during some build and optimization process, I'm afraid
that an implicit opt-in comes with a huge complexity budget for users.

Current ES users can be told "these are the new features of ES6 that
you can only use in modules". For the next generation of users, the
story will sound more like "you have to be very careful about where
you put what code. Depending on which source file you put a function
in, its behavior can vary wildly."

In essence, users would have to keep in mind that there are two
contexts in which to write ES, what the differences are between those,
and what exactly is allowed in which of them.

Granted: the outcome could very well be that the next generation of ES
programmers get taught "put all your code in modules, always" before
their first "hello, world". If so: great. But maybe it goes wrong and
instead they are taught "there are these newfangled features which
only work some of the time and if you move them into the wrong file,
they stop working, so just forget about them".

Essentially, I'm afraid that an implicit opt-in could turn out to be
an impediment to ES6's adoption instead of easing its path.


till

On Sun, Jan 1, 2012 at 02:46, David Herman <dher...@mozilla.com> wrote:
> Happy new year, everyone. I've got some good news.
>
> There's been grumbling lately about the ES6 version opt-in [1]. The 
> detractors are not right about everything, but it's true that both the MIME 
> type opt-in:
>
>    <script type="application/ecmascript;version=6">
>        ...
>    </script>
>
> and the pragma opt-in:
>
>    use version 6;
>
> are painful -- ugly, verbose, and a permanent tax for opting to use the new 
> semantics.
>
> We can do better, and the way we can do it is with modules. We can introduce 
> module syntax in a backwards-compatible way, and use them as the implicit 
> opt-in for any new semantics [2].
>
> And the benefit we get is **just one JavaScript**.
>
> # Backwards-compatible syntax
>
> Both `use` and `module` can be contextual keywords, with a restricted 
> production that disallows a newline after the keyword. To avoid ambiguity 
> with contextual infix operators like `is` and `isnt` [3], such as:
>
>    module is {}
>
> we can resolve in favor of the declaration form in statement context, and in 
> any other expression contexts `module` is just an ordinary identifier.
>
> This is totally backwards-compatible: all the new forms would have been parse 
> errors in ES5:
>
>    module foo { }
>    module bar {
>    }
>    module {
>    }
>
> and in all cases that ASI accepts in ES5, it continues to parse the same, 
> i.e., not as a module:
>
>    module // semicolon inserted
>    foo    // semicolon inserted
>
> # Modules as the opt-in for new semantics
>
> Any ES6 feature that breaks web-compatibility can be made available only 
> within module code. For example, if `let` as a keyword breaks the web, then 
> in global code we treat it as an identifier, but we treat it as a keyword 
> once you're inside a module. Similarly, the proper but backwards-incompatible 
> scoping semantics for block-local functions would only be enabled within 
> module code.
>
> We could do the same for `yield`, but since it's only meaningful within 
> function*, we should allow generator functions outside of modules as well. 
> I'm not sure whether we can/should reserve `yield` as a keyword in global 
> code.
>
> Each new feature can be considered independently. Anything that is only 
> allowed within modules becomes a carrot to lead programmers to the improved 
> semantics, but whenever we can compatibly make something available to global 
> code, we should do so. No point needlessly depriving programmers of ES6 
> goodies such as destructuring or spread/rest.
>
> # What about eliminating the window from the scope chain?
>
> Short answer: giving up.
>
> You can still do it with a custom loader, and I still want to push on new 
> HTML <meta> conveniences for specifying a custom loader to use for the 
> remainder of the program. In that context you could create a loader with a 
> nice, clean global scope.
>
> # But then what about static scoping?
>
> Compile-time checking of variables is a really important goal, and we don't 
> have to abandon it. We just do the checking only within module code, relative 
> to the current contents of the global object. This means it's still 
> technically possible for globals to disappear at runtime (and consequently 
> throw errors).
>
> But this doesn't bother me. First of all, variable errors due to dynamic 
> deletion of globals are not the common case. Second, you can avoid globals 
> entirely by strictly importing from modules. Finally, you can easily create 
> loaders with frozen global objects. An environment like SES might choose to 
> do this. But we retain compatibility in the default browser context.
>
> If you ask me, this compromise is **totally** worth it.
>
> # Anonymous modules as a simple way of opting in
>
> A common pattern on the web is to protect yourself against creating 
> unnecessary globals is to wrap top-level code in an IIFE:
>
>    (function() {
>        /* program goes here */
>    })();
>
> By allowing anonymous modules, we simultaneously make this more idiomatic and 
> implicitly opt in to all the goodies of ES6:
>
>    module {
>        /* program goes here */
>    }
>
> Kills two birds with one stone!
>
> # Avoiding rightward drift
>
> Still, whether you use an IIFE or an anonymous module, the extra rightward 
> drift (requiring an initial level of indentation around the entire program 
> body) is annoying. A simple pragma takes care of that:
>
>    // equivalent to wrapping program in module { ... }
>    use module;
>
> This is not strictly necessary but avoiding an extra level indentation in 
> every single program is a big win when you multiply it over every program 
> ever written, and some editors will fight you if you try not to indent within 
> curlies. But notice that even though this is a kind of opt-in pragma, it 
> still is strictly *less* code than you have to write today with an IIFE -- 
> kills two birds with a smaller stone than ES5 requires to kill one.
>
> # Summing up
>
> We can make ES6 100% backwards-compatible, using modules to opt in to 
> backwards-incompatible changes. It replaces the notion of a new language 
> "mode" with the simple syntactic characteristic of whether the code is in a 
> module. And you can now mix old code and new code freely, even within the 
> same <script> tag or source file.
>
> One final note: the "...;version=6" MIME-type could be used to hide ES6 
> scripts from downrev browsers. So it may still have a place, but not for 
> opting in to new semantics.
>
> Dave
>
> [1] https://plus.google.com/112284435661490019880/posts/6W7ErmRC1XN
>
> [2] We can't be future-compatible, as some have hoped to accomplish with 
> HTML, except maybe with macros. We'll get there if/when we can.
>
> [3] http://wiki.ecmascript.org/doku.php?id=harmony:egal#is_and_isnt_operators
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to