Sunday, March 14, 2010

Understanding ApplicationDomains

I've been explaining how ApplicationDomains work in ActionScript frequently in recent days, so I'd
thought I'd put down an explanation here.

ApplicationDomains contain ActionScript class definitions.[1] The rules for ApplicationDomains are:

  1. Every ApplicationDomain except for the system ApplicationDomain has a parent ApplicationDomain, so ApplicationDomains form a tree structure.
  2. Definitions in parent ApplicationDomains are used over definitions in child ApplicationDomains.
  3. In a particular ApplicationDomain, the “first definition in” is used.

The Flash runtime has a special ApplicationDomain called the System ApplicationDomain, and it is special for two reasons: it contains all the definitions that are built into the Flash runtime, and it is the only ApplicationDomain that doesn’t have a parent. All other ApplicationDomains are descendants of the system ApplicationDomain. This means that the classes that are built-in to the Flash runtime will always win over classes defined in swf files loaded by the runtime.

When a swf is loaded, all the class definitions go into a particular ApplicationDomain. For the main[2] swf of an application, the Flash runtime creates a new ApplicationDomain that is a child of the system ApplicationDomain. When the application loads other swfs, it can choose the ApplicationDomain that the swf will be loaded into.

Ok, too many words, time for a demo:

This application visually shows how ApplicationDomains affect which version of a class is instantiated, when there are multiple versions of a class present. The tree shown corresponds to the ApplicationDomain hierarchy created by this application: each ellipse corresponds to an ApplicationDomain. When you hover over an ellipse, six small coloured ellipses appear, corresponding to one of six different swfs. Clicking on a small ellipse will load the swf corresponding to the small ellipse into the ApplicationDomain corresponding to the large ellipse, drawing an instance of the class on that large ellipse. The six swfs all contain the same Ellipse class, but each version draws the ellipse in a different colour. This is the ellipse class:

package
{
    import flash.display.Sprite;
    import flash.events.Event;

    public class Ellipse extends Sprite
    {
        public function Ellipse()
        {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        
        private function addedToStageHandler(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            graphics.lineStyle(1);
            graphics.beginFill(ELLIPSE::COLOUR);
            graphics.drawEllipse(0, 0, 50, 25);
            graphics.endFill();
        }
    }
}

The important part to note is the ELLIPSE::COLOUR constant. We create six different versions of this class by simply compiling the class six times, defining the constant differently each time:

mxmlc -define=ELLIPSE::COLOUR,0xff0000 -default-size 50 25 -o=ellipse-r.swf Ellipse.as
mxmlc -define=ELLIPSE::COLOUR,0x00ff00 -default-size 50 25 -o=ellipse-g.swf Ellipse.as
mxmlc -define=ELLIPSE::COLOUR,0x0000ff -default-size 50 25 -o=ellipse-b.swf Ellipse.as
mxmlc -define=ELLIPSE::COLOUR,0x00ffff -default-size 50 25 -o=ellipse-c.swf Ellipse.as
mxmlc -define=ELLIPSE::COLOUR,0xff00ff -default-size 50 25 -o=ellipse-m.swf Ellipse.as
mxmlc -define=ELLIPSE::COLOUR,0xffff00 -default-size 50 25 -o=ellipse-y.swf Ellipse.as

So to see the rules mentioned at the start in action, click the yellow ellipse in ApplicationDomain 111. That ellipse will turn yellow, because ellipse-y.swf, containing the yellow version of Ellipse, was loaded into ApplicationDomain 111 and an instance of Ellipse was created in that ApplicationDomain and drawn on the large ellipse. Then click the red ellipse in ApplicationDomain 1; this will load ellipse-r.swf into ApplicationDomain 1 and draw an instance from that ApplicationDomain on that ellipse. Click the small yellow ellipse (or any other ellipse) in ApplicationDomain 112 and it will turn red. Why? Since the red version of Ellipse was loaded into an ancestor domain, the new instantiations of Ellipse in ApplicationDomain 112 will be of the red version and any Ellipse versions loaded into ApplicationDomain 112 will be ignored.

To compile the main application from source:

mxmlc -o=ad-example.swf ApplicationDomainExample.as

I compiled these examples with the Flex 3.5 SDK.


  1. Technically, all varieties of ActionScript definitions are looked up via ApplicationDomains, not just class definitions.
  2. The swf referenced in the <object> tag of the html wrapper for a web application or the swf specified in the <content> tag of the application descriptor for an Air application.

No comments:

Post a Comment