Personal tools

SWF9 Conversion

From OpenLaszlo

Contents

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 lz map *outside* of the class def.

class LzNode { 
...
}
lz[LzNode.tagname] = 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) {