Why some AS3 swfs work stand alone but fail to load into other swfs

Wednesday, August 13th, 2008 | flex

Most developers who create standalone swfs have some standard instantiation code in their class constructor, something like this:

stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

This works fine when the swf is embedded on a page directly as the “stage” property will be available instantaneously.
When this swf is loaded into another swf however, say like this:

var loader:Loader = new Loader();
addChild(loader);
loader.load(new URLRequest(”http://widget.meebo.com/mcr.swf?id=RQYRkTseLc”));

It generates the infamous and ambiguous: TypeError: Error #1009: Cannot access a property or method of a null object reference.
I’m pretty sure this is because when a swf is loaded into another swf, it’s class constructor is called to create the object before it is even added to it’s parent (the Loader object).
Thus the stage property is undefined, which throws the error, which kills the call stack including what ever else was in the constructor after the stage reference.
I’d kind of consider this a bug in the flash architecture.

The work around to insure your swf is compatible with loading into other swfs:
If the stage references are just the above, you can throw a try/catch around them as they would probably get set by the loader anyways:

try {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
} catch(er:Error) { };

or just ensure the property is available:

if (stage){
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
}

or, if there is setup that absolutely requires the stage reference, put this in your constructor:

Constructor(){
if (stage){
onAddedToStage();
} else {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
}

private function onAddedToStage(evt:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
initApp();
}

12 Comments to Why some AS3 swfs work stand alone but fail to load into other swfs

[...] Very clear description is here. [...]

Steven Sacks
August 13, 2008

It’s not a bug in the Flash architecture, it’s a mistake on the part of the developer. AS3 is different than AS1. In AS3, things that have access to stage are not on stage unless you put them there using addChild. This is not a bug, but a developer mistake.

That being said, most AS3 component authors have proven themselves to be sloppy coders because they release broken components (and charge for them) because they mistakenly assume stage will not be null in the constructor and do not use addEventListener(Event.ADDED_TO_STAGE, onAddedToStage) which is simply good coding practice in AS3. I learned this the very first day I learned AS3, but then again, I read a book about it and didn’t just dive in expecting everything to be the same as AS1.

The solution is simple:

if (stage == null)
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
else
{
onAddedToStage();
}
private function onAddedToStage(event:Event = null):void
{
// init code that requires stage
}

markledford
August 14, 2008

Hi Steve,
Thats why I said I would “kind of” consider it a bug. In the example I’ve included the Loader IS added to the stage before the call to download the SWF. As far as the developer is concerned the SWF has been added correctly beforehand. This is unexpected behavior with how SWFs loaded into SWFs are instantiated.

Something I’m working on currently involves users being able to specify their own swfs to load. A good portion aren’t working because of this issue. Its just annoying that the authors of those swfs have to have the foresight to take the extra step of making their swf compatible. You can’t expect every swf author to do this or follow this “good coding practice” especially if their swf was never originally intended to be loaded into another swf.

I’d actually prefer if “stage” was never accessible by a class constructor so that this “best practice” could be a requirement.

sugandha
August 20, 2008

it helped me…as I was also facing the same problem.
I still further get few security errors that is surely solvable but besides that I get an error for stage access as well.
Lets say “swf_contain” is my container swf and “swf_loaded” is my swf being loaded into it.

Now I get error saying:
caller “swf_loaded” cannot access Stage owned by “swf_contain”
at flash.display::Stage/set align()
at net.slideshare.controller::Controller/onAddedToStage()
at flash.display::DisplayObjectContainer/addChild()
at egoWidgetNEW_fla::MainTimeline/playerLoaded()

I just wanted to understand how flash distinguishes between stage of container and loader swf. because here further loading I want it to access stage of loader swf.

Any help would be appreciated. Kindly mail me:)

markledford
August 20, 2008

Hi Sugandha,
Your probably loading a swf from a different domain into the first swf. The flash security sandbox prevents cross domain swfs from accessing each others properties unless explicitly allowed through the code. Try adding this to “swf_contain” and it should work:

Security.allowDomain(”*”);

Regarding how flash distinguishes between the stage of the container and the loaded swf, they reference the same object.

All stage properties references the single base-container Stage instance that all SWFs, including your main SWF and nested loaded swfs are contained in. The “stage” property will be “owned” by your main swf so you need to explicitly allow access to it like any other property of the swf using the above.

There is a nice hierarchy chart here:
http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000142.html

sitron
September 16, 2008

thanks so much!

Suresh
September 22, 2008

Hi,
I have used above code and when I trace the satge its giving as null but from else code the function is not getting triggered on that addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); event…
donno why? even I cant trace anything in that function..Can any one tell me what Im doing wrong?
thanks in advance

markledford
September 25, 2008

Hi Suresh,
Perhaps that function isn’t your class constructor. Can you paste the code?

Wale
October 6, 2008

You guys are the best. Thanks for the code. bBen searching the net for over 3 hours. Am referring to the topic (swf into swf) in as3. its been bugging sine last night. Your code worked perfectly. Am uploading my new web site in 20 mins. Thanks alot and have a nice day.

[...] Why does my swf work standalone, but when I try and load it into another swf, I get a null object error? Stages. [...]

Flo
November 27, 2008

Hi,
Thanks for the code it helped me a lot, but i try to use this code inside an child swf which have resize and possition function. Everything is working good until i try to resize the swf…I think somethig is wrong with the “possition” function..Bellow i paste my code:

if (stage){
onAddedToStage();

} else {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}

function onAddedToStage(evt:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

possitionBar();
stage.addEventListener(Event.RESIZE,positionAll);

}

function possitionBar():void {
bar_mc.bar_mc.width = stage.stageWidth-20;
buttons_mc.x =(stage.stageWidth - buttons_mc.width)/2;

bar_mc.x = 10;
buttons_mc.y = stage.stageHeight - ((bar_mc.height-5 )*2);
bar_mc.y = stage.stageHeight - bar_mc.height;
//positioning the loader
_loader_mc.alpha = .2;
_loader_mc.x = 10;
_loader_mc.y = bar_mc.y;

}

//position all the elements on resize
function positionAll(e:Event):void {

try {
resizeAndPositionTheBigImage(_bigContainer_sp,W ,H,false);

} catch (e:Error) {
}
//positioning the loader
_loader_mc.x = 10;
_loader_mc.y = bar_mc.y;

}

This is the Url:
http://www.fashionbehave.com/SV-project/

Thanks in advance, Flo

Sue Leo
December 15, 2008

Thanks SO much for this code. I have been looking for an answer for this error in clear understandable terms. I am a designer learning how to code. I had several event listeners on the stage and that was the source of the error code.

Leave a comment

Meta

Search