incubator-flex-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Frank Wienberg <fr...@jangaroo.net>
Subject [FalconJx] New JavaScript runtime format prototype
Date Thu, 20 Dec 2012 17:30:07 GMT
Hi folks,

as mentioned in another thread, I have been working on a new JavaScript
"runtime", which is what I call the way the generated JavaScript code looks
and works like. While this thread's title has [FalconJx] in it, there is no
reason the proposal could not be used for FalconJS, too, but I understood
that for now, using Google Closure is a given.

I had the following design goals:

   - Support ActionScript 3's "differentiator" features: private members,
   interfaces + is/as, lazy class initialization, method binding,
   getter/setter functions
   - work in IE < 9 (except for getter/setter functions)
   - Produce debuggable JavaScript code that can also be optimized for
   deployment. The debuggable code should be very similar to the original
   ActionScript source code for every line containing executable code
   - Dependency management: load/bundle only the needed classes. Every
   compilation unit to debug should load as a separate request
   - Minimal to no runtime overhead, even in debug mode
   - Support trace()


I took the following design decisions:

   - For private members, a mix of JavaScript lexical scope and field
   renaming like in Jangaroo is used
   - To implement an efficient "is" operator, all interfaces a class
   implements are determined once for the class. I use a prototype chain to
   inherit the interfaces implemented by the super class
   - Lazy class initialization uses a very efficient technique refined by
   Olaf Kummer: Wherever a constructor or non-private static member is called,
   the "self-destructing" class initialization function is checked for
   existence and, if still existing, called ("guarded" call)
   - Method binding is again borrowed from the Jangaroo Runtime: the bound
   function is "cached" at the object under a different but unique name so
   that it keeps its identity. This is important e.g. to be able to remove
   event listeners
   - Getter/setter functions map to Object.defineProperty("...", { get:
   ..., set: ...}), thus no support in IE < 9
   - To make everything else work in IE < 9, I use polyfills for ECMAScript
   5 Object, Array and Function API
   - For keeping generated code in separate JS files, expressing
   dependencies between these files, loading them separately at runtime and
   linking them statically into a single JavaScript file, I chose to use
   Asynchronous Module Definitions (AMD) and RequireJS (version 2.1.2) as the
   concrete implementation of AMD. AMD is preferred over CommonJS because it
   better fits web applications, as e.g. argued here:
   http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/To
link and optimize the application, RequireJS provides an optimizer
tool
   simply called "r.js".
   - To conditionally load polyfills (for IE < 9), I use the "shim"
   RequireJS plugin
   - To achieve minimal runtime overhead, I only use helper functions to
   define the class structure once (defineClass and defineInterface). As soon
   as the complete application structure is set up, all code executed is
   inlined
   - Since all modern browsers seem to support a "console" object with a
   "log" method, trace() is simply implemented to check for the existence of
   console.log() by trial-and-error (try... catch). It then String-converts
   and concatenates all its arguments like its ActionScript sibling


*About the Example*

To specify how I think FalconJx-generated JavaScript output should look
like, I created an ActionScript example, consisting of two classes and
three interfaces. Every language feature supported by the new runtime
format gives an appearance in the code (well, I didn't add a private static
method, because it works like a private method, only simpler).
The whole thing is a public GitHub project at
https://github.com/fwienber/as-js-runtime-prototype.
To download all files in one go as a zip or tar.gz, please use the tag
page: https://github.com/fwienber/as-js-runtime-prototype/tags.

A live demo is available on the corresponding GitHub pages at
http://fwienber.github.com/as-js-runtime-prototype/index.html
>From there, you can reach all ActionScript example sources and the proposed
JavaScript equivalent (so far, hand-coded :-)).
To see the example in action, use the three bottom links which start the
same application in three flavors:

   - debug: Each JS file corresponding to an AS class or interface and the
   main bootstrap file is loaded with a single request. This gives you a nice
   1:1 mapping of source to output in the JavaScript debugger. Additionally,
   there are some "infrastructure" files: require.js itself, the RequireJS
   plugin "shim" (shim.js, shims.js), my AS3 runtime helpers defineClass.js
   and defineInterface.js, and a couple of built-in AS3 functions (bind, as,
   is, trace). If loading in IE < 9, the shim plugin loads several ES5
   polyfills.
   - linked: The whole application is merged into one JS file using the
   RequireJS optimizer "r.js" without optimizations. Thus you only have two
   requests: require.js and hello-worls-all.js are loaded. In IE < 9, the
   polyfills are still loaded one-by-one (I didn't bother to optimize this
   case, but of course, it can be done).
   - minified: Same as "linked", only that require.js and
   hellow-world-all.js are minified by Uglify2. This can easily be achieved
   using "r.js" with the parameter optimize=uglify2.


For the demo, I redirected trace() from the JavaScript console (backed-up
in trace-console.js) to the DOM, so that you can see the log messages
directly.

Just look into the code and observe how it works in Firebug or any other
JavaScript debugger of your choice, and let me know if anything is unclear,
missing or if you need more reasoning for the design decisions taken.
I know there are still several issues to be fleshed out (e.g. interaction
with "native" JavaScript or package-scope variables, just to name two), but
I think the current state is a solid core of how a modern, efficient,
self-contained, extensive and still concise JavaScript runtime format for
Apache Flex could look like.
Please tell me what you think!

Have fun,
-Frank-

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message