TL;DR: Adding any non-built-in functions to Array.prototype AND Function.prototype will cause the IE8 native JSON parser to get a stack overflow when parsing any JSON that contains an array, but only when you also pass a reviver function into JSON.parse().
This started out as a question, but I answered my own original question, so now I'll ask: can anyone think of a work-around for this IE8 bug that doesn't involve eliminating all JS libraries that modify Array.prototype and Function.prototype?
Original question:
I have about 13k of JSON data to parse. The structure of the data is an object with a single value that is a nested array.
{ 'value':[[ stuff ], [ more stuff], [ etc ]] }
I'm using json2.js, which defers to the browser native JSON.parse when available. I'm passing a reviver function into JSON.parse to handle dates properly. When IE8 is in IE7 emulation mode (which causes it to use the script-based json2.js parser) everything works fine. When IE8 is in IE8 mode (which causes it to use the browser-native JSON parser) it blows up with an "out of stack space" error. Firefox and Chrome, of course, work just fine with their browser-native JSON parsers.
I've narrowed it down to this: if I pass even a do-nothing reviver function into JSON.parse, the IE8 native parser gets the stack overflow. If I pass in no reviver function, the IE8 native parser works fine, except it doesn't parse dates correctly.
// no error:
JSON.parse(stuff);
// "out of stack space" error:
JSON.parse(stuff, function(key, val) { return val; });
I'm going to play with my JSON data, to see if less data or less nesting of the data can avoid the error, but I was wondering if anyone had seen this before, or had any other suggested work-arounds. IE8 is slow enough already, it would be a shame to disable native JSON for that browser because of this bug.
UPDATE: In other cases, with different JSON data, I'm getting a javascript error "$lineinfo is undefined" when I use the IE8 native parser with a reviver function, and no error if I use no reviver function. The string "$lineinfo" does not appear anywhere in any of my source code.
UPDATE 2: Actually, this problem seems to be caused by Prototype 1.6.0.3. I was unable to reproduce it in an isolated test page until I added in the Prototype library.
UPDATE 3:
The reason prototype.js breaks the IE8 native JSON parser is this: Adding any non-built-in functions to Array.prototype AND Function.prototype will cause the IE8 native JSON parser to get a stack overflow when parsing any JSON that contains an array, but only when you also pass a reviver function into JSON.parse().
The Prototype library adds functions to both Array.prototype and Function.prototype, but this applies equally to any other library that does the same thing. This bug in the IE JSON parser is exposed by Prototype and Ext, but not jQuery. I haven't tested any other frameworks.
Here is a completely stand-alone reproduction of the problem. If you remove the Function.prototype line, or the Array.prototype line, or remove the array from the JSON string, you won't get the "out of stack space" error.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
Function.prototype.test1 = function() { };
Array.prototype.test2 = function() { };
window.onload = function()
{
alert(JSON.parse('{ "foo": [1,2,3] }', function(k,v) { return v; }));
}
</script>
</head>
<body>
</body>
</html>
It seems to work okay here:
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 above paragraph explains why my reviver function looks the way it does. My first attempt at test code was:
Obviously if this reviver function is applied to the
address
node above after being applied to all its children, I've completely destroyed theaddress
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:
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.
A solution is to remove the native JSON.parse on IE8 and replace it with the JSON.parse from the json2.js lib:
Add:
… and then include:
This will trigger json2 to replace the JSON.parse with its own version
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:
This was just patched. http://support.microsoft.com/kb/976662
http://msdn.microsoft.com/en-us/library/cc836466(VS.85).aspx
is transforming a String into an Object in IE 8.