2012-04-14 7 views
6

Tengo una herramienta muy ingeniosa, underscore-cli, que está teniendo el comportamiento más extraño al imprimir la información de ayuda/uso.Error en el motor regex JavaScript V8 cuando se hace coincidir el comienzo de la línea?

En la función de uso(), hago esto a los bloques de sangría del texto (por ejemplo, las opciones):

str.replace(/^/, " "); 

Esta expresión regular, además de ser bastante obvio, viene directamente de TJ Hollowaychuk de commander.js código. La expresión regular es correcta.

Sin embargo, obtengo espacios bizarros insertados en el medio de mi texto de uso. como este:

 Commands: 
... 
    values    Retrieve all the values of an object's properties. 
    extend &ltobject>  Override properties in the input data. 
    defaults &ltobject> Fill in missing properties in the input data. 
    any &ltexp>   Return 'true' if any of the values in the input make the expression true. Expression args: (value, key, list) 
     all &ltexp>   Return 'true' if all values in the input make the expression true. Expression args: (value, key, list) 
    isObject   Return 'true' if the input data is an object with named properties 
    isArray    Return 'true' if the input data is an array 
    isString   Return 'true' if the input data is a string 
... 

99% de probabilidad, esto tiene que ser un error en V8.

¿Alguien sabe por qué sucede esto, o cuál sería el trabajo más fácil?

Yup, resulta esto IS un error de V8, 1748 para ser exactos. Aquí es the workaround I used in the tool:

str.replace(/(^|\n), "$1 "); 
+0

¿Solo agrega una cadena al principio? –

+1

¿ha limpiado el texto de los retornos de carro? – Trey

+0

¿Has intentado poner algo que no sean espacios? el navegador no debe mostrar más de un espacio; para colocar varios espacios, debe usar '       ' ... –

Respuesta

4

Esto es un error en V8 (error 1748):

http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/regress/regress-1748.js?spec=svn9504&r=9504

Aquí es una prueba para el error:

function assertEquals(a, b, msg) { if(a !== b) { console.log("'%s' != '%s' %s", a, b, msg); } } 

var str = Array(10000).join("X"); 
str.replace(/^|X/g, function(m, i, s) { 
    if (i > 0) assertEquals("X", m, "at position 0x" + i.toString(16)); 
}); 

En mi caja, imprime:

'X' != ''. at position 0x100 
'X' != ''. at position 0x200 
'X' != ''. at position 0x300 
'X' != ''. at position 0x400 
'X' != ''. at position 0x500 
'X' != ''. at position 0x600 
... 

En jsFiddle, imprime nada (la versión del V8 en mi navegador Chrome doesn' t tiene el gusanillo):

http://jsfiddle.net/PqDHk/


Bug Historia:

Desde el V8 changelog, el error se corrigió en V8-3.6.5 (2011-10-05).

Desde el Node.js changelog, el Nodo-0.6.5 debería estar usando V8-3.6.6.11!? !!?. Node.js actualizado de V8-3.6.4 a V8-3.7.0 (Nodo-0.5.10) y luego degradado a V8-3.6.6 para el Nodo-0.6.0. Entonces, teóricamente, este error debería haberse solucionado antes del nodo V0.6.0. ¿Por qué todavía repro en Node-0.6.5 ??? Impar.

¿Puede alguien con la última versión (Node-0.6.15) ejecutar el fragmento de prueba anterior e informar si genera errores? O lo haré eventualmente.

Gracias a ZachB por confirmar este error en el Nodo-0.6.15. Archivé un problema (issue #3168) contra un nodo y se ha aplicado una corrección (5d69bbf) que debería incluirse en el Nodo-0.6.16. :) :) :)

Hasta entonces, la solución es reemplazar:

str.replace(/^/, indent); 

Con:

str.replace(/(^|\n)/, "$1" + indent); 

ACTUALIZACIÓN: Sólo por diversión, he comprobado esto en la versión nodo actual, v0.8.1, y confirmó que el error está corregido. No me he molestado en volver y confirmar si el error se solucionó en 0.6.16 o en algún momento entre ese momento y la serie v0.8.X.

+1

v0.6.15 imprime el mismo ''X'! = ''. en la posición 0x ... 'bits para mí. – ZachB

+0

Gracias por probarlo Zach. Parece que el error todavía está allí. Archivaré un problema en Node. –

+0

https://github.com/joyent/node/issues/3168 –

1

solución alternativa: capturar el primer carácter, y reemplazarlo con los espacios, y la propia

str.replace(/^./, " $1"); 

o, para asegurarse de que la línea no está ya sangría

str.replace(/^[^\s]/, " $1"); 
+0

intenté eso (capturando el primer char). resulta que no funciona. +1 por esfuerzo sin embargo. –

+0

bien disparar. publica un violín y estaría feliz de darle otra puñalada. – Umbrella

+2

@ddopson: '$ 1' funciona con grupos de captura. 'str.replace (/^(.)/ gm, '$ 1');' http://jsfiddle.net/T2Uur/ –

Cuestiones relacionadas