I should be asleep, but this is such an awesome bug. Have the need to load one Flex app into another Flex app at work. Modules force us to refactor our 2 separate code bases, which we don’t have time nor budget to do right now and a component suffers from the same problem. Using a unique ApplicationDomain, I can load an app Mike built into an app I built without worrying about class collisions.
Nick, a co-worker and brilliant PHP developer not even out of college, found a bug where if you went to a state that showed Mike’s app, then left that state which removes Mike’s app from the display list (that’s how states work), and then resized the browser, you got an exception. The stack trace is just 1 line, basically stating that mx.managers.SystemManager is having a problem with a null object in the Stage_resizeHandler function.
The short description of the problem is that the “stage” property of DisplayObjects is null when a DisplayObject is not in the DisplayList. It’s set after it’s added. The SystemManager is designed to assume that the stage is never null in this case. The stage does become null, though, because since this application is only shown in one state, and then not shown in another means that it’s removed from the DisplayList. Therefore, the listener to the Stage object is still there, and the resize handler gets triggered when you resize your browser. Since the whole entire app, SystemManager included, is in fact a DisplayObject, it fails since its stage object is now null.
It’s a justified design decision because the use case of loading Flex apps into other Flex apps is just weird to begin with, and thus an edge use case that doesn’t really get much testing. The “right” thing to do would be to build an encapsulated component or Module, thus rendering this use case invalid, and thus not a problem.
The solution for now isn’t pretty because SystemManager’s resize handler, and the rest of the code it uses to setup the stage listeners is private, thus nothing I can really do save modifying the code directly, and recompiling the SWC. Not really a solution.
Instead, we just removed the external app from the state, and add it to the main app. We then just use a SetProperty action for the state tag to toggle the visibility. Since being invisible and being out of the DisplayList are 2 different things, with the former still retaining a non-null reference to the Stage via the stage property, it works. To say that another way, when you set the visibility of a DisplayObject to false, like a MovieClip, it still retains it’s reference to the stage.
Interestingly, I reckon removedFromStage was added in a new Flash Player 9 build (don’t know which one) because the 2.01 docs show it for flash.display.DisplayObject whereas the 2.0 docs do not. If SystemManager were to respond to this event, I think things would work just fine. Either that, or just code things to assume stage may be null.
…again, in all fairness, this is a problem Flash Developers have run into for years, so didn’t really think it’d go away in Flex (although, I hoped it would). To quote one of the Flash greats with regards on how to code your Flash apps, which could apply in this case to your Flex apps: