Archive for the 'Research' Category

Iterating properties creates unwanted side-effects

Sunday, October 12th, 2008

Also known as:

  • iterating properties in actionscript 2 causes getter setter to execute
  • I was working on our AS2 logger today. In particular I was creating a setup where you could simply drop in a couple components in your fla and ‘tada’, you would have a reflecting logger at your disposal.

    I’ll go into the reflecting logger and component creation in another post, because what happened was that during a test run I ran into the dreaded 256 levels recursion problem.

    Some research indicated that the problem lay with getters and setters.

    Imagine you have a class:

    class TestClass {
        public function get id1 () {
            trace ("hello world");
        }
    
        public function id2() {
            trace ("goodbye world");
        }
    }
    

    Now do:

    _global.ASSetPropFlags(TestClass.prototype, null, 0, 7);
    for (var i:String in TestClass.prototype) {
        trace (
             "Property:"+i+" is function ? "+
             (TestClass.prototype[i] instanceof Function)
        );
    }
    

    Ok, truth be told, you will not do this every day. In fact building a reflection package is probably the only time this issue shows up. However I like to document stuff for posterity’s sake, so here we are.

    Executing the code above will show something like:
    hello world
    Property:id1 is function ? false
    Property:id2 is function ? true
    Property:__get__id1 is function ? true
    Property:__proto__ is function ? false
    Property:constructor is function ? true

    The _global.ASSetPropFlags is used to unprotect all the prototypes properties, in order to force them to show up. In a real situation, you should always make sure you keep track of the original settings of an object’s properties and revert the object back to those settings after you are done with it.

    Anyway what is really interesting is that testing the id1 property to see whether it is a function or not, causes the underlying method (the ‘get’ method) to execute.

    Luckily I never use getters and setters. But other people do. This is not to say that getters and setters are bad, just that I ran into a situation which I hadn’t anticipated :) .

    In most situation this will not cause a problem either, but you never know. The getter might go into a recursive loop if no parameters are passed. A class might update it’s properties unintentionally, who knows? I don’t. I do know that if those side effects do happen, you will lose hours of precious time bughunting.

    So how to circumvent these special properties of woe?
    If you look closely at the output again, you’ll see something like __get__id1 in there as well.
    These kind of methods will only be created by flash if you use getters and setters.

    So how can you detect if obj[i] refers to a getter/setter and should not be executed?

    Test for the existence of __set__i and __get__i.

    As the saying goes, you’ll find the solution in the last place you look.

    More information on ASSetPropFlags:
    http://objectpainters.com/blog/2007/06/21/assetpropflags-explained/

    Why you MUST call super

    Friday, December 7th, 2007

    When implementing super and subclasses, Flash will call the superclass’ constructor automatically unless you call it yourself.

    ‘Great’, I hear you think. Well… not so much.

    Imagine you have the following code:

    class Super {
       public function Super () {
           trace ("super called");
       }
    }
    
    class Sub extends Super {
    }
    
    var myObject:Object = new Sub();
    

    Result? Yes indeed, it traces “super called”. The constructor for Sub doesn’t exist, so the default constructor is used, which calls the super class constructor by default.
    All’s fine…

    Next example:

    class Super {
       public function Super (pName:String) {
           trace ("super called with "+pName);
       }
    }
    
    class Sub extends Super {
    }
    
    var myObject:Object = new Sub();
    

    Result? The super constructor is still called! (To my amazement, but anyway). It is called with no parameters since we didn’t pass any, so I guess that was to be expected. So although this is a little evidence that we should have called the constructor explicitly, it still wouldn’t have prevented us from calling it without parameters.

    Ok, next bit of code:

    class Super {
       public function Super (pName:String) {
           trace ("super called with "+pName);
       }
    
       public function mySuperMethod() {
       }
    }
    
    class Sub extends Super {
        public function Sub() {
        }
    }
    
    var myObject:Object = new Sub();
    

    Result? Yes, the super constructor is still called, since that was the default behavior. Us defining a constructor doesn’t mean we have overridden the superclass constructor.

    Ok, let’s move on!

    class Super {
       public function Super (pName:String) {
           trace ("super called with "+pName);
       }
    
       public function mySuperMethod() {
       }
    }
    
    class Sub extends Super {
        public function Sub() {
            super.mySuperMethod();
        }
    }
    
    var myObject:Object = new Sub();
    

    Result? The super constructor is NO LONGER called. Appearently something is getting messed up by the super. statement. In both the Flash IDE and the MTASC compiler the super constructor fails to run. If we replace super.mySuperMethod(); with mySuperMethod(); the super constructor is called again. Note that super.mySuperMethod is NOT a case of calling the superclass’ constructor, I’m simply calling one of the superclass’ methods.

    Conclusions:

    • always called super ( … ) ; explicitly
    • do not use super. to clarify your code, unless you consequently follow the first rule

    Ideas for asset and code separation

    Wednesday, November 14th, 2007

    I had an idea this afternoon for simple asset from code separation in Flash8/AS2. You might have been in the situation were you wanted to load in your views, or have your views and other assets external from your code. If these assets happened to be V2 Components you were even having a bigger party.

    I am usually working on a kind of hybrid projects, I create a fla with assets and code runnable from the IDE, and use the resulting swf as an injection swf in FlashDevelop. The cool thing of working this way is that -seeing the project is hybrid and all- you can either work on the project in the Flash IDE, or crank some code in FlashDevelop. There are a few drawbacks however.

    • you are using an swf which already contains all code as an injection swf. Since we use only intrinsic mx classes, we can’t use the keep flag to remove all classes from the swf, since we lose the mx classes from the swf. However especially refactoring where new superclasses are introduced or interfaces, requires recompilation of the injection swf in the Flash IDE. And in general it’s bad practice, and bloates your swf
    • you need the code to export the swf from the IDE
    • you need the injection swf to run your application from FlashDevelop

    Especially when working with a designer where the designer (more…)

    Flash Frameworks Revisited

    Saturday, October 20th, 2007

    On my long list of plans for this year was to dive into the world of Flash Frameworks.
    Only thing is that it has taken me so long, that the world has moved on to Flex Frameworks, but that’s beside the point.

    I wanted to dive into frameworks because I heard all these people talk about how great frameworks are and how they’ve helped people build great applications etc.

    A quick recap of my first impressions/experiences: (more…)

    Local Flash Content And SSL

    Tuesday, August 14th, 2007

    We are in the process of migrating one of our largest eLearning systems to SSL and Active Directory. Some of the Learning Objects within this system are pretty complex and I’ve implemented a mechanism which allows you to test them standalone.

    However during the migration to SSL these objects stopped working when run locally, from the IDE or from FlashDevelop.

    I tried to wrap my head around why this was happening, since I’ve been doing less and less with serverside content and certificates these past few years.

    Luckily I found this URL which described the problem quite accurate.

    Http:// content cannot always access https:// content it seems, but the invalid security certificate was the biggest issue for us.

    Our system admin Roy Olthof quickly jumped in, installed a valid certificate and tadaaaaa. Local content could access https content again. Note that we were accessing https content on our own test server, which didnt have a certificate installed.

    In addition the Flash content kept giving me the mixed content (secure and unsecure) warning. After changing all the http://’s in the macromedia/adobe codebases (contained within the object and embed tags) this disappeared as well.

    Flash Reflection package

    Friday, July 6th, 2007

    In the ongoing work on our internal framework, this week has been dedicated to rewriting the reflection package. A reflection package in general is responsible for providing you with names for your objects.

    For example if you use:
    ReflectUtil.getName (Stage);

    the result would be:
    “Stage”

    Very handy for loggers and stuff. As a matter of fact my current reflection package is the package integrated in Xray). That implementation is pretty solid & simple however some things are bothering me about it, and I have partially solved them at the moment. I don’t think it’s going to replace the simple package anytime soon, but I do know the new package rocks.

    At the moment it can tell the names for all packages, classes and functions and whether a function is static or not. No references are kept between the object being reflected and the reflection object itself.

    In addition methods are provided to resolve a reflected object to the object being reflected and vice versa. It includes a basic visitor implementation so to act on the class tree you no longer have to deal with all the nitty gritty details of methods, properties etc.

    At the moment I’m working on optimizing the implementation and synchronizing the source after new code loads. I’m not sure whether I should override the loadMovie function for that or implement a Command queue, with a simple RefreshCodeTreeCommand.

    kk back to work now, I’ll post the result to the flashcoders list when it’s done.

    Image Perspective Effect

    Monday, July 2nd, 2007

    Very rudimentary image perspective demo. Since it’s performance intensive in AS2 you’ll have to click the more link if it’s not already visible.

    You just got to read the original story by the way, it’s hilarious :) : http://www.b3ta.com/board/496182

    (more…)

    Image Flipping

    Monday, July 2nd, 2007

    A post on the flashcoderlist (http://www.mail-archive.com/flashcoders@chattyfig.figleaf.com/msg34296.html) asking about an image turn around effect got me coding for 2 hours in a row until I finished it and realized my effect was not quite similar to what was required (http://www.ja-ik-doe-mee.be/).

    Anyway I liked it nonetheless so what-the-heck :), posting it anyway :)

    You can download this example here (Flash IDE & FlashDevelop / MTASC compatible).

    flash try-catch

    Tuesday, June 26th, 2007

    Flash Try Catch not catching custom Error Subclasses.

    Last week I’ve been working on a custom error class for flash (as 2). This error class will become the key error handling mechanism in our framework. The base error class in our framework will be a RuntimeException.

    What makes this class special is:

    • uncaught top level errors can be dispatched to a catch all handler
    • it contains the error cause, and the parent error
    • it contains a subcode

    Not all that special however the first item makes this an (at least to us) indispensable asset in our framework.

    Normally people have different ways of handling errors in Flash:

    • they ignore the fact errors occur and remain blissfully ignorant
    • they return some kind of errorcode or provide a method for error detection
    • they use the try-catch exception mechanism

    In my opinion the easiest way to handle errors is to:

    • handle them at the level they occur
    • throw an Exception and let the caller handle it

    Ignoring the fact errors can occur, or adding lots of methods to the signature of an object to allow (but not force) a client to detect errors are not really options I’d like to consider.

    However throwing exceptions involves some intricacies, the two most important being:

    • it requires knowledge of lower level library errors and thus couples high level code to your libraries if you are not aware of this issue. In practice this usually means converting errors from one level to the next, or catching errors in general and not specific errors. So instead of throwing your webservice exception all the way to the frontcontroller, you catch the exception, convert it into a more general DataSourceFailureException and throw that.
    • it requires knowledge THAT code throws exceptions at all. RuntimeExceptions are not checked (checked exception do not exist in Flash), therefore the compiler does not enforce them.
    • displaying uncaught exceptions

    The base error class in Flash is the Error class.
    If you use:

    throw new Error("test");

    your swf will show “test” in the trace output BUT only if you run in the IDE.

    What our RuntimeException class does is the following:

    • it extends Error, so you can use it through throw new RuntimeException();
    • it sets an interval to run after the current callstack unwinds, pushing itself onto a list of not yet handled errors
    • it allows itself to be consumed, removing itself from the list of not yet handled errors

    After the current callstack unwinds, the interval kicks in. Two things might have happened.
    One, the error may have been caught and consumed :


    catch (e:....) {
    //show and handle error here, never just catch it, that negates the use of error handling
    ....
    e.consume(); //consume the error so it doesnt propagate any further
    }

    Two, the error may not have been consumed.

    If the error has been consumed, it would have removed itself from the list of unhandled errors.
    The moment the interval kicks in, all errors that are still unhandled at that moment are passed to an error handler.
    If the RuntimeException class cannot find an error handler, it creates a default error handler, which does nothing more than create a textfield at the stage and print error information to it.

    In effect what this does is that you can throw exception throughout your code, which you should catch and handle.
    However, if you forget to catch one, it will show up at runtime on your stage instead of remain hidden.

    One step further and you can imagine it is very easy to implement an Assert class with an AssertionFailedException.

    The assert class can be used in your code, for example:

    public function setParent (pParent:MovieClip) {
    Assert.assert (pParent != null, "Parent movieclip cannot be null.");
    .....
    }

    If you fail to pass a reference, the assertion will fail and a message will show up on your screen. Combining this with our reflection package, the message on our screen looks something like:


    ASSERTION_FAILED in MyClass.setParent, called from MyClassB.myMethod, with parameters ......

    Ofcourse this check could be even more extensive including runtime type checking, but we should wonder how far we should take this. In most cases, compiling using MTASC with the strict flag, most type checking will already have been done. Ofcourse calling the method like:


    setParent (myClips["clip")

    circumvents typechecking, and might cause some subtle errors which do not trigger exceptions.

    In some cases, adding a type check is easy:

    Assert.assert (MovieClip(pParent) != null, "Parent movieclip cannot be null.");

    However if you do this using an array:

    Assert.assert (Array(pArray) != null, "Given array cannot be null.");

    it will work as expected in MTASC but not in the Flash IDE, since MTASC will cast it, but the Flash IDE will create a new array for you. In other words, this would require you to implement some more extensive checks.

    Which brings me to another framework class:
    ReferenceValidator

    The Reference validator is an alternative to the Assert class, specifically created for testing references for null and their types.

    A common scenerio is where you wrap a clip with your own screen class. The screen class needs a reference to the clip and the components on it, which is where the ReferenceValidator comes in. It copies all the references for you from the clip to the wrapper, testing the values for their types and null (if required).

    Ok, that’s it for now, I hope to post more on the framework coming into being at the moment.

    Before I forget:
    One major bug I encountered is that in order to catch a custom error you have to specify the full path to the error.
    So in other words:


    catch (e:MyCustomError) {

    }

    will not work, whereas :


    catch (e:my.full.package.to.my.error.path.MyCustomError) {

    }

    will work.

    Very annoying. Ah well such is life.

    AsSetPropFlags Explained

    Thursday, June 21st, 2007

    You might stop reading here, everything you need to know is in the provided example.

    So you have decided to read on. Yes, I’m still doing AS2. I know, it’s sad, and I’m never gonna get my band started (weird purple tentacle sucking noises). But believe or not, I still love it :).
    One of the things on my todo list was understanding the AsSetPropsFlags demon. As with all things, once you do understand them, you can’t understand why it took you so long.

    AsSetPropFlags is simple. Really. Assuming you know your binary numbers, and I assume you do. But if you don’t check the example below and the utility classes provided.

    So now I’m going to try and explain it to you :). Note that I only have used it in Flash 7 and above, so don’t ask me about all the flash 5 and flash 6 weirdness involved.

    Properties and their attributes

    Before diving into _global.ASSetPropFlags let us discuss properties first. Properties are part of an object.

    For example:


    var lObj:Object = new Object();
    lObj ["testProp"] = "testValue";

    gives us an object with a single property ‘testProp’.

    In flash these properties have certain attributes, just as files in your filesystem can have a read only attribute, so can a property of your object. Which attributes do you ask? These:

    * the hidden attribute: a property can be visible or hidden, meaning for … in loops will or will not enumerate over the property
    * the protected attribute: a property can be deletable or not, meaning delete obj.prop can throw away the object stored in obj.prop or not
    * the read only attribute: a property can be overwritable or read only, meaning you can assign store new values in the property or not

    A property might have default values set. In the previous example where a new object was created, the default values are (visible, deletable, overwritable). Some other properties such as _global might have all their properties hidden.

    I don’t want to go into the ‘why would you need this’ too much, since you probably already know or you wouldn’t be reading this, but sometimes it might be necessary to be able to enumerate over all hidden objects for example in order to implement something such as reflection.

    Now we are almost getting to explaining _global.ASSetPropFlags.

    Attribute representation and storage

    A question to be answered first is HOW are these attributes stored. To be honest I don’t have a clue. Somewhere with the object. This is part of why it’s so confusing. These attributes are stored, they have a representation, and apparently can be altered through _global.ASSetPropFlags, but we cannot retrieve them directly to print them (except through a little trick, but we’ll get to that).

    Let’s check the representation of these attributes first. Although we cannot directly retrieve them, some smart minds have figured them out by checking their findings with the documentation from Adobe (thanks John :)).

    Basically: Each property has a bitflag, consisting of 3 bits, one bit for each attribute:
    bit 1 - hidden (0 no, 1 yes)
    bit 2 - protected (0 no, 1 yes)
    bit 4 - read only (0 no, 1 yes)

    As said, you cannot retrieve these directly, but you can test them. If I tell you anObject has a property aProperty, you can check if you encounter it while enumerating, check if you can delete it, and check if you can overwrite it. Based on your findings you know the bitflags. Luckily this code was already available on osflash.org, and I’ve included the snippet in the ObjectUtil.as contained in the download (check the getPropertyFlags method). (Note that the code is not completely the same, since the original modifies the flags while testing).

    So… now we know about attributes, attribute representation in binary format, and retrieving the bitflags for a property. But that’s not the end of it, we might want to alter these attributes as well. That is where _global.ASSetPropFlags comes in.

    You might *still* stop reading here, everything you need to know is in the provided example. All the _global.ASSetPropFlags calls and intricacies are neatly wrapped in that class.

    _global.ASSetPropFlags in detail

    The _global.ASSetPropFlags method has the following signature:

    _global.ASSetPropFlags(pObj:Object , pProp:Object , pBitSet:Number , pBitClear:Number)

    ASSetPropFlags takes four arguments (note the global to satisfy MTASC):

    @param pObj
    - the object whose properties you want to affect

    @param pProp a specification of the properties whose flags you want to change
    - null -> all properties,
    - “propName” -> a single prop,
    - “p1,p2″ -> multiple properties,
    - [”p1″, “p2″] -> multiple properties

    @param pBitSet
    - any bits that are 1 are set on the target property, zero bits are ignored (so whatever you specify here it will NEVER CLEAR any bits)

    @param pBitClear
    - any bits that are 1 are cleared on the target property, zero bits are ignored (so whatever you specify here it will NEVER SET any bits)

    Confused about the pBitSet and pBitClear?
    Remember that you would use the ASSetPropsFlags to alter specific attributes, eg you wish unhide all properties in _global. So you know which bit you want to change, but you don’t know the bits for all the other properties, so pBitSet let’s you specify only the bits you want to set. It does not let you specify which bits to ‘unset’ so:

    Assume we have:

    var lObj:Object = new Object();
    lObj ["testProp"] = "testValue";
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 0
    _global.ASSetPropFlags(lObj , "testProp", 1, 0); //sets bit 1
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 1
    _global.ASSetPropFlags(lObj , "testProp", 2, 0); //sets bit 2, but does not unset bit 1
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 3
    

    So you see the pBitSet only specifies the bits that are set, first we pass bit 1 and then bit 2, in binary 011, which is 3 in decimal. In other words:

    001
    010
    ---
    011

    So how do we clear bits then? Right through the bBitClear flag. It works exactly the same, however instead of setting bits, the specified bits are cleared. And they are cleared BEFORE the bits specified in pBitSet are applied.

    Referring to the previous example again:

    var lObj:Object = new Object();
    lObj ["testProp"] = "testValue";
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 0
    _global.ASSetPropFlags(lObj , "testProp", 1, 0); //sets bit 1
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 1
    _global.ASSetPropFlags(lObj , "testProp", 2, 1); //clear bit 1, sets bit 2,
    trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 2
    

    Ok, so you might say: what the.. ? How can I ever be sure what flags I end up with? Well thats very simple. If you want to be entirely sure and in control of the endresult you use:

    _global.ASSetPropFlags(lObj , "testProp", newFlags, 7); //clear all bits, sets newFlags
    

    You clear all bits and set whatever you want. However usually you want to flip certain bits so for enabling a certain bit you use:

    _global.ASSetPropFlags(lObj , "testProp", bitToSet, 0); //clear nothing, set my bit
    

    and to clear it:

    _global.ASSetPropFlags(lObj , "testProp", 0, bitToClear); //clear my bit, set nothing.
    

    If you’d rather see it in formula form:

    The formula is:
    oldBit ^(oldBit & clearBit) | setBit

    where oldBit represents the property’s current flags. The oldBit and clearBit are AND-ed together first giving you only those bits from clearBit that are actually in oldBit. Then this value is XOR against oldBit, meaning the bits from clearBit that are in oldBit are flipped to 0. Last but not least we OR it against all bits in setBit.

    You might have seen (oldBit ^ clearBit) ^ setBit, that formula is not correct:

    var oldBit:Number = 1;
    var clearBit:Number = 2;
    var setBit:Number = 3;
    trace (oldBit ^(oldBit & clearBit) | setBit); //--> RIGHT FORMULA traces 3
    trace ((oldBit ^ clearBit) ^ setBit);  //--> WRONG FORMULA traces 0
    

    Download example

    If you’d rather see in in action, everything you need to know is in the provided example.

    Credits

    I would like to thank John Grden for his (code) groundwork and assistance in getting my head around the specifics. Other credits go to the people who created the osflash documentation on http://osflash.org/flashcoders/undocumented/assetpropflags especially Jerome Cordiez

    If I forgot to give you due credit, or you would like to see it changed, drop me a line!