6

私はかなり気の利いたツール、underscore-cliを持っています。これは、ヘルプ/使用法情報を出力するときに最も奇妙な動作をします。

Usage()関数では、テキストのブロック(オプションなど)をインデントするためにこれを行います。

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

この正規表現は、非常に明白であることに加えて、TJHollowaychukのcommander.jsコードから直接得られます。正規表現は正しいです。

それでも、使用法のテキストの途中に奇妙なスペースが挿入されています。このような:

  コマンド:
..。
     valuesオブジェクトのプロパティのすべての値を取得します。
     <object>を拡張します。入力データのプロパティを上書きします。
     デフォルト<object>入力データに不足しているプロパティを入力します。
     any <exp>入力のいずれかの値が式をtrueにした場合、「true」を返します。式の引数:(値、キー、リスト)
         all <exp>入力のすべての値が式をtrueにすると、「true」を返します。式の引数:(値、キー、リスト)
     isObjectは、入力データが名前付きプロパティを持つオブジェクトである場合に「true」を返します
     isArray入力データが配列の場合は「true」を返します
     isString入力データが文字列の場合は「true」を返します
..。

99%の確率で、これはV8のバグである必要があります。

なぜこれが起こるのか、または最も簡単な回避策は何でしょうか?

うん、これは正確には1748年のV8バグであることがわかった。ツールで使用した回避策は次のとおりです。

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

2 に答える 2

4

これはV8のバグ(バグ1748)です。

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

バグのテストは次のとおりです。

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

私の箱には、次のように印刷されています。

'X'!=''。位置0x100
'X'!=''。位置0x200
'X'!=''。位置0x300
'X'!=''。位置0x400
'X'!=''。位置0x500
'X'!=''。位置0x600
..。

jsfiddleでは何も出力されません(私のChromeブラウザのV8のバージョンにはバグがありません):

http://jsfiddle.net/PqDHk/


バグ履歴:

V8の変更ログから、バグはV8-3.6.5(2011-10-05)で修正されました。

Node.jsの変更ログから、Node-0.6.5はV8-3.6.6.11!?!!?を使用しているはずです。Node.jsはV8-3.6.4からV8-3.7.0(Node-0.5.10)に更新され、Node-0.6.0ではV8-3.6.6にダウングレードされました。したがって、理論的には、このバグはノードV0.6.0より前に修正されているはずです。Node-0.6.5でまだ再現されるのはなぜですか?奇数。

最新(Node-0.6.15)の誰かが上記のテストスニペットを実行して、エラーが発生したかどうかを報告できますか?または、私は最終的にそれを回避します。

Node-0.6.15でこのバグを確認してくれたZachBに感謝します。ノードに対して問題(問題#3168)を提出しましたが、修正(5d69bbf)が適用されており、Node-0.6.16に含める必要があります。:) :) :)

それまでは、回避策は次のものを置き換えることです。

str.replace(/^/, indent);

と:

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

更新:ちょっとした笑いのために、現在のノードバージョンv0.8.1でこれをチェックし、バグが実際に修正されていることを確認しました。わざわざ戻って、バグが0.6.16で修正されたかどうか、またはそのバグがv0.8.Xシリーズとの間で修正されたかどうかを確認していません。

于 2012-04-14T01:26:26.860 に答える
1

回避策:最初の文字をキャプチャし、それをスペースとそれ自体に置き換えます

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

または、行がまだインデントされていないことを確認します

str.replace(/^[^\s]/, "    $1");
于 2012-04-14T01:14:46.197 に答える