SWF9 Conversion
From OpenLaszlo
Migration of code to SWF9 Runtime
Number of arguments must match in caller and callee
In Javascript runtimes, people are accustomed to having missing arguments default to a value of null when calling methods. In as3, the number of arguments must match exactly, or else some of the arguments must be declared optional.
There are two ways to declare optional arguments:
<method name="foo" args="a = null, b = 259">
Or for a variable number of args, the "..." syntax can be used
<method name="foo" args="...myargs">
All class attributes should be declared
If your method references an instance var such as "this.foo", you need to declare foo as an attribute or else a compile-time error "access to undefined property" will occur.
A workaround, for classes which are declared dynamic (the default), is to refer to this['foo']. But it is better to declare instance properties explicitly.
Use "cast" for casting types
To cast a type portably, use the "cast" operator. E.g.,
expr cast LzAlwaysExpr
You cannot override a method and change the argument signature
Any method which overrides a superclass method must have the same argument signature.
I'm not sure what the exceptions here are, i.e., if you can make arguments optional that are not optional in the superclass method.
API Changes
Methods that handle events must accept one argument
When creating a delegate `new LzDelegate(<object>, <methodname>)`, <methodname> must be a method of one argument, because it will be invoked by LzDelegate#execute with one argument (typically the argument that is passed to LzEvent#sendEvent when that delegate is registered to receive events). If <methodname> is called elsewhere, it will have to be called with a suitable argument). Similarly if the handler tag is used to connect an event to a method, the method must be a method of one argument.
In DHTML and swf9 you will get a warning if you create a delegate or attach a handler method that does not accept 1 argument. You should update your code appropriately.
SWF9 Gotchas
Notes for converting LFC code to swf9. For instructions on setting up a SWF9 build environment see BuildingSWF9
ActionScript 2.0 Migration page from Adobe
[| ActionScript 2.0 Migration]
[| Adobe Tips for Learning ActionScript 3]
use new Array() instead of Array()
To create an array, you must use "new", e.g.,
change
return Array(a, b, c, d);
to
return new Array(a, b, c, d);
constructor in a non-dynamic class must be referenced using this syntax
this['constructor']
In a function, if you use the special "arguments" var:
arguments.caller is no longer supported
calling 'instanceof' with a null value will throw runtime error.
Workaround, use "is" instead, in cases where the first arg may be null or undefined:
if (foo instanceof LzView)
becomes
if (foo is LzView) ...
You cannot delete "fixtures" (declared instance vars) of an instance
We have code in the LFC that deletes var in order to free up memory or null them out. These have to be checked, and in most cases converted to just set the value to null when possible. For cases where the property really has to be deleted to remove shadowing of an instance var, we need to rewrite that code to use some other approach.
Need to put call to add tagname to constructor map *outside* of the class def.
class LzNode {
...
}
ConstructorMap['node'] = LzNode;
If you override a superclass method, you must use the override keyword
public override function setWidth (...) { ... }
Classes which receive events must inherit from LzEventable
Any object which receives events (e.g., is target of a sendEvent() call) must extend the LzEventable class.
overriding variable definitions
You cannot initialize a variable that is already defined in a base class using this syntax:
var nodeType = LzDataNode.TEXT_NODE; // Done in the derived class
Instead, you must initialize the value in the constructor:
function LzDataText(text) {
super();
....
this.nodeType = LzDataNode.TEXT_NODE;
}
Be careful using the 'in' operator
Using 'in' to see if an object contains a method only works in swf9 if that method is labeled public.
For example,
if (this.context && 'getContext' in this.context)
is always going to fail. One solution is to make sure the base class has a definition for getContext().
Use 'is' operator instead of looking for a property
This line of code,
}else if (n.length) {
fails in swf9 if n does not have a property named length. This check is trying to determine if the object is an Array. This can be rewritten as,
}else if (n is Array) {

