IE8 原生 JSON.parse 错误导致堆栈溢出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1288962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
IE8 native JSON.parse bug causes stack overflow
提问by Joel Mueller
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().
TL;DR:将任何非内置函数添加到 Array.prototype AND Function.prototype 将导致 IE8 原生 JSON 解析器在解析任何包含数组的 JSON 时出现堆栈溢出,但前提是您还传递了一个 reviver 函数进入 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?
这开始是一个问题,但我回答了我自己的原始问题,所以现在我要问:任何人都可以想出解决此 IE8 错误的方法,而不涉及消除所有修改 Array.prototype 和 Function 的 JS 库。原型?
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.
我有大约 13k 的 JSON 数据要解析。数据的结构是一个具有单个值的对象,它是一个嵌套数组。
{ '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.
我正在使用 json2.js,它在可用时遵循浏览器本机 JSON.parse。我正在将一个 reviver 函数传递给 JSON.parse 以正确处理日期。当 IE8 处于 IE7 仿真模式(这会导致它使用基于脚本的 json2.js 解析器)时,一切正常。当 IE8 处于 IE8 模式(这会导致它使用浏览器原生 JSON 解析器)时,它会因“堆栈空间不足”错误而崩溃。当然,Firefox 和 Chrome 与它们的浏览器原生 JSON 解析器一起工作得很好。
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.
我把它缩小到这个范围:如果我将一个什么都不做的reviver 函数传递给JSON.parse,IE8 本地解析器就会得到堆栈溢出。如果我没有传入 reviver 函数,IE8 本机解析器就可以正常工作,除非它不能正确解析日期。
// 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.
我将使用我的 JSON 数据,看看更少的数据或更少的数据嵌套是否可以避免错误,但我想知道是否有人以前见过这个,或者有任何其他建议的解决方法。IE8 已经足够慢了,因为这个错误而禁用该浏览器的原生 JSON 是一种耻辱。
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.
更新:在其他情况下,对于不同的 JSON 数据,当我使用带有 reviver 函数的 IE8 本机解析器时,我收到一个 javascript 错误“$lineinfo 未定义”,如果我不使用 reviver 函数,则没有错误。字符串“$lineinfo”没有出现在我的任何源代码中。
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 2: 实际上,这个问题似乎是由 Prototype 1.6.0.3 引起的。在我添加到 Prototype 库之前,我无法在单独的测试页面中重现它。
UPDATE 3:
更新 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().
prototype.js 破坏 IE8 原生 JSON 解析器的原因是:向 Array.prototype AND Function.prototype 添加任何非内置函数将导致 IE8 原生 JSON 解析器在解析任何包含数组的 JSON 时出现堆栈溢出,但前提是您还向 JSON.parse() 传递了一个 reviver 函数。
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.
Prototype 库向 Array.prototype 和 Function.prototype 都添加了函数,但这同样适用于任何其他做同样事情的库。IE JSON 解析器中的这个错误由 Prototype 和 Ext 公开,但不是 jQuery。我还没有测试过任何其他框架。
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.
这是问题的完全独立的再现。如果删除 Function.prototype 行或 Array.prototype 行,或者从 JSON 字符串中删除数组,则不会出现“堆栈空间不足”错误。
<!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>
采纳答案by Luke
回答by Anders
A solution is to remove the native JSON.parse on IE8 and replace it with the JSON.parse from the json2.jslib:
一个解决方案是删除 IE8 上的原生 JSON.parse 并将其替换为json2.js库中的 JSON.parse :
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 用它自己的版本替换 JSON.parse
// 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.
这种方法的一个问题是 json2.js 解析方法比原生方法慢。
回答by Joel Mueller
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:
微软的 Eric Law 说:
The JavaScript team reports that this is a known issue in the JavaScript engine.
JavaScript 团队报告说,这是 JavaScript 引擎中的一个已知问题。
回答by James Hutchison
An extension of this issue (which is still present in IE9), is the native JSON.stringify function crashes IE when there is:
这个问题的一个扩展(IE9 中仍然存在),是原生的 JSON.stringify 函数在出现以下情况时会导致 IE 崩溃:
- a large object graph
- the object graph references jQuery 'data' objects.
- the object graph is circular.
- 大对象图
- 对象图引用 jQuery 'data' 对象。
- 对象图是圆形的。
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.
在这种情况下,我们的解决方法是在 stringify 函数上使用替换函数,以在特定对象属性上返回 null 并停止遍历对象图。
回答by Grant Wagner
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.
问题是 Internet Explorer 8 安装损坏(您是否尝试在同一个 Windows 安装上运行多个 Internet Explorer 副本?)或者您的输入错误。
You may also want to read Native JSON in IE8. This particular paragraph may be of interest:
您可能还想在 IE8 中阅读本机 JSON。这个特定的段落可能很有趣:
The optional revive argumentis a user defined function used for post parse changes. The resulting object or array is traversed recursively, the reviverfunction 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′ afterall its members are ‘revived′.
可选的revive 参数是一个用户定义的函数,用于解析后的更改。递归遍历生成的对象或数组,将reviver函数应用于每个成员。每个成员值都替换为reviver返回的值。如果 reviver 返回 null,则删除对象成员。遍历和调用 reviver 是按后序完成的。这是正确的; 在所有成员都“复活”之后,每个对象都被“复活”。
The above paragraph explains why my reviver function looks the way it does. My first attempt at test code was:
上一段解释了为什么我的 reviver 功能看起来如此。我第一次尝试测试代码是:
function (key, val) {
return val + '-reviver!';
}
Obviously if this reviverfunction is applied to the addressnode above after being applied to all its children, I've completely destroyed the addressobject.
显然,如果这个reviver函数address在应用于其所有子节点之后应用于上面的节点,我已经完全破坏了该address对象。
Of course, if the test of your reviveris 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.
当然,如果您的reviver测试像您在问题中描述的一样简单,那么某些全局循环引用不太可能导致您看到的问题。我仍然认为它指向损坏的 Internet Explorer 或错误的数据。
Can you edit your questionand post a sample of actual data that exhibits the problem so I can try it here?
您能否编辑您的问题并发布显示问题的实际数据样本,以便我可以在这里尝试?
回答by Got_IE8_Yessss
eval(Ext.decode("{"foo":"bar"}"));
is transforming a String into an Object in IE 8.
在IE 8中将字符串转换为对象。

