Const, Types, For/Each, and E4X

This post about cross-compiling ActionScript to JavaScript  is continuing our discussion about ActionScript language features and how they could be emulated in JavaScript. In this part you will learn about:

  • const and types
  • int and uint
  • vectors
  • for..each
  • E4X

 

Const and Types

ActionScript encourages the usage of types and const.

// ActionScript:
const num : Number = 1.0;

The “const” keyword can either be ignored for member declarations, or be replaced with “var”. Types disappear in JavaScript.

// JavaScript:
var num = 1.0;

int and uint

In JavaScript you only have one Number data type, while ActionScript supports Number, int, and uint. This is quite problematic, because int and uint represent 32-bit integers with smaller number ranges than Number’s:

int.MAX_VALUE = 2147483647;
int.MIN_VALUE = -2147483648;
uint.MAX_VALUE = 4294967295;
uint.MIN_VALUE = 0;

Why is this problematic? Because int and uint “roll over” at their number range boundaries:

// ActionScript:
var num : uint = 4294967295;  // = uint.MAX_VALUE
num++;                        // becomes 0

This is bad news. That means we cannot just translate uint and int to Numbers.

// JavaScript:
var num = 4294967295;  // = uint.MAX_VALUE
num++;                 // becomes 4294967296.0, because Number has a wider range

In order to correctly transform uint and int to JavaScript we have no other choice than injecting utility function calls that emulate the rolling over behavior:

// JavaScript:
var num = 4294967295;          // = uint.MAX_VALUE
num = as3.addToUint(num, 1);   // calling utility function that emulates uint.

The implications are devastating. You can imagine that injecting utility function calls for every numeric operation involving uint and int will result in slow JavaScript code. In order to prevent that we might have to bend the rules. Here are three ideas:

  1. “Roll overs are bugs” – Don’t inject utility function calls and live with the differences between ActionScript and JavaScript.
  2. “Use Number instead” – Drop support for uint and int and throw a syntax error if the client code uses uint or int.
  3. “It’s only bad in debug” – Use “dart rules” and inject function calls only in debug mode. In release mode we would use the original expressions.

Besides potentially having to inject utility function calls for numeric operations we probably also need to create fake int and uint classes for things like MAX_VALUE and instanceof:

// ActionScript:
var num : uint = uint.MAX_VALUE;
trace( num instanceof uint );

Google’s optimizing Closure compiler barks if you use “uint” and “int” as identifiers. That’s why it’s probably better to use UintClass and IntClass instead.

// JavaScript:
var UintClass = { MAX_VALUE: 4294967295 };
trace( as3.instanceOf(num, UintClass) );

Vectors

ActionScript Vectors are a fairly recent addition to ActionScript. I like them:

// ActionScript:
var vec : Vector.<int> = new Vector.<int>();
var myFilter = function(item:int, index:int, vector:Vector.<int>):Boolean {};
var result:Vector.<int> = vec.filter(myFilter);

Since ActionScript’s Vector API is a superset of the Array API we could probably just transform Vectors to Arrays and inject utility function calls for the parts that are not covered by Array’s API:

// JavaScript:
var vec = [];
var myFilter = function(item, index, vector) {};
var result = as3.vectorFilter(vec, myFilter);

for..each

In ActionScript for..each and for..in are very close cousins:

  • FOR EACH gives you access to the element in the array.
  • FOR IN gives you access to the index of the array.

Here is an example in ActionScript:

// ActionScript:
const haystack : Object = {a:1, b:2, c:3};
for each( var needle: uint in haystack )
{
    trace( needle );   // 1, 2, 3
}

Fortunately for..each expressions can easily be transformed to for..in expressions:

// JavaScript:
var haystack = {a:1, b:2, c:3};
for(var needle1 in haystackObj)
{
    needle = haystack[needle].toString();
    trace(needle);
}

 

E4X

According to Wikipedia “ECMAScript for XML (E4X) is a programming language extension that adds native XML support to ECMAScript (which includes ActionScript, JavaScript, and JScript)”. This feature seems to be quite popular. For example, Open Source Media Framework (OSMF), away3D, and papervision3D all use E4X . But reality is that none of the major browsers except for Firefox support E4X and it seems unlikely that they ever will. Even Mozilla seems to have moved away from E4X. On their website they warn:

Warning: Mozilla is not actively maintaining E4X except
for security bugs. Do not use it for any new work.

Cross-compiling E4X to JavaScript can be done but it’s probably not worth the trouble. You would have to inject appropriate utility function calls for every E4X expression. My recommendation would be dropping support for E4X when cross-compiling ActionScript to JavaScript. In other words if the client code uses E4X our cross-compiler needs to report clear error messages.

 

 

 

 

11 Responses to Const, Types, For/Each, and E4X

  1. Raju Bitter says:

    That makes sense. I personally like E4X, but without browser support there’s no reason to support E4X (or to invest any time into finding a solution to cross-compile E4X into JavaScript) for FalconJS.

    Is there – by any chance – a public mailing list to discuss possible features of FalconJS?

    • Bernd Paradies says:

      Unfortunately there is no public mailing list for discussing FalconJS features. Please comment on this blog as you see fit. In addition I will send you my email address in case you prefer to contact me directly. Thanks for your interest in FalconJS.

  2. Many of your considerations have been discussed or even solved before, namely as part of the Jangaroo project. It is interesting that you come to very similar conclusions. For example, have a look at our E4X discussion http://groups.google.com/group/jangaroo-users/browse_frm/thread/953acd9f5965d149 or at the get/set function problem http://groups.google.com/group/jangaroo-users/browse_frm/thread/39afd2e109f92bb9#
    As Jangaroo is open source, I hope Adobe is not re-inventing the wheel here? I understand that you want the compiler to be based on Falcon, not a “home-grown” one like the Jangaroo compiler, but what about sharing the code generator (which, after some recent refactoring, is quite independent from the parser) and the runtime? I’d be willing to co-operate!

    • Bernd Paradies says:

      I like Jangaroo and I think your project is pretty impressive considering that you don’t have access to the source code of the Flash Runtime and the Flash Player. I investigated Jangaroo in April 2010 and have followed it with great interest since. Back then I found the Maven dependency pretty awkward. The parser/lexer code seemed heavily influenced by our open source version of asc (http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/asc), which is fine because we open sourced it. I did have to report to our legal department that some of ActionScript files with original Adobe copyright notes were converted to Creative Commons Licences without Adobe’s permission. One thing about Jangaroo I didn’t like was that each class got loaded separately. (Is that still the case?) It seemed to me that Jangaroo “outsourced” the problem of building a dependency graph between modules to Ext JS. You can do that but that of course drags down your performance and the closure compiler won’t be able to optimize much.
      Jangaroo might have overcome those (what I thought were) shortcomings and I don’t want to sound too negative. In short, I think Jangaroo is a really nice project and I would like to encourage you to participate in this discussion about cross-compiling ActionScript to JavaScript and share your knowledge with the developer community. In regards to sharing code between Jangaroo and FalconJS I can imagine cross-compile Jangaroo’s runtime code with FalconJS. On the other hand at this point FalconJS’s runtime (FlashRT) covers significantly more APIs than Jangaroo does. Cheers.

      • Bernd, thanks for your reply and your evaluation of Jangaroo. Let me comment on some of your statements.

        > Back then I found the Maven dependency pretty awkward.

        The Jangaroo compiler itself does not have a Maven dependency. You can use Maven, but also Ant, the command line (if you like) or since version 0.9 even a Java API to invoke the compiler. Since we prefer Maven, it is the recommended and best-tested usage scenario.
        For Flex, you also have flexmojos, so why do you think using Maven for Jangaroo is awkward?

        > The parser/lexer code seemed heavily influenced by our open source
        > version of asc…

        I will have to ask Andreas, who is the core compiler author, but I don’t think so. Implementing a parser/lexer for a given syntax / semantics is likely to lead to very similar results…

        > I did have to report to our legal department that some of ActionScript
        > files with original Adobe copyright notes were converted to Creative
        > Commons Licences without Adobe’s permission.

        Do you mean some of the runtime and JooFlash AS3 classes? What we did (after reassuring with Adobe that the license of FlashPlayer’s ASDoc is, as stated on the Web site, creative commons http://creativecommons.org/licenses/by-nc-sa/3.0/) was to “screen-scrape” the ASDoc-HTML and reconstruct the ActionScript APIs / method signatures, solely based on the documentation. No implementation whatsoever has been copied (where from, anyway?). Only for some very simple classes (e.g. classes containing constants only or very obvious implementations like getters/setters), this might resemble the original ActionScript files. Since we used only the creative-commons-licensed information to reconstruct the API, I can’t confirm that we “converted ActionScript files” to another (weaker) license.

        > One thing about Jangaroo I didn’t like was that each class got loaded separately.
        > (Is that still the case?)

        Yes and no. Jangaroo loads each class separately in debug mode, so that there is a one-to-one mapping between JS files loaded in the browser and AS files in your IDE. Since debugging is done locally, even for a large number of classes, a Jangaroo application starts up astonishingly fast. Jangaroo compiles to a format that keeps code in exactly the same line as in the AS source code, making debugging independent of any special “hosted environment” (GWT).
        For deployment, all JS code of a complete module is concatenated to a single JS file and can be run through any JS minifier. We just got nice results using Closure (after fixing an issue with the “int” keyword you also mention in your blog).

        > It seemed to me that Jangaroo “outsourced” the problem of building a dependency
        > graph between modules to Ext JS. You can do that but that of course drags down your
        > performance and the closure compiler won’t be able to optimize much.

        Jangaroo “outsources” dependencies between modules to Maven (not to Ext JS). However, you can compile multi-module projects with Ant or CLI, too, but of course it is more effort.
        Dependencies between classes are added to the generated code so that the Jangaroo runtime can (in debug mode!) use these to load all needed classes. Without debug mode, you can concatenate all JS of all module into a single file and load that, if you like.
        Why should this have negative impact on performance or code optimization possibilities?

        > In regards to sharing code between Jangaroo and FalconJS I can imagine cross-compile
        > Jangaroo’s runtime code with FalconJS. On the other hand at this point FalconJS’s
        > runtime (FlashRT) covers significantly more APIs than Jangaroo does.

        The value of Jangaroo is not so much in the Flash API re-implementation (which is still quite incomplete and I’m sure you have better ways to achieve this goal at Adobe), but in the generated code layout and runtime support. By “runtime”, I don’t mean the Flash API, but the core runtime to simulate AS3 language features. For example, how do you implement private members efficiently? How do you take care of static code being executed at the right time? Which is the best way to simulate a super method call? What about optional parameter default values? I understand this is what your blog is about, and I think we could contribute our insights regarding these questions.

        Greetings, -Frank-

  3. Kevin Newman says:

    +1 to Frank Wienberg – why duplicate so much effort?

  4. Joseph says:

    I don’t mind having a learning to to modify my Actionscript to have Falcon work!!

    Though i am curious, what about MXML… even MXML components like the <s:List ?

    • Rahan says:

      Joseph, MXML components are compiled to AS3 classes, before being compiled to bytecode.
      Thus, the cross compilation to JS of MXML is the same question than cross compiling AS3 to JS.

    • Rahan says:

      +1 about AS3 little rewrites to be JS cross compilation compatible

  5. Rahan says:

    Hi all,
    About this cross compilation issue.
    I have more global questions which are very important for strategic future of the flash platform.

    You’ talking about FalconJS and cross compilation to actual JS, aka EcmaScript 3.
    But the near future and the very usefull cross compilation of AS3 for mobile web browsers where theres no flash player, will be for sure the cross compilation to Ecmascript 6. would’nt it?

    So i wonder:
    – how is it difficult to cross compile AS3 to ES6? what performances drawbacks it leads to?
    – what is the gap between ES6 and ES4 and thus, how long will it take for standards to evolve from ES6 to next version?
    – what the drop of packages, namespaces and early bindings imply for AS3 cross compilation and performances?

    Thanks a lot, for the answers which are very very important to understand where flash platform and AS3 coding can lead to the near future.