2009-08-17 4 views
31

TL; DR: Добавление любых встроенных функций в Array.prototype И Function.prototype заставит исходный JSON-анализатор IE8 получать переполнение стека при анализе любого JSON, который содержит массив, но только когда вы также передаете функцию reviver в JSON.parse().Исходный код JSON.parse IE8 вызывает переполнение стека

Это началось как вопрос, но я ответил на свой собственный вопрос, поэтому теперь я спрошу: может ли кто-нибудь подумать об обходном пути для этой ошибки IE8, которая не включает в себя устранение всех JS-библиотек, которые изменяют Array.prototype и Function.prototype?

Оригинальный вопрос:

У меня есть около 13k данных JSON для синтаксического анализа. Структура данных - это объект с единственным значением, являющимся вложенным массивом.

{ 'value':[[ stuff ], [ more stuff], [ etc ]] } 

Я использую json2.js, который отсылает браузер на родной JSON.parse, когда он доступен. Я передаю функцию reviver в JSON.parse для правильной обработки дат. Когда IE8 находится в режиме эмуляции IE7 (что заставляет его использовать скрипт json2.js на основе скрипта), все работает нормально. Когда 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 для этого браузера из-за этой ошибки.

ОБНОВЛЕНИЕ: В других случаях, при использовании разных данных JSON, я получаю ошибку javascript «$ lineinfo undefined», когда я использую собственный синтаксический анализатор IE8 с функцией reviver, и нет ошибки, если я не использую функцию reviver. Строка «$ lineinfo» не отображается нигде в каком-либо из исходного кода.

ОБНОВЛЕНИЕ 2: На самом деле эта проблема, по-видимому, вызвана Prototype 1.6.0.3. Мне не удалось воспроизвести его на изолированной тестовой странице, пока я не добавлю в библиотеку Prototype.

UPDATE 3:

Причина prototype.js разбивает IE8 родной JSON парсер это: Добавление любого не-встроенных функций Array.prototype И Function.prototype вызовут IE8 родной JSON парсер, чтобы получить переполнение стека при анализе любого 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> 
+3

Команда JavaScript сообщает, что это известная проблема в движке JavaScript. Благодарю. – EricLaw

+0

Спасибо, что сообщили мне. –

ответ

2

Это, кажется, работает хорошо здесь:

<!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 in IE8. Этот конкретный пункт может представлять интерес:

Необязательный аргумент оживить является определенной функции пользователя используется для разбора пост изменений. Полученный объект или массив перемещается рекурсивно, функция применяется к каждому члену. Значение каждого члена заменяется значением , возвращаемым редактором . Если редактор возвращает значение null, объект удаляется. Обход и призыв к редактору выполнен в . Это верно; каждый объект is 'revived' после все его члены ' revived '.

В приведенном выше параграфе объясняется, почему функция моего возрождения выглядит так, как она есть. Моя первая попытка тестового кода был:

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

Очевидно, что если эта Восстановитель функция применяется к address узлу выше после того, как применяется ко всем своим детям, я полностью уничтожил address объект.

Конечно, если тест вашего reviver так же прост, как вы описали в своем вопросе, маловероятно, что какая-то глобальная циркулярная ссылка приведет к проблеме, которую вы видите. Я все еще думаю, что это указывает на сломанный Internet Explorer или плохие данные.

У вас есть edit your question и отправьте образец фактических данных, которые обнаруживают проблему, поэтому я могу попробовать ее здесь?

+0

Спасибо - оказывается, прототип как-то преступник. +1 за тщательный ответ! –

3

У меня был этот вопрос без каких-либо принятых ответов, довольно долгое время, поэтому, чтобы избавиться от него, я отвечу сам.

Эрик юриспруденцию в Microsoft говорит:

Команда JavaScript сообщает, что это известная проблема в движке JavaScript.

5

Решение состоит в том, чтобы удалить родной JSON.parse на IE8 и заменить его с JSON.разобрать из 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) { 
... 

После этого синтаксический разбор должен работать снова.

Одна из проблем с этим подходом заключается в том, что метод разбора json2.js медленнее, чем собственный.

+0

У меня такая же проблема. Мне нужен JSON.parser для работы с IE8. Я сделал вашу рекомендацию, это не работает для меня. Он работает с любыми другими браузерами. есть идеи? – user1471980

-2
eval(Ext.decode("{"foo":"bar"}")); 

преобразует строку в объект в IE 8.

2

Расширение этого вопроса (который по-прежнему присутствует в IE9), является родной функция JSON.stringify сбоя IE, когда есть:

  1. большой объект ссылка график
  2. объект граф JQuery ' данных ".
  3. График объекта является круглым.

Мы не уверены, какая именно причина вызывает крушение.

Наше обходное решение в этом случае состояло в том, чтобы использовать функцию replacer в функции stringify для возврата null к определенному свойству объекта и прекратить перемещение графика объекта.

Смежные вопросы