Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE8 native JSON.parse bug causes stack overflow

This was just patched. http://support.microsoft.com/kb/976662

http://msdn.microsoft.com/en-us/library/cc836466(VS.85).aspx


A solution is to remove the native JSON.parse on IE8 and replace it with the JSON.parse from the json2.js lib:

Add:

<script type="text/javascript">
if (jQuery.browser.msie && jQuery.browser.version.indexOf("8.") === 0) {
    if (typeof JSON !== 'undefined') {
        JSON.parse = null;
    }
}
<script>

… and then include:

<script type="text/javascript" src="json2.js"></script>

This will trigger json2 to replace the JSON.parse with its own version

// json2.js
...
if (typeof JSON.parse !== 'function') {
    JSON.parse = function (text, reviver) {
...

After that the parse should work again.

One problem with this approach is that the json2.js parse method is slower than the native one.


I've had this question with no accepted answers sitting around for quite a while, so just to get rid of it, I'll answer it myself.

Eric Law at Microsoft says:

The JavaScript team reports that this is a known issue in the JavaScript engine.


It seems to work okay here:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test</title>
</head>
<body>
<pre>
<script type="text/javascript">
document.writeln('');
var o = {
    "firstName": "cyra",
    "lastName": "richardson",
    "address": {
        "streetAddress": "1 Microsoft way",
        "city": "Redmond",
        "state": "WA",
        "postalCode": 98052
    },
    "phoneNumbers": [
        "425-777-7777", 
        "206-777-7777"
     ]
};
var s = JSON.stringify(o);
document.writeln(s);
var p = JSON.parse(s, function (key, val) {
    if (typeof val === 'string') return val + '-reviver!';
    else return val;
});
dump(p);

function dump(o) {
    for (var a in o) {
        if (typeof o[a] === 'object') {
            document.writeln(a + ':');
            dump(o[a]);
        } else {
            document.writeln(a + ' = ' + o[a]);
        }
    }
}
</script>
</pre>
</body>
</html>

The problem is either a corrupt Internet Explorer 8 install (are you trying to run multiple copies of Internet Explorer on the same Windows install?) or your input is bad.

You may also want to read Native JSON in IE8. This particular paragraph may be of interest:

The optional revive argument is a user defined function used for post parse changes. The resulting object or array is traversed recursively, the reviver function is applied to every member. Each member value is replaced with the value returned by the reviver. If the reviver returns null, the object member is deleted. The traversal and the call on reviver are done in postorder. That’s right; every object is ‘revived´ after all its members are ‘revived´.

The above paragraph explains why my reviver function looks the way it does. My first attempt at test code was:

function (key, val) {
    return val + '-reviver!';
}

Obviously if this reviver function is applied to the address node above after being applied to all its children, I've completely destroyed the address object.

Of course, if the test of your reviver is as simple as you describe in your question, it is unlikely that some global circular reference is leading to the problem you're seeing. I still think it points to a broken Internet Explorer or bad data.

Can you edit your question and post a sample of actual data that exhibits the problem so I can try it here?


An extension of this issue (which is still present in IE9), is the native JSON.stringify function crashes IE when there is:

  1. a large object graph
  2. the object graph references jQuery 'data' objects.
  3. the object graph is circular.

We're unsure which specific point causes the crash.

Our workaround in this instance was to use a replacer function on the stringify function to return null on a particular object property and stop the object graph from being traversed.