Experimental ES6-to-ES3 transpilation -- try it out! :)

2,875 views
Skip to first unread message

Tyler Breisacher

unread,
Aug 22, 2014, 6:56:42 PM8/22/14
to closure-comp...@googlegroups.com
As you may have noticed, we've been working hard on ES6-to-ES3 conversion in the compiler. While we're not quite done yet, we're far enough along that we'd like people to start trying it out and filing bugs. Note that we don't support all ES6 features, nor do we plan to. See https://github.com/google/closure-compiler/wiki/ECMAScript6

If you're already using the Closure compiler and you've been wanting to try out some ES6 features, this is your chance! Or, if you have JS projects that already use ES6 features, and you've been transpiling with another tool, such as the Traceur compiler, you can try compiling with the Closure compiler instead and see if it works for you.

To transpile ES6 to ES3, add --language_in=ECMASCRIPT6_STRICT (or --language_in=ECMASCRIPT6 if you need to use strict-mode-incompatible code) and --language_out=ECMASCRIPT3 to your compiler commandline.

There's a lot of good ES6 info out there. http://es6rocks.com/ or https://github.com/lukehoban/es6features are probably good places to start.

Our ES6 support is still experimental, so please help us improve it by reporting any strangeness you see, on this mailing list, or by filing a bug at https://github.com/google/closure-compiler/issues

Nate

unread,
Aug 22, 2014, 11:08:16 PM8/22/14
to closure-comp...@googlegroups.com
 
I couldn't find the javascript for modules (goog.loadModule, goog.module, etc). Is a library update required to test this?

Thanks

Tyler Breisacher

unread,
Aug 23, 2014, 4:24:03 PM8/23/14
to closure-comp...@googlegroups.com
Yeah, I think there are several changes in the Closure Library (which is pushed to Github separately from the compiler) which have not been pushed to Github yet but it should happen soon and I'll try to remember to update this thread when it does (or you can just "watch" that project on Github). I put modules in the "will be supported soon" list because of that, and because it seems the committee may slightly change the syntax of modules in the specification over the next few months.


--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/closure-compiler-discuss/6afbb668-e6ba-4df5-821f-390358b98c89%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daniel Steigerwald

unread,
Aug 23, 2014, 5:38:33 PM8/23/14
to closure-comp...@googlegroups.com
So, and correct me If I'm wrong please , does it mean that we have to develop out app in compiled mode only? One thing I like on Closure Library is, that I don't have compile anything during development.

Tyler Breisacher

unread,
Aug 23, 2014, 6:02:20 PM8/23/14
to closure-comp...@googlegroups.com
If you use ES6 features in your code, then you either need a browser that supports those features (http://kangax.github.io/compat-table/es6/ is generally kept pretty up to date so you can see who supports which features) or some kind of transpiler (whether it's Traceur, Closure, or something else).

Or you can do a combination of those, e.g. only use features that are implemented in Firefox 34, and run the code uncompiled in that browser for development, but then serve the transpiled code to your users so that your app will work in all browsers.


--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.

mario....@gmail.com

unread,
Aug 24, 2014, 9:56:48 AM8/24/14
to closure-comp...@googlegroups.com
Nice. I haven't tested it yet... But maybe a es6 module loader polyfill could help for the older browsers?
https://github.com/ModuleLoader/es6-module-loader

pw.r...@gmail.com

unread,
Jan 7, 2015, 7:58:48 AM1/7/15
to closure-comp...@googlegroups.com
On Saturday, 23 August 2014 21:24:03 UTC+1, Tyler Breisacher wrote:
Yeah, I think there are several changes in the Closure Library (which is pushed to Github separately from the compiler) which have not been pushed to Github yet but it should happen soon and I'll try to remember to update this thread when it does (or you can just "watch" that project on Github). I put modules in the "will be supported soon" list because of that, and because it seems the committee may slightly change the syntax of modules in the specification over the next few months.

what does 'support for modules' mean here? I've just tried compiling some very simple ES6 modules, such as:

  export default var x = 'x';

or

  import x from 'x';
  console.log(x);

or the somewhat more complex examples at http://jsmodules.io/ But I always get 'Invalid attempt to remove node'. If the compiler at the moment is simply transpiling ES6 to ES3/5, what's it trying to transpile modules to? If it's trying to convert to the new goog.module, how does that work if you're not using Closure library?

Tyler Breisacher

unread,
Jan 8, 2015, 1:04:02 PM1/8/15
to closure-comp...@googlegroups.com
It actually converts to goog.require/provide, currently, though we may change that. Unfortunately, while the compiler support for modules is (or was) working, there are various other tools within Google that need to be updated, which has stopped us from using modules very much. So for you to try it out as a non-Googler is very much appreciated! I will look into the issues and improve our test coverage. So, thanks!


Are you on an older version of the compiler perhaps?

Tyler

--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.

pw.r...@gmail.com

unread,
Jan 8, 2015, 1:37:04 PM1/8/15
to closure-comp...@googlegroups.com
I'm using the latest release zip

Version: v20141215
Built on: 2014/12/17 09:05

java version "1.7.0_55"

here's the complete error report, which occurs with all import/export commands

------------------
java -jar compiler.jar --language_in=ECMASCRIPT6 --language_out=ECMASCRIPT5 compilertest.js                                                                                                               
compilertest.js:17: WARNING - unreachable code
import x from 'x';
       ^
0 error(s), 1 warning(s)
java.lang.RuntimeException: INTERNAL COMPILER ERROR.
Please report this problem.

INTERNAL COMPILER ERROR.
Please report this problem.

Invalid attempt to remove node: NAME x 17 [source_file: compilertest.js] of IMPORT 17 [source_file: compilertest.js]
  Node(NAME x): compilertest.js:17:7
import x from 'x';
  Parent(IMPORT): compilertest.js:17:0
import x from 'x';

        at com.google.javascript.jscomp.NodeUtil.removeChild(NodeUtil.java:2181)
        at com.google.javascript.jscomp.UnreachableCodeElimination$EliminationPass.removeNode(UnreachableCodeElimination.java:261)
        at com.google.javascript.jscomp.UnreachableCodeElimination$EliminationPass.removeDeadExprStatementSafely(UnreachableCodeElimination.java:251)
        at com.google.javascript.jscomp.UnreachableCodeElimination$EliminationPass.visit(UnreachableCodeElimination.java:104)
        at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:588)
        at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:582)
        at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:582)
        at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:582)
        at com.google.javascript.jscomp.NodeTraversal.traverse(NodeTraversal.java:291)
        at com.google.javascript.jscomp.NodeTraversal.traverse(NodeTraversal.java:540)
        at com.google.javascript.jscomp.UnreachableCodeElimination$1.visit(UnreachableCodeElimination.java:81)
        at com.google.javascript.jscomp.NodeTraversal$1.shouldTraverse(NodeTraversal.java:526)
        at com.google.javascript.jscomp.NodeTraversal.traverseBranch(NodeTraversal.java:569)
        at com.google.javascript.jscomp.NodeTraversal.traverse(NodeTraversal.java:291)
        at com.google.javascript.jscomp.NodeTraversal.traverseChangedFunctions(NodeTraversal.java:531)
        at com.google.javascript.jscomp.UnreachableCodeElimination.process(UnreachableCodeElimination.java:66)
        at com.google.javascript.jscomp.PhaseOptimizer$NamedPass.process(PhaseOptimizer.java:285)
        at com.google.javascript.jscomp.PhaseOptimizer$Loop.process(PhaseOptimizer.java:453)
        at com.google.javascript.jscomp.PhaseOptimizer.process(PhaseOptimizer.java:217)
        at com.google.javascript.jscomp.Compiler.optimize(Compiler.java:1974)
        at com.google.javascript.jscomp.Compiler.compileInternal(Compiler.java:769)
        at com.google.javascript.jscomp.Compiler.access$000(Compiler.java:94)
        at com.google.javascript.jscomp.Compiler$3.call(Compiler.java:655)
        at com.google.javascript.jscomp.Compiler$3.call(Compiler.java:652)
        at com.google.javascript.jscomp.Compiler$4.call(Compiler.java:699)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.RuntimeException: INTERNAL COMPILER ERROR.
Please report this problem.

Invalid attempt to remove node: NAME x 17 [source_file: compilertest.js] of IMPORT 17 [source_file: compilertest.js]
  Node(NAME x): compilertest.js:17:7
import x from 'x';
  Parent(IMPORT): compilertest.js:17:0
import x from 'x';

        ... 29 more
Caused by: java.lang.IllegalStateException: Invalid attempt to remove node: NAME x 17 [source_file: compilertest.js] of IMPORT 17 [source_file: compilertest.js]
        ... 29 more
----------------------

Tyler Breisacher

unread,
Jan 8, 2015, 2:11:16 PM1/8/15
to closure-comp...@googlegroups.com
You'll also need the --rewrite_es6_modules flag. I don't recall why we made that a separate flag, instead of having it be implied by the language_in/language_out flags, just like all other ES6 features.

--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.

pw.r...@gmail.com

unread,
Jan 8, 2015, 4:29:47 PM1/8/15
to closure-comp...@googlegroups.com
On Thursday, 8 January 2015 19:11:16 UTC, Tyler Breisacher wrote:
You'll also need the --rewrite_es6_modules flag. I don't recall why we made that a separate flag, instead of having it be implied by the language_in/language_out flags, just like all other ES6 features.

ah, right. I was wondering what that flag was for :-)
ok, next issue. 2 simple modules, x.js says:

  var x = 2;
  export default x;

This compiles ok. y.js says:

  import x from 'x';
  var y = x * 2;
  export default y;

If I try and compile that, it tells me 'required "module$x" namespace never provided'. The x compile creates a module$x var, but that's purely internal to x.js and isn't relevant to y - it just has to import what x exports. Or am I missing something?

Tyler Breisacher

unread,
Jan 8, 2015, 5:19:22 PM1/8/15
to closure-comp...@googlegroups.com
Hm, I can't seem to repro this.

$ cat x.js 
  var x = 2;
  export default x;
$ cat y.js 
  import x from 'x';
  var y = x * 2;
  export default y;
$ ant jar && java -jar build/compiler.jar --language_in=ES6 --language_out=ES5 --rewrite_es6_modules --js=x.js --js=y.js
<logging from Ant...>
var x$$module$x=2,$jscompDefaultExport$$module$x=x$$module$x,module$x={};module$x.default=$jscompDefaultExport$$module$x;var y$$module$y=2*module$x.default,$jscompDefaultExport$$module$y=y$$module$y,module$y={};module$y.default=$jscompDefaultExport$$module$y;

This is at the current HEAD (b9a434) and I get the same result with the 12/17 release.

--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.

pw.r...@gmail.com

unread,
Jan 8, 2015, 6:20:58 PM1/8/15
to closure-comp...@googlegroups.com
On Thursday, 8 January 2015 22:19:22 UTC, Tyler Breisacher wrote:
Hm, I can't seem to repro this.

$ cat x.js 
  var x = 2;
  export default x;
$ cat y.js 
  import x from 'x';
  var y = x * 2;
  export default y;
$ ant jar && java -jar build/compiler.jar --language_in=ES6 --language_out=ES5 --rewrite_es6_modules --js=x.js --js=y.js
<logging from Ant...>
var x$$module$x=2,$jscompDefaultExport$$module$x=x$$module$x,module$x={};module$x.default=$jscompDefaultExport$$module$x;var y$$module$y=2*module$x.default,$jscompDefaultExport$$module$y=y$$module$y,module$y={};module$y.default=$jscompDefaultExport$$module$y;

I'm compiling them separately, not together. My assumption would be that modules are independent entities loadable independently, and therefore would be compiled/optimized separately too. If you take a more realistic example, say, where x and y are classes, y might import x, but you wouldn't necessarily always want to use/load them together, so you wouldn't want them in one file.

Tyler Breisacher

unread,
Jan 8, 2015, 6:24:21 PM1/8/15
to closure-comp...@googlegroups.com
I don't think we have a mode where you can compile a single ES6 module in isolation, though perhaps we should.

--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.

pw.r...@gmail.com

unread,
Jan 9, 2015, 7:06:43 AM1/9/15
to closure-comp...@googlegroups.com
On Thursday, 8 January 2015 23:24:21 UTC, Tyler Breisacher wrote:
I don't think we have a mode where you can compile a single ES6 module in isolation, though perhaps we should

I think there's 2 different scenarios here, depending on whether you want to bundle modules together. If you're bundling a lot of files together, say a library, then you probably don't want to export all the exports from all the modules, but have a separate set of exports for the bundle; the individual module exports can be minified away. However, if you're importing someone else's module to use in yours, or if, for example, you load different modules depending on the environment, then they can't be bundled together. Take Traceur's example at https://github.com/google/traceur-compiler/wiki/LanguageFeatures#modules - which Profile you load will vary, though the exported/imported var names are the same. As I see it, the compiler needs to keep the import and export statements as is, but can minify any other module-internal logic as usual, for example, the setHeader function in ProfileView.

If I expand on my previous example:

  var minifiable = 2;
  var exported = minifiable * 2;
  export default exported;

then 'exported' cannot be compressed (the equivalent of goog.exportProperty), but 'minifiable' can, so I would expect the compiler output to be something like:

  var a=2;var exported=a*2;export default exported;

or even:

  var exported=2*2;export default exported;

However, if I compile this, I get:

var minifiable$$module$x=2,exported$$module$x=2*minifiable$$module$x,$jscompDefaultExport$$module$x=exported$$module$x,module$x={};module$x.default=$jscompDefaultExport$$module$x;

Not only is it not compressing 'minifiable', but the output is far larger than the input, and in addition it's not clear to me what I'm supposed to do with this file. Ok, I appreciate we're in a transition period at the moment, as no browser currently implements a module loader (later this year perhaps?). So I'm not sure what it should be doing with the 'export' statements. It's a while since I used Traceur, but as I recall it wraps modules in AMD-style functions, so, to use/import this output in another module, I could use output_wrapper to add an AMD function, but the whole thing doesn't seem very user-friendly to me.
Reply all
Reply to author
Forward
0 new messages