Mommy, where do framescripts come from?

When writing ActionScript you have your choice of using external class files or attaching code to a timeline by simply typing it into the .fla code editor window. I’m going to ask you to follow four simple steps and observe the results.

  1. Create a new .fla in Flash, set to use AS3
  2. On frame 1, type gotoAndStop(3);
  3. On frame 2, type trace(“I’m a script on frame 2″);
  4. On frame 3, type this["frame2"]();

This should result in your trace window showing “I am a script on frame 2″.

“No way, Mr. Horseman! How could this have happened? The playhead never touched frame 2!” I hear your cries of astonishment even from here. Indeed, how did this happen? Let’s stop to think for a minute about what happens when Flash actually compiles a swf. The first thing to remember is that in a published swf frame scripts do not exist. In a previous entry I talked briefly about what the compiler does with instances on the stage. Note the following line of code from that old entry:

public var foo_mc:NewMovieClip0; // Where did this come from?????

Something similar happens every time you use the Flash Authoring Tool to write a framescript. There is an undocumented (but by now very well known) function of the MovieClip class called addFrameScript, which allows you to attach “frame scripts” at runtime to a MovieClip or any class derived from MovieClip. Indeed one thing you’ll find is that if you try to subclass Sprite and link that to a library symbol with frame scripts, you’ll recieve an error to the effect that Sprite does not have a function called addFrameScript. This should tell you that internally Flash uses this function to give the illusion that scripts you write in the Flash editor just “exist” as part of the movieclip. If we decompile the swf we just created, we will see exactly that.

package DecompileMe_fla
{
    import flash.display.*;
 
    dynamic public class MainTimeline extends MovieClip
    {
 
        public function MainTimeline()
        {
            addFrameScript(0, frame1, 1, frame2, 2, frame3);
            return;
        }// end function
 
        function frame3()
        {
            var _loc_1:String;
            _loc_1.this["frame2"]();
            return;
        }// end function
 
        function frame1()
        {
            gotoAndStop(3);
            return;
        }// end function
 
        function frame2()
        {
            trace("I am a script on frame 2");
            return;
        }// end function
 
    }
}

When Flash is required to attach frame scripts to a class (regardless of whether you explicitly created the class, or whether you are implicitly creating one simply by nature of the fact that you’ve attached a framescript to a movieclip in the editor) it adds (implicitly) public functions to that class named after the frame on which the code appears, and then uses addFrameScript in the constructor to add those frames at runtime. Since these functions are just public and freely accessable, the fact that the “playhead” never even needs to “touch” a frame in order for the frame’s scripts to be called should be quite obvious.

“You’re making my head hurt, Horseman! I implore you, cease this haunting with accursed visions from beyond the abyss!”

Piercing the veil of abstraction is always a perception-altering experience. You can expect to feel a slight discomfort, but more than that you should feel a distinct thrill about uncovering another of the world’s great mysteries.

Tags: ,

  1. #1 written by Mike M September 3rd, 2011 at 13:19

    Met you briefly at PAX Dev. Just wanted to say, awesome blog. The flaming letters are an especially nice touch :)

  2. #2 written by The Horseman September 5th, 2011 at 13:24

    @ Mike M
    Hi there, thanks for stopping by and for the compliments! I believe I met you along with Ezra, yes? And you have the awesome hair style?