actionscript-3mxmlcswccompc

Actionscript 3 - Script Libraries


I'm attempting to load the resulting swf of a swc build manually. Due to my particular environment, we have a need to segregate class definitions into swcs (where it makes sense) to remove redundant code from output swfs.

In a nutshell, I'm defining a class (LibA) in a swf that I'm building with compc. I'm compiling it both into swc and directory formats so I can easily extract library.swf from the directory to load at runtime (external linkage) and use the swc to compile out from any swf's built either with Flash CS5 or mxmlc.

LibA.as:

package
{
    public class LibA
    {
        public function LibA()
        {
            trace("*** LibA()");
        }
    }
}

Main.as:

package
{
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;

    public class Main extends Sprite
    {
        private var self:Main;
        private var context:LoaderContext;

        public function Main()
        {
            var l:Loader = new Loader();
            self = this;

            l.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event) {
                self.addChild(l.content);

                var liba:LibA = new LibA();
            });
            l.load(new URLRequest("./libs/build/liba.swf"));
        }
    }
}

I build the swc/directory swc with

compc -output libs/build/liba.swc -include-sources libs/LibA.as -debug=true

and I set the appropriate linkage in AS3 settings in Flash CS5 when building Main (class linked directly to the stage).

Everything publishes without an issue.

However, at runtime I get VerifyError: Error #1014: Class LibA could not be found.

What am I missing here? I want to be able to load and use classes defined within liba.swf from my Main.swf.

Full trace dump:

verify Function/<anonymous>()
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  0:getlex 4
                        stack: Main?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  2:getlex 7
                        stack: Main? flash.display::Loader?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  4:getproperty content
                        stack: Main? flash.display::DisplayObject?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  6:callpropvoid addChild 1
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  9:findpropstrict LibA
                        stack: Object
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  11:constructprop 10 0
                        stack: *
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  14:coerce LibA
VerifyError: Error #1014: Class LibA could not be found.

Solution

  • If you want to load classes from a SWF, you'll need to do something like (in your event handler):

    var li:LoaderInfo = e.target as LoaderInfo; // get the loaderInfo object from the event
    var swf:MovieClip = li.loader.content as MovieClip; // get the swf
    var c:Class = swf.loaderInfo.applicationDomain.getDefinition( "LibA" ) as Class; // get the class definition for LibA
    

    Creating a new c should give you your LibA object. You'll need the full class definition as a name.

    If I understand what you're trying to do though, I'm pretty sure you can set the SWC to embed an an external library - that is you get code completion, but none of the classes are included, and the SWC is searched for at runtime.

    EDIT

    Just tried something like what you're doing. In my example above, when you create c, if you trace it out, it'll trace LibA. However, if you explicitly reference it, you'll get the error that you describe. I think this is because Flash is getting confused with essentially 2 definitions of LibA - the one that was referenced and the one you're loading - they're in 2 different application domains.

    The fix is as @turbosqel describes it, load it in with a LoaderContext object:

    var l:Loader = new Loader();
    var context:LoaderContext = new LoaderContext( false, ApplicationDomain.currentDomain );
    l.contentLoaderInfo.addEventListener(Event.COMPLETE, this._onLoadComplete );
    l.load(new URLRequest("./libs/build/liba.swf"), context);
    

    This works for me, I can now explicitly reference the LibA class.