Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Friday, June 20, 2008

Weird Issue with responseXML and JSON in FF3

I recently (like today) upgraded Mint to support FireFox 3. I was not expecting this to be a difficult process, because there is no drastic difference between the JavaScript engines of FF3 and FF2. However, I was surprised to find that many parts of the site did not work. Upon further studied I realized the most peculiar behavior. Upon receiving a JSON response from the server using GetXmlHttpObject(), FF3 populates the XmlHttpObject.responseXML with the following:

Example 1: Parser Error

<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML-Processing error: not well formed Address: URL_BEING_REQUESTED Line Number 1, Column 1:<sourcetext>JSON_OBJECT^</sourcetext></parsererror>

In all other browsers, including FF2, the responseXML value is ‘null’ when the response is a JSON object, and occasionally ‘undefined’, but never populated with a value. On Mint we have several different code paths, depending on if a response is an XML or JSON object, or just text. Because the responseXML was not NULL, the code assumed that all my JSON Objects were XML and crashed.

Obviously, this was unacceptable, so I wrote a hack that fixes FF3. If you do any responseXML detection, then the following hack might help you as well:

Example 2: Parser Error Fix

var doc = (data.responseXML); var docString = Dom.getContentAsString(doc); var isXML = $defined(doc) && 0 !== docString.indexOf('<parsererror ');

First, note that the parentheses are required, otherwise FF3 (and possibly other browsers) will set the ‘doc’ to ‘undefined’, even if it has a value. The method ‘getContentAsString’ iterates through the nodes inside of the XmlHttpObject, in a browser safe way, turning everything into a String (useful with ‘innerHTML’). This was originally modeled after a method in OpenRico by the same name. If ‘doc’ is not defined, then isXML is false and everything works as before. Wowever, if ‘doc’ is defined then we look at its content and see if it starts with parsererror. When it does, we assume that the response was not suppose to be XML.

This works for almost every case, with the possible exception that your response is supposed to be XML, and does actually have an XML parser error. However, since that is another issue and I cannot think of any reason why one would intentionally return XML with a parse error, I believe this hack solves the problem.

I have also posted on the FireFox forums and am hoping to here back from somewhere there on why the behavior of ‘responseXML’ has changed (click here to see my post).

—–

I have resolved the issue. The mime-type was not being properly set to ‘text/json’ in the server-side code. However, as I read on Mozilla Docs XMLHttpRequest, responseXML should be null if you do not explicitly send ‘text/xml’ or if the XML is not well formed. So unless I’m missing something, it should still be null, and not a parser error.

Debugging this also, made me ask myself, “Why am I not using the mime-type for response detection”? Kinda of a “Doh” moment. This is a much more robust way of type detection and if you use YUI’s Connect.js, you have the mime-type readily available in the data Object passed into your AJAX callback function. Simply do the following:

var ajaxCallback = function(data) { var isMimeType = data.getResponseHeader['Content-Type'].indexOf(mimeType); };

Where ‘mimeType’ is the type that you wish to test for, such as ‘text/json’.

posted by Matt Snider at 3:46 pm  

5 Comments »

  1. The link to your Mozilla post is broken.

    Comment by Rob — June 23, 2008 @ 10:26 am

  2. Thanks rob, the URL was truncated for some reason. Anyway, I have fixed it.

    Comment by Matt Snider — June 23, 2008 @ 11:23 am

  3. Perhaps there is something on this Mozilla page, that explains the problem. FF3 had number of changes to xmlhttp handling:

    http://developer.mozilla.org/en/docs/XMLHttpRequest

    Comment by tt — June 24, 2008 @ 6:04 am

  4. Thanks tt,

    I took a look at it, which inspired me to take a closer look at my own code. The mime-type wasn’t being properly set, but (I believe) according to the documentation, it should still be null.

    Comment by Matt Snider — June 24, 2008 @ 5:26 pm

  5. Thanks - the server-side mime-type was messing me up too. After search for a client-side solution, this is the only thing that seemed to help me too (using Dojo toolkit).

    Comment by Eric Poulin — July 23, 2008 @ 4:49 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress