apache / royale-asjs

Apache Royale ASJS
Apache License 2.0
372 stars 116 forks source link

(Feature Request) Use ES6 modules #247

Open jgranick opened 6 years ago

jgranick commented 6 years ago

The EcmaScript 2015 standard (ES6) introduced a module system, that allows for multiple JavaScript files to import from one another and build complex applications.

The latest version of most browsers support ES6 syntax, and even support using these modules without a compiler.

The first library we used for bundling modules in the NPM release of OpenFL was browserify, but circular references resulted in needing to remove features from the library. ES6 modules have better handling of cyclic dependencies, depending on the implementation. We use Webpack, and have no circular dependency issues. Being compatible with modern JavaScript toolchains also opens up a wide world of ways to mix/match/interact/expand on the codebase.

If Royale supported ES module output, we would gain support for using SWF assets, for granular code splitting, for many, many features "for free" from the NPM community, and make the cost of integrating ActionScript-based sources much lower in an NPM-based project.

aharui commented 6 years ago

The compiler's -compiler.targets option lets you pick different ways of outputting JS. Under the hood, the compiler essentially uses different classes called Emitters that take AST nodes and generate JS. If you have the resources to write an ES6 Emitter for the Royale Compiler, we will provide advice and other support. You don't have to know much about compilers to write an Emitter. The Emitter is essentially being called as part of the AST tree node walk.

jgranick commented 6 years ago

How do we learn what options are supported by the compiler? Are there currently multiple targets supported? Where is the source code to the existing Emitter(s)? :smile:

aharui commented 6 years ago

I just fixed the transpiler listing out its options. So try the latest nightly builds. It could probably use more verbose doc though.

Multiple targets are supported. By default we compile both JSRoyale and SWF. JSRoyale is ES5Strict with Royale patterns for getters/setters and some other options. I think you have used both to create your SWC. When we get around to ES6 output, we'd probably add a new target like JSRoyaleES6.

The Emitters are in: the compiler-jx folder in packages like org.apache.royale.compiler.internal.codegen.js.royale. The JSRoyaleEmitter is the one used for JSRoyale target.

aharui commented 6 years ago

I wrote up a bit more about the compiler code base here: https://github.com/apache/royale-compiler/wiki/Developer-Guide

carlosrovira commented 6 years ago

Thanks Alex, I think this is very important so people can get their hands dirty with the code, and make the compiler less a black box. Thanks for doing this :)

aharui commented 6 years ago

What module system does NodeJS use? I saw support for that module system in the compiler.

jgranick commented 6 years ago

NodeJS uses CommonJS, like var MyModule = require ("my/Module");

If we could emit CommonJS output, that could (potentially) help largely for running things through Webpack and integrated with other libraries. Part of the trick, though, would be allowing for adding the correct require meta-data to an ActionScript 3.0 extern or ordinary class. I believe there's "js module" tag that's supported by the compiler right now, but it didn't sanitize values properly. For example:

[JSModule(name="path/to/MyModule")]

...generated

var path/to/MyModule = require ("path/to/MyModule");

So there might be some work needed there

aharui commented 6 years ago

Sorry for the delay. I was hoping @joshtynjala would notice this thread and answer your questions. I haven't tried it myself, but there is an examples/node/HelloWorld that supposedly uses this output type.

joshtynjala commented 6 years ago

I added support for loading CommonJS modules using require(). I focused only on supporting named modules with require() and [JSModule]. If you wanted to load modules using paths too, you'd need to modify the compiler to add that.