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.