Ответ 1
Это было просто исправлено. http://support.microsoft.com/kb/976662
http://msdn.microsoft.com/en-us/library/cc836466(VS.85).aspx
TL; DR: Добавление каких-либо не встроенных функций в Array.prototype И Function.prototype заставит исходный JSON-анализатор IE8 получить переполнение стека при анализе любого JSON, содержащего массив, но только тогда, когда вы также передаете функцию reviver в JSON.parse().
Это началось как вопрос, но я ответил на свой собственный оригинальный вопрос, поэтому теперь я спрошу: может ли кто-нибудь подумать об обходном пути для этой ошибки IE8, которая не включает в себя устранение всех JS-библиотек, которые изменяют Array. прототип и Function.prototype?
Оригинальный вопрос:
У меня есть около 13k данных JSON для разбора. Структура данных - это объект с единственным значением, являющимся вложенным массивом.
{ 'value':[[ stuff ], [ more stuff], [ etc ]] }
Я использую json2.js, который отдает предпочтение браузерному родному JSON.parse, когда он доступен. Я передаю функцию reviver в JSON.parse для правильной обработки дат. Когда IE8 находится в режиме эмуляции IE7 (что заставляет его использовать парсер json2.js, основанный на script), все работает нормально. Когда IE8 находится в режиме IE8 (что заставляет его использовать собственный анализатор JSON на основе браузера), он взрывается с ошибкой "из пространства стека". Firefox и Chrome, конечно же, отлично работают с их парсерами JSON, основанными на браузере.
Я сузился до этого: если я передам в JSON.parse даже функцию do-nothing reviver, исходный парсер IE8 получит переполнение стека. Если я не передаю функцию reviver, собственный парсер IE8 отлично работает, за исключением того, что он правильно не обрабатывает даты.
// no error:
JSON.parse(stuff);
// "out of stack space" error:
JSON.parse(stuff, function(key, val) { return val; });
Я буду играть со своими данными JSON, чтобы увидеть, может ли меньше данных или меньше вложенности данных избежать ошибки, но мне было интересно, видел ли кто-нибудь это раньше или какие-либо другие предлагаемые варианты работы. IE8 уже достаточно медленный, было бы позором отключить собственный JSON для этого браузера из-за этой ошибки.
UPDATE: В других случаях, при использовании разных данных JSON, я получаю ошибку javascript "$ lineinfo is undefined", когда я использую собственный синтаксический анализатор IE8 с функцией reviver, и нет ошибки, если я не использую функцию reviver, Строка "$ lineinfo" не отображается нигде ни в одном из моих исходных кодов.
ОБНОВЛЕНИЕ 2: На самом деле эта проблема, по-видимому, вызвана прототипом 1.6.0.3. Мне не удалось воспроизвести его на отдельной тестовой странице, пока я не добавлю в библиотеку Prototype.
ОБНОВЛЕНИЕ 3:
Причина, по которой prototype.js ломает собственный синтаксический анализатор JSON IE8, заключается в следующем: добавление каких-либо не встроенных функций в Array.prototype И Function.prototype заставит исходный JSON-анализатор IE8 получить переполнение стека при анализе любого JSON, который содержит массив, но только тогда, когда вы также передаете функцию reviver в JSON.parse().
Библиотека Prototype добавляет функции как для Array.prototype, так и для Function.prototype, но это в равной степени относится к любой другой библиотеке, которая делает то же самое. Эта ошибка в синтаксисе IE JSON отображается Prototype и Ext, но не jQuery. Я не тестировал другие структуры.
Вот полностью автономное воспроизведение проблемы. Если вы удалите строку 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>
Это было просто исправлено. http://support.microsoft.com/kb/976662
http://msdn.microsoft.com/en-us/library/cc836466(VS.85).aspx
Решение состоит в том, чтобы удалить собственный JSON.parse на IE8 и заменить его на JSON.parse из json2.js lib:
Добавить
<script type="text/javascript">
if (jQuery.browser.msie && jQuery.browser.version.indexOf("8.") === 0) {
if (typeof JSON !== 'undefined') {
JSON.parse = null;
}
}
<script>
... и затем включить:
<script type="text/javascript" src="json2.js"></script>
Это приведет к тому, что json2 заменит JSON.parse своей версией
// json2.js
...
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
...
После этого синтаксический разбор должен работать снова.
Одна из проблем с этим подходом заключается в том, что метод parse json2.js медленнее, чем собственный.
У меня был этот вопрос без каких-либо принятых ответов, довольно долгое время, поэтому, чтобы избавиться от него, я сам отвечу.
Eric Law в Microsoft говорит:
Команда JavaScript сообщает, что это известная проблема в движке JavaScript.
Кажется, все в порядке:
<!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>
Проблема заключается либо в поврежденной установке Internet Explorer 8 (пытаетесь ли вы запускать несколько экземпляров Internet Explorer при одной и той же установке Windows?) или ваш ввод плох.
Вы также можете прочитать Native JSON в IE8. Этот конкретный пункт может представлять интерес:
Дополнительный аргумент revive - пользователь определенная функция, используемая для пост-анализа изменения. Полученный объект или массив пересекается рекурсивно, функция применяется к каждому члену. Каждое значение элемента заменяется на значение, возвращаемое редактором. Если reviver возвращает null, объект член удален. Обход и призыв к postorder. Это верно; каждый объект "возрожден" после, все его члены "Revived'.
В приведенном выше параграфе объясняется, почему моя функция reviver выглядит так, как она есть. Моя первая попытка тестового кода заключалась в следующем:
function (key, val) {
return val + '-reviver!';
}
Очевидно, что если эта функция reversion применяется к address
node выше, после применения ко всем ее дочерним элементам, я полностью уничтожил объект address
.
Конечно, если тест вашего реверсинга так же прост, как вы описываете в своем вопросе, маловероятно, что какая-то глобальная циклическая ссылка приведет к проблеме, которую вы видите. Я все еще думаю, что это указывает на сломанный Internet Explorer или плохие данные.
Можете ли вы изменить свой вопрос и опубликовать образец фактических данных, которые обнаруживают проблему, поэтому я могу попробовать ее здесь?
Расширение этой проблемы (которая все еще присутствует в IE9), является встроенной функцией JSON.stringify, сбой IE, когда есть:
Мы не уверены, какая именно причина вызывает крах.
Наше решение в этом случае состояло в том, чтобы использовать функцию replacer для функции stringify для возврата null к определенному свойству объекта и прекратить перемещение графика объекта.
eval(Ext.decode("{"foo":"bar"}"));
преобразует строку в объект в IE 8.