Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Feature Request) Support for JS extern output with royale-js #232

Closed
jgranick opened this issue May 14, 2018 · 10 comments
Closed

(Feature Request) Support for JS extern output with royale-js #232

jgranick opened this issue May 14, 2018 · 10 comments

Comments

@jgranick
Copy link

This is probably a known issue, but it would be awesome if we could use the (much cleaner) royale-js package for generating extern SWC files for use with Apache Royale. Another option (if possible) would be to allow support for @externs classes without putting them in the final output, avoiding the need for SWCs. Using royale-js, attempting to generate an SWC results in either a warning about missing the Object built-in, or generates no output.

In order to generate SWC externs during the build of a JavaScript library, we would like to be able to use a minimal package that does not require the full Adobe AIR SDK.

@jgranick jgranick changed the title (Feature Request) Support for JS externs with royale-js (Feature Request) Support for JS extern output with royale-js May 14, 2018
@aharui
Copy link
Contributor

aharui commented May 14, 2018

Do you have test cases so we can make sure we understand what you are looking for? I don't think we have any examples, but I think if you want to build a SWC that never supports SWF output you can do so without requiring Adobe AIR SDK.

You can define @externs in ActionScript. I'm not sure if they will work outside a SWC just in the source-path, but if you set up a test case for that we can see how hard it would be to make it work. Here's an example of an @externs in AS: https://github.com/apache/royale-tourjs/blob/develop/cordova/BatchScanner/barcodeScanner/src/main/flex/cordova/plugins/barcodeScanner.as

Thanks,
Alex

@jgranick
Copy link
Author

Sure thing! 😄

Here's a quick sample:

https://github.com/jgranick/MinimalSWCTest

I tried this before using "js" as the target, but I think letting the target remain the default ("royale") is probably what would (ideally) work. We want to take these source files, and pack them into an SWC for code completion later. Using royale-js, this outputs nothing, where it does generate an SWC with royale-js-swf

@jgranick
Copy link
Author

For the second case, here's a little sample. It's using one class path, but in our case we'd expect instead to add another include path (pointing to node_modules/openfl/lib for example)

https://github.com/jgranick/MinimalASExternTest

Using the real AS externs we're creating, it did compile, but it generated JavaScript files for each of our externs. It worked at runtime because we imported a global "openfl.js" which override the references previously defined in the Royale-generated JavaScript, but in the above test, it does not fully compile. Either way, it would be nice to be able to (have the option to) compile pointing at "@externs" marked AS sources rather than packing in an SWC 😄

@aharui
Copy link
Contributor

aharui commented May 15, 2018

To create a SWC without needing AIR SDK, this should work (worked for me):

compc -load-config=<path to Royale SDK>/frameworks/js-config.xml -include-sources=src -compiler.targets=SWF,JSRoyale -output=<desired path and name of SWC>

One unexpected parameter is needing the SWF compiler.target. SWCs must have a SWF with the ABC for the API surfaces so you can compile against them in other projects.

@aharui
Copy link
Contributor

aharui commented May 15, 2018

Regarding the second case: At some point, the .AS file needs to be cross-compiled to a .JS file to be fed as an "@externs" to the Google Closure Compiler. I'm not clear when you want that to happen.

@jgranick
Copy link
Author

Great! Thank you, I appreciate the help. Using royale-js really is better than royale-js-swf for generating a lib extern SWC.

Here's the command that's working for me (similar to the one shared):

compc -load-config=node_modules/@apache-royale/royale-js/royale-asjs/frameworks/js-config.xml -keep-as3-metadata=JSModule -include-sources=lib -compiler.targets=SWF -output=dist/openfl.swc

Regarding the second, I must have misunderstand. Haxe does not generate JavaScript for extern classes, it means "please don't generate this, it exists at runtime." Perhaps I misunderstood what was happening

:shipit:

@aharui
Copy link
Contributor

aharui commented May 16, 2018

You are correct that an extern represents code that exists at runtime. However, in Royale, the fact that some code is going to be supplied at runtime is only important to the Google Closure Compiler that optimizes the final set of JS. The extern in AS helped the compiler resolve the APIs you used, but we still need to convert it to the format that Google expects which is essentially a JS file.

Since it probably doesn't make sense for consumers of your library to have the AS extern compiled to JS on every compile, it is probably better to transpile the AS to JS and package both into a SWC so the AS remains paired with its transpiled JS counterpart.

I was thinking you wanted to make development of the AS extern easier by skipping the creating of the SWC and paying the price of the transpile on each compile until your errors go away and then you can put it all in a SWC. If you want to make sure that workflow is valid I will look into it.

@jgranick
Copy link
Author

Yeah, I think it makes sense to allow both, for example, allowing "node_modules/openfl/lib" as a source path vs. "node_modules/openfl/dist/openfl.swc" as an external library path, is similar to how we allow ES6/TypeScript developers to either use require (which comes from "lib" as separate modules) or to require/import a precompiled "openfl.js" or "openfl.min.js" which comes from "dist".

I apologize in advance for fitting a couple new questions within this one issue, but I have a couple questions that are somewhat related that I could not find documentation about.

After my SWC created, where do I put my source files? Can I give a compiler argument to specify where external JS files are located? Can I use require instead of using window references? Can this work with CommonJS-style modules (var openfl_display_Sprite = require ("../path/openfl/display/Sprite").default)? Is there a way to avoid using "bin/js-debug" and "bin/js-release" (to customize the output directory)? Warnings about public variables and minification prints as a warning, but seems to emit an error code and stop my compilation. Can I ignore this warning, or do something automatic to "keep" a variable?

Thank you

@aharui
Copy link
Contributor

aharui commented May 18, 2018

A SWC is a package of pre-compiled AS. So once you distribute it, your AS source files are no longer needed to compile and run. Inside the SWC (it is a ZIP so just unzip it to see what is in it) is a SWF containing the compiled AS as ActionScript Byte Code, and the transpiled JS files.

You can deliver just JS files and point to them with the -sdk-js-lib=.
You can specify more than one -sdk-js-lib option.

Set -warn-public-vars=false to suppress warnings about public vars. I'm surprised it generates an error code. There is a way to turn off the warning per declaration in the source files.

There is no current compiler option to change the js-debug/js-release folder names. You should be able to set where those two folders go with the -output= option.

I'm not familiar enough with CommonJS modules to know how to answer the 'require' vs 'window' question so I have some questions for you instead. Do you want to have the Google Closure Compiler process your output? Especially to minify/optimize it? Because that will require being careful about public vars. And as I'm looking into your bug #234 I ran into an issue where our compiler currently doesn't handle output where a class extends an @extern class. So far, all of the @externs we've used are just APIs to be called, not extended. Currently, our output is tuned to what Google Closure Compiler wants, but the compiler was designed to allow the output to be swapped to generate something else. We/you might want to write what we call an Emitter that outputs CommonJS-style JS.

@aharui
Copy link
Contributor

aharui commented Jun 7, 2018

I recently pushed changes to allow use of @externs in the source-path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants