IE9 is Worse Than IE6 at Ajax

What is it about Microsoft that, the more they claim their browser is standards-compliant, the harder it is to write code for it that support standards? What is it that makes code just work on all the other browsers, but makes developers jump through hoops to make things work on Internet Explorer? I think it's something of a culture. While other browser developers work towards the spirit of the standards, Microsoft must create an environment where standards-compliance is a forced nuisance rather a goal. Or is something more sinister afoot? Are they actively try to make it hard for developers to create maintainable, standards-compliant applications. Whatever the case, after all the years and years of pain with Internet Explorer 6, Internet Explorer 9 has come along and screwed everything up even more.

In 2005 I wrote a complete web framework, Guise, using my own JavaScript Ajax communication library. (This was before things like JQuery were available.) I labored for hours and hours to make it work under all the major browser at the time, with IE6 problems easily taking over the majority of my time. Essentially my framework sends back XML from the server representing DOM changes, and the JavaScript on the browser synchronizes the web page with the new tree.

First of all, you probably already know that for all the IEs, I have to send back the document as text/html, not application/xhtml+xml, even though my web page is 100% well-formed XML with namespaces and everything, because Internet Explorer freaks out at the thought of XHTML. That I understand and accept. Under IE6, no namespaces were supported either, so I detected this and created my own DOM access code that converted getAttributeNS() calls into the plain old non-namespace-aware getAttribute() calls. And my code puttered right along on Firefox, IE6, and Safari.

Fast forward six years. My code works just as well on Firefox, Safari, and now Chrome—and it works even better, because these browser have become even more standards-compliant, so that a lot of the special cases in my code (to compensate for non-standards-compliance) don't even have any bearing anymore.

Internet Explorer has made a lot of changes, too. In fact, their HTML DOM is now namespace-aware. (That's right, they still don't support application/xhtml+xml, but their text/html DOM is now namespace-aware.) That's a good thing, right? Yes, at first glance. But what about Ajax communication? Remember that my server sends back XML to be patched into the HTML tree? If you know the evil heart of IE, you've probably guessed already that IE does not support namespaces in Ajax XMLHttpRequest.responseXML documents! Yes! Microsoft IE9 supports namespaces in HTML, but not in XML! So my special-case code that saw that IE6 didn't support namespaces now thinks IE9 does support namespaces, so it fails when it tries to process XML returned from the server, giving an ugly:

TypeError: Object doesn't support property or method 'getAttributeNS'.

OK, so I thought I would bite my tongue and litter my code with more special cases to detect when the response XML didn't support namespaces. Oh, but then there are more problems. When I'm patching up the HTML tree with some of the returned XML, naturally I have to import some of the nodes from the returned XML into the document. The best I remember, IE6 didn't support Document.importNode(), so I had to detect this and write my own custom node import function. It was a long beast of a function, with all sorts of nasty special cases because, for example, in IE6 you can't even use Document.createElement() for <button type="button"> or you'll crash your whole web application! But IE9 now supports Document.importNode(). That's a good thing, right? No, it makes it even worse.

IE's definition of "supporting" something really means "we'll put some code behind an API, and this code will be so buggy and error-prone that it will be harder to use than if you had written a replacement yourself." Remember that in IE9 the response XML doesn't support namespaces, but the HTML document does. So when you try to import a node from the Ajax response XML into your document, you get this:

No such interface supported.

Lovely. OK, so I'll screw using Document.importNode() on IE9 and go back to using my custom import code that worked on IE6. Oh, if I could dream. Now that IE9 supports namespaces on the HTML document, my old import code that uses innerHTML won't work anymore, because the fragment of XML I'm bringing in from the (non-namespace-aware) Ajax response uses a namespace prefix, but the particular element that I'm using doesn't declare that namespace! Never mind that the in the Ajax response XML document somewhere up the chain an element declares the namespace, compliant with XML namespace standards. And never mind that the destination document (the namespace-aware HTML document) does support namespaces, and this very prefix is declared higher up in the hierarchy, just as the XML namespace specifications require. Oh, but this isn't XML—it's HTML that's namespace-aware, so maybe Microsoft thinks it can make its own rules. Microsoft always thinks it can make its own rules.

So I'm stuck with code that works on all the other major browsers besides IE9, and code that has worked on IE6 just fine since 2005, but completely crashes on IE9. And even worse, I have yet to see a workaround, because Microsoft's paying lip-service to standards-compliance is worse than no standards-compliance at all. Microsoft still hasn't figured that out. Or maybe that was the plan all along.