So we finally tracked down just how Jay broke Grooveshark Lite the other day.

He apparently managed to trigger a very obscure language bug, that no one has really posted about, though if you dig deep enough into Adobe’s bug tracking system, you can find some reports of, though it’s supposedly fixed as of some version of the compiler that I have no idea if it’s in production yet.

This is all it takes to break Actionscript with a nasty runtime error:


private function breakIt():void
{
    var arr:Array = [];
    for each (var obj:Object in arr) {
        switch ('s') {
            case 's':
                if (null) {
                }
            //break;
        }
    }
}

The key here is the nested for/switch/if and that the expression for the if statement evaluates to false, and that there is nothing in the case after the if.

Uncommenting the commented break statement will prevent the bug. Even a variable declaration on that line will prevent the bug. Removing the switch from inside the for loop will prevent the bug. Notice in this case the loop shouldn’t even be executing: the array is empty. Doesn’t matter, it crashes anyway.

The runtime error this triggers is “VerifyError: Error #1068: CLASSNAME and CLASSNAME cannot be reconciled.” where CLASSNAME is the name of the class that contains the above code.

So if you’re getting the above error in your code, check around for any constructs like the above.

Consider this situation:

You have an MXML component with multiple states. Each of these states has an associated error state that’s based on one of the other states. The overrides for each of the error states is identical – all that’s different is which state each error state is based on. Instead of duplicating the overrides for each error state, you can declare the overrides in an <mx:Array> tag, and use data binding to set the overrides property of each error state to the same array.

Alright, talking about this abstractly is kinda confusing. It will make perfect sense as soon as you see an example:

<mx:Array id="errorOverrides">
    <mx:AddChild relativeTo="{msgWrapper}">
        <mx:Label text="The following errors occurred:" styleName="popupMessageError"/>
    </mx:AddChild>
    <mx:AddChild relativeTo="{msgWrapper}">
        <mx:VBox paddingLeft="15">
            <mx:Repeater id="errorRepeater" dataProvider="{errors}" recycleChildren="true">
                <mx:Text width="{msgWrapper.width-45}" text="{errorRepeater.currentItem}"/>
            </mx:Repeater>
        </mx:VBox>
    </mx:AddChild>
</mx:Array>

<states>
    <mx:State name="twitterBroadcast">
        <mx:SetProperty target="{this}" name="bodyContent" value="{twitterBroadcastBodyContent}"/>
        <mx:SetProperty target="{this}" name="title" value="Broadcast to Twitter"/>
    </mx:State>

    <mx:State name="facebookBroadcast">
        <mx:SetProperty target="{this}" name="bodyContent" value="{facebookBroadcastBodyContent}"/>
        <mx:SetProperty target="{this}" name="title" value="Broadcast to Facebook"/>
    </mx:State>

    <mx:State name="shareError" overrides="{errorOverrides}"/>
    <mx:State name="twitterError" basedOn="twitterBroadcast" overrides="{errorOverrides}"/>
    <mx:State name="facebookError" basedOn="facebookBroadcast" overrides="{errorOverrides}"/>
</states>

This solution seems obvious as soon as you think about how you would go about declaring these states in Actionscript, but in MXML it’s really easy to feel like you would need to declare the overrides over again inside each <mx:State> tag.

Maybe I’m late to the party and everyone else figured this out already, but if not, hopefully this post will help you think about MXML in a new way.