2009-08-17 5 views
31

TL; DR: Agregar funciones no incorporadas a Array.prototype AND Function.prototype provocará que el analizador JSON nativo de IE8 obtenga un desbordamiento de la pila al analizar cualquier JSON que contiene una matriz, pero solo cuando también pasa una función de reactivación a JSON.parse().El error JSON.parse nativo de IE8 provoca el desbordamiento de la pila

Esto comenzó como una pregunta, pero respondí mi propia pregunta original, así que ahora voy a preguntar: ¿alguien puede pensar en una solución para este error IE8 que no implica eliminar todas las bibliotecas JS que modifican Array.prototype y Function.prototype?

pregunta original:

Tengo alrededor de 13k de datos JSON para analizar. La estructura de los datos es un objeto con un único valor que es una matriz anidada.

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

estoy usando json2.js, que se remite a la nativa del navegador JSON.parse cuando esté disponible. Paso una función reviver en JSON.parse para manejar las fechas correctamente. Cuando IE8 está en modo de emulación IE7 (lo que hace que use el analizador json2.js basado en script) todo funciona bien. Cuando IE8 está en modo IE8 (lo que hace que use el analizador JSON nativo del navegador) explota con un error de "falta de espacio en la pila". Firefox y Chrome, por supuesto, funcionan bien con sus analizadores JSON nativos del navegador.

Lo he reducido a esto: si paso incluso una función reviver do-nothing en JSON.parse, el analizador nativo IE8 obtiene el desbordamiento de la pila. Si paso sin función de reactivación, el analizador nativo IE8 funciona bien, excepto que no analiza las fechas correctamente.

// no error: 
JSON.parse(stuff); 

// "out of stack space" error: 
JSON.parse(stuff, function(key, val) { return val; }); 

Voy a jugar con mis datos JSON, para ver si menos datos o menos de anidación de los datos se puede evitar el error, pero me preguntaba si alguien había visto esto antes, o ha tenido cualquier otro sugerido problemas de trabajo. IE8 ya es lo suficientemente lento, sería una pena deshabilitar JSON nativo para ese navegador debido a este error.

ACTUALIZACIÓN: En otros casos, con diferentes datos JSON, obtengo un error de javascript "$ lineinfo no está definido" cuando uso el analizador nativo IE8 con una función reviver y no hay error si no uso la función reviver. La cadena "$ lineinfo" no aparece en ningún lugar de ninguno de mis códigos fuente.

ACTUALIZACIÓN 2: En realidad, este problema parece ser causado por el prototipo 1.6.0.3. No pude reproducirlo en una página de prueba aislada hasta que agregué en la biblioteca Prototype.

Actualización 3:

La razón prototype.js rompe el analizador JSON nativo IE8 es la siguiente: La adición de cualquiera que no sea incorporado en las funciones de Array.prototype Y Function.prototype hará que el analizador JSON nativo para obtener IE8 un desbordamiento de pila al analizar cualquier JSON que contenga una matriz, pero solo cuando también pasa una función de reactivación a JSON.parse().

La biblioteca Prototype agrega funciones tanto a Array.prototype como a Function.prototype, pero esto se aplica igualmente a cualquier otra biblioteca que haga lo mismo. Este error en el analizador de IE JSON está expuesto por Prototype y Ext, pero no jQuery. No he probado otros marcos.

Aquí hay una reproducción completamente independiente del problema. Si elimina la línea Function.prototype, o la línea Array.prototype, o quita la matriz de la cadena JSON, no obtendrá el error "out of stack space".

<!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

El equipo de JavaScript informa que este es un problema conocido en el motor de JavaScript. Gracias. – EricLaw

+0

Gracias por avisarme. –

Respuesta

2

Parece que funciona bien aquí:

<!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> 

El problema es o bien un corrupto Internet Explorer 8 instalar (estás tratando de ejecutar varias copias de Internet Explorer en la misma instalación de Windows?) O tu entrada es mala

Le recomendamos que lea Native JSON in IE8. Este párrafo en particular puede ser de interés:

El opcional revivir argumento es una función definida por el usuario utilizado para post analizar cambios. El objeto o matriz resultante se recorre recursivamente, la función reviver se aplica a cada miembro. Cada valor de miembro se reemplaza con el valor devuelto por reviver. Si el restablecedor devuelve nulo, se elimina el miembro del objeto. El recorrido y la llamada al reanimador se realizan en el postorder . Está bien; cada objeto es 'revivido' después de todos sus miembros son 'revivió'.

El párrafo anterior explica por qué mi función reviver se ve como lo hace. Mi primer intento de código de prueba fue:

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

Obviamente, si esta función resucitador se aplica al nodo address anterior después de aplicarse a todos sus hijos, he destruido por completo el objeto address.

Por supuesto, si la prueba de su reviver es tan simple como usted describe en su pregunta, es poco probable que alguna referencia circular global esté dando lugar al problema que está viendo. Todavía creo que apunta a un Internet Explorer roto o datos incorrectos.

¿Puedes edit your question y publicar una muestra de los datos reales que presentan el problema para que pueda probarlo aquí?

+0

Gracias - resulta que Prototype es de alguna manera el culpable. +1 para la respuesta completa! –

3

He tenido esta pregunta sin respuestas aceptadas por mucho tiempo, así que solo para deshacerme de ella, la responderé yo mismo.

Eric Derecho de Microsoft dice:

El equipo de JavaScript informa que este es un problema conocido en el motor de JavaScript.

5

Una solución es eliminar el JSON.parse nativo en IE8 y sustituirlo por el JSON.análisis sintáctico de la json2.js lib:

Añadir:

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

... y luego se incluyen:

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

Esto desencadenará json2 para reemplazar el JSON.parse con su propia versión

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

Después de eso, el análisis debería funcionar de nuevo.

Un problema con este enfoque es que el método de análisis json2.js es más lento que el nativo.

+0

Tengo el mismo problema. Necesito JSON.parser para trabajar en IE8. Hice tu recomendación, no funciona para mí. Funciona en cualquier otro navegador diferente. ¿algunas ideas? – user1471980

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

está transformando una cadena en un objeto en IE 8.

2

Una extensión de este problema (que todavía está presente en IE9), es la función JSON.stringify nativo se bloquea IE cuando hay:

  1. un objeto grande referencias gráfico gráfico
  2. el objeto jQuery ' objetos de datos.
  3. el gráfico del objeto es circular.

No estamos seguros de qué punto específico causa el colapso.

Nuestra solución temporal en esta instancia era utilizar una función de sustitución en la función de stringify para devolver nulo en una propiedad de objeto particular y evitar que se atraviese el gráfico de objetos.

Cuestiones relacionadas