2012-04-14 7 views
6

Ho uno strumento piuttosto elegante, underscore-cli, che sta ottenendo il comportamento più strano quando si stampano le informazioni di aiuto/utilizzo.Errore nel motore regex di JavaScript V8 quando si combina l'inizio della linea?

Nella funzione d'uso(), faccio questo a blocchi del rientro del testo (ad esempio, le opzioni):

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

Questa espressione regolare, oltre ad essere piuttosto ovvio, arriva direttamente dal TJ Hollowaychuk di commander.js codice. L'espressione regolare è corretta.

Tuttavia, ottengo spazi bizzarri inseriti nel mezzo del mio testo di utilizzo. in questo modo:

 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% di possibilità, questo deve essere un bug nel V8.

Qualcuno sa perché questo accade, o quale sarebbe la soluzione più semplice?

Sì, risulta questo IS un errore V8, 1748 per l'esattezza. Ecco the workaround I used in the tool:

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

Basta aggiungere una stringa all'inizio? –

+1

hai pulito il testo dei ritorni a capo? – Trey

+0

hai provato a mettere qualcosa di diverso dagli spazi? il browser non suppone di mostrare più di uno spazio - per inserire più spazi è necessario utilizzare '       ' ... –

risposta

4

Questo è un bug nel V8 (bug 1748):

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

Ecco un test per il bug:

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)); 
}); 

Sulla mia macchina, esso stampa:

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

Su jsfiddle, viene stampato nulla (la versione di V8 nel mio browser Chrome doesn' t hanno il bug):

http://jsfiddle.net/PqDHk/


Bug Storia:

Dal V8 changelog, il bug è stato risolto in V8-3.6.5 (2011-10-05).

Da Node.js changelog, Node-0.6.5 deve utilizzare V8-3.6.6.11!? !!?. Node.js aggiornato da V8-3.6.4 a V8-3.7.0 (Nodo-0.5.10) e quindi declassato a V8-3.6.6 per Node-0.6.0. Quindi, teoricamente, questo bug avrebbe dovuto essere risolto prima del Nodo V0.6.0. Perché continua a riprodurre su Node-0.6.5 ??? Dispari.

È possibile qualcuno con l'ultimo (Nodo-0.6.15) eseguire lo snippet di test sopra e segnalare se genera errori? O me ne andrò alla fine.

Grazie a ZachB per la conferma di questo errore su Node-0.6.15. Ho archiviato un problema (issue #3168) contro il nodo e una correzione (5d69bbf) è stata applicata e dovrebbe essere inclusa nel nodo 0.6.16. :) :) :)

Fino ad allora, la soluzione è di sostituire:

str.replace(/^/, indent); 

Con:

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

UPDATE: Solo per risatine, ho controllato questo sulla versione nodo corrente, v0.8.1, e ha confermato che il bug è effettivamente risolto. Non mi sono preso la briga di tornare indietro e confermare se il bug è stato risolto in 0.6.16 o qualche volta tra lì e la serie v0.8.X.

+1

v0.6.15 stampa lo stesso ''X'! = ''. alla posizione 0x ... 'bit per me. – ZachB

+0

Grazie per averlo testato Zach. Sembra che l'errore sia ancora lì. Presenterò un problema su Node. –

+0

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

1

work-around: catturare il primo carattere, e sostituirlo con gli spazi, e si

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

o, per assicurarsi che la linea non è già rientrato

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

provato (catturando il primo carattere). risulta che non funziona. +1 per lo sforzo però. –

+0

sparare bene. pubblicare un violino e sarei felice di prenderne un'altra pugnalata. – Umbrella

+2

@ddopson: '$ 1' funziona con i gruppi di cattura. 'str.replace (/ ^(.)/ gm, '$ 1');' http://jsfiddle.net/T2Uur/ –

Problemi correlati