Here at Grooveshark, we’re using SWFAddress for deep linking/browser history support in our flagship product.

It’s been working great, except for one of our developers on Arch Linux using Gran Paradiso. We hadn’t been getting any user complaints, so that particular bug pretty much fell to the bottom of the stack. Until a few days ago, when we started get the same complaint from users on Debian/Iceweasel.

Now, since SWFAddress says that it officially supports Firefox v1 and up, I had pretty much assumed it would work fine on all Gecko browsers. In fact, since Iceweasel technically *is* Firefox (and wow, is the history behind *that* an interesting tale), there shouldn’t have been any reason for it to fail.

So off I went to poke about in the SWFAddress source, where I found that Firefox detection is made by matching the string ‘Firefox’ in the user-agent string. Also, when SWFAddress cannot identify the browser, it will refresh the page with the hash removed, which is probably a great fallback for a lot of Flash/Ajax sites, but winds up causing some problems for us.

Well Iceweasel doesn’t have ‘Firefox’ in it’s user agent string. It has ‘Iceweasel’ instead. Same with Gran Paradiso. So, I’ve written a patch for SWFAddress to fix the problem. If SWFAddress doesn’t match either Firefox or Camino (the two Gecko browsers that it officially supports), it will fall back on navigator.product to detect any other Gecko browser, regardless of what it calls itself in its user-agent string.

We’ve got it up live on http://listen.grooveshark.com now, and it seems to be working fine.

I’m going to email asual to see if it can get added to the actual trunk, but in the meantime, if you’re using SWFAddress and would like to use my patch, you can grab it here SWFAddress Gecko Patch.

Just check out the SWFAddress trunk at https://swfaddress.svn.sourceforge.net/svnroot/swfaddress/trunk. I wrote the patch off of Revision 702.

EDIT
So my first version of this didn’t work in Chrome/Safari. Apparently WebKit reports its navigator.product as “Gecko” despite the fact that it’s, you know, WEBKIT. I’ve uploaded a new version of the patch, so if you grabbed it before 11:20 am eastern on Feb 4, grab it again for the fix.

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.

A couple weeks ago I needed to easily convert HTML entities in a string back to their normal representation, but I didn’t really find anything nice, and wound up just using str.replace(/&/g, "&").replace(/'/g, "'"); since those were the only characters I was having a problem with at the time.

But today I went searching again for something better, and found a really great way to escape and unescape HTML entities. Not sure why I didn’t find his post the first time, I guess my Google-fu was weak that day.

Anyway, I’ve wrapped his methods up in a little helper class, and it works great:

package com.grooveshark.utils
{

    public class HTMLEntityUtils
    {
        import flash.xml.XMLDocument;
        import flash.xml.XMLNode;
        import flash.xml.XMLNodeType;

        public function HTMLEntityUtils()
        {
        }

        public static function htmlEscape(str:String):String
        {
            return XML(new XMLNode(XMLNodeType.TEXT_NODE, str)).toXMLString();
        }

        public static function htmlUnescape(str:String):String
        {
            return new XMLDocument(str).firstChild.nodeValue;
        }
    }
}

Hope it helps someone else!