What is in flash.swc?

In this part of our ongoing series about cross-compiling ActionScript to JavaScript I will talk about flash.swc, which is the last of the three FlashRT SWCs of my  “dreamed up” Flex SDK for JavaScript:

  • frameworks/libs/browser/browserglobal.swc
  • frameworks/libs/browser.swc
  • frameworks/libs/flash.swc

The FlashRuntime API has about 450 classes and flash.swc has about 200 of those classes covered. Some of the APIs for i.e. accessing the camera will probably never make it into flash.swc, because browsers don’t support those APIs. One important thing to point out right from the start is that I recommend implementing the FlashRuntime API in ActionScript in terms of browser.swc and browserglobal.swc like I did in my previous post with the implementation of trace().

There is no way I can cover all 200 classes of flash.swc. Instead I would like to focus on a few classes that were particularly hard. Those are:

  • Proxy
  • Dictionary
  • XML, XMLList
  • EventDispatcher
  • DisplayObject
  • BitmapData
  • ByteArray
  • MovieClip
  • Stage

Let’s get started!

 

Proxy

You might recall that I explained Proxy in a previous post in December. It can be done, but supporting Proxy requires a lot of work on the cross-compiler.

 

Dictionary

I have also talked in detail about Dictionary in a previous post. To summarize, Dictionaries can be implemented as a class derived from Proxy. The only ActionScript feature that we cannot support is weak references. For that reason it is probably a good idea to throw an error if somebody passes true for useWeakKeys when creating a Dictionary:

// ActionScript:
public dynamic class Dictionary extends Proxy
{
    public function Dictionary( useWeakKeys : Boolean = false )
    {
        if( useWeakKeys )
            throw new Error("Weak references are not supported!");
    }
}

XML, XMLList

ActionScript support built-in XML (E4X) but no browser except for Firefox supports E4x and even Mozilla hinted that they might drop support for E4X. In a previous post I suggested for that reason dropping support for E4X. But in practice you’ll find a lot of projects that do use XML and E4X. Over time I realized that we probably need to offer some sort of compromise and I created two classes AS3XML and AS3XMLList that emulate a subset of XML features on top of DOM Element and NodeList.

The details are pretty boring except for maybe the part where the constructor parses a string to an Element:

package flash.xml
{
  import adobe;
  import org.w3c.dom.DOMParser;
  import org.w3c.dom.Element;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  ...
  // E4X definitions. based on ECMA-357
  public final dynamic class AS3XML extends Object
  {
    public function AS3XML(value:Object=null)
    {
      if( adobe.jsInstanceOf(value, Node) )
      {
        const valueAsNode : Node = value as Node;
        setNode(valueAsNode);
      }
      else if( typeof(value) == "string" )
      {
        const str:String= value as String;
        setNode( parseFromString(str) );
      }
      else
      {
        throw new Error("XML: incorrect parameter");
      }
   }
   public static function parseFromString( str : String ) : Element
   {
     if( !str )
       return null;

     const parser : DOMParser = new DOMParser();
     const elem : Element = parser.parseFromString(str, "text/xml") as Element;
     return elem;
   }
   public function getNode() : Node
   {
     return m_node;
   }
   private function setNode( val : Node ) : void
   {
     m_node = val;
   }
   ...
 }
}

 

EventDispatcher

In the Flash Runtime dispatching and observing events is probably one of the most important mechanism used for communicating between instances. The browser’s DOM does support event propagation, too. But some features like event bubbling are either different, or missing. You could roll your own event model like Google did in its Closure Library. If you do so you would run the risk of  missing out on some optimizations that only the native browser code offers. I went back and forth on this topic until I decided to base flash.events.EventDispatcher on jQuery’s event implementation. My hope was that I might get the good parts of both worlds. Later I abstracted the event model core in IFramework in order to allow other framework implementations including Google’s Closure Library.

 

DisplayObject

“Do you use SVG, or Canvas?” That’s what people ask me all the time. My answer has always been: “Both”. But my flash.swc has a bias towards SVG. DisplayObject uses an SVGLocatableElement. Here is an example:

public function set alpha(value:Number):void
{
  m_alpha = value;
  m_element.setAttribute( "opacity", value.toString() );
}

 

BitmapData

As far as I remember BitmapData is the only class that uses Canvas within flash.swc. But how do I integrate Canvas elements with the rest of my SVG tree? Well, SVG has this fantastic feature called ForeignObjectElement. You can mix Canvas into SVG, but not the other way around. If you are interested in more details on how you can use Canvas in SVG, please read this article.

 

ByteArray

I probably spent more than a week on ByteArray alone. These were the painful areas:

  • read/writeFloat
  • read/writeDouble
  • read/writeObject
  • compress/uncompress, deflate/inflate

read/writeFloat is about  serializing IEEE 754 single-precision (32-bit) floating-point numbers while read/writeDouble is about  IEEE 754 double-precision (64-bit) floating-point number serialization. You might think that by now there should be tons of libraries and examples out there that serialize according to IEEE 754. That is indeed the case, but I could only find one implementation that worked. The rest all had bugs which I found with the fantastic IEEE-754 Analyzer.

In order to support read/writeObject I had to implement Action Message Format serialization. I did that by manually converting BlazeDS’s Java code to ActionScript. The compress/uncompress, deflate/inflate require zip compression code, which I implemented using the old FZlib, that is still floating around on the Web.

The code for AMF and FZLib is so large that I moved it into amf.swc and fzlib.swc. The current implementation of ByteArray doesn’t require amf.swc and fzlib.swc and will assert if you use i.e. read/writeObject without linking amf.swc:

public function readObject():*
{
  // s_defaultDeserializer is implemented by amf.swc
  if( s_defaultDeserializer )
    return s_defaultDeserializer.readObject(this);
  throw new Error( "ByteArray: no default deserializer. " +
                   "Did you forget to link amf.swc?" );
}

 

MovieClip

As a Flex developer you rarely see or use MovieClip. But if you come from the Flash Pro world you constantly deal with MovieClips. The biggest pain about MovieClip is that it is a read-only interface. As a developer you are supposed to only play a MovieClip but never programatically add any frames to it. When I started working more seriously with MovieClip I quickly realized that the API is pretty much useless if you want to for example cross-compile a game like Pew Pew.

A MovieClip is conceptually a Sprite with a Timeline. So here is how MovieClip looks like in flash.swc (and in my opinion that is how MovieClip should have been designed):

public dynamic class MovieClip extends Sprite
{
  protected var m_timeline : ITimeline = null;
  public function MovieClip(tl:ITimeline = null, element : SVGLocatableElement=null)
  {
    super(null,element);
    if(tl)
      m_timeline = tl;
    else
      m_timeline = new Timeline();

    ...
 }
 ...
}

The ITimeline interface allows you to add frames and retrieve TimelineObjects from the timeline. This change allowed me to cross-compile ActionScript code that integrates with Adobe Edge‘s runtime.

 

Stage

There is really only one Stage per SWF. For that reason I made Stage a singleton:

public static function instance() : Stage
{
  if( !s_instance )
  {
    ...
    s_instance = createStage(w,h,null,bgcolor);
    ...
  }
  return s_instance;
}

 

What is next?

We finally made it through the long lost of painful flash.swc classes!

So what’s next? These are the topics that I have in mind:

  • debugging
  • testing
  • optimizing
Please let me know if there are any topics you would like me to talk about.

 

 

 

 

 

 

 

 

 

 

 

 

6 Responses to What is in flash.swc?

  1. Hello, FalconJS seems going in the good way, but when can we hope to see a release even beta ?
    For my part i’m most interested in the AS to JS cross compiler than in the different api implementation, could we hope to see that part published before the flex api implementation, the flash api implementation, and the mxml cross-compiler are finished ?

  2. Hi, Thanks for you posts!

    My questions are:
    – What is the status of the FalconJS project? Everything from the Flash Player API is implemented (what is possible atm)?
    – What are the foreseen limitations of the compiler? Why you are not sure it could be finalized into production quality? (referring to previous video about falcon js)
    – Can you post some results of flash vs. cross compiled javascript performance tests? If there are any existing data..
    – I’m also interested in the size of the whole cross compiled framework (source and minifyed), also comparsion of SWF vs cross compiled JS application file size.
    – What was most complex application which you could cross compile and run smoothly?
    – Have you done any tests running FalconJS apps on mobile/tablet like android or ios? If yes what were the observations?
    – Can you list all the classes which could not be implemented in javascript due to browser limitations (like Camera and Microphone..). Are there many?
    – Do you think runtime asset loading and sequential preloading is an easy task for js? Loader implementation is working?

    Any pre-alpha / beta release would be highly welcomed!

    Best regards,
    Andrew

    • Bernd Paradies says:

      Those are good questions! I am planning on writing three more blog posts about optimizing, debugging, and testing. Then I might grab one of my projects and walk you all through the details. I am pretty sure I will answer some of your questions. If you are interested in tracking the progress of Apache Flex and when Falcon and FalconJS might become available etc. I can recommend Michael Schmalle’s blog: http://blog.teotigraphix.com/. It’s almost a diary of Apache Flex.
      Please poke me again after the next three posts if there are still open questions.

  3. pratyoosh says:

    Hello Bernd, this is some really cool stuff & debunks some myth that Flex to HTML/JS conversion will be an impossible beast

    The performance implications ofsuch a conversion would need to be cleverly managed

    We have significant investment in Flex technology & think that language/toolset is more valuable than the runtime. I am a committer on open source Flex project & would love to devote time & energy into this project.

    The problem may be challenging but i can see how it is very achievable reading through your blog posts

  4. Hi Bernd!

    Thanks for the response, i’m looking forward to the next posts!
    Actually i’m subscribed to the Apache Flex mailing lists so i can follow the news regarding the Falcon project.
    I’ve got one more question to add:
    – Do you think it will possible to compile directly existing (huge) libraries/frameworks to JS without any manual modification?
    One of the gaps of eg. HaXe is that you have to port the existing frameworks by hand, there are no converters out there (AS3toHx is not 100% perfect because of the language differences [no super getter/setter override for example]).

    Best,
    Andrew

    • Bernd Paradies says:

      Depends on your definition of “huge” libraries. We recently cross-compiled GSkinner’s TweenLite without any modifications. But if you look at the code you kind of want to make some changes (if you know what I mean).
      I usually end up tweaking the code and I don’t mind it. For example Box2D uses “virtual” as a keyword. The old MXMLC doesn’t complain. But Falcon throws a syntax error.

      Cheers,

      – Bernd