匹配行首时JavaScript V8正则表达式引擎中的错误?

时间:2012-04-14 01:03:24

标签: javascript regex node.js newline v8

我有一个非常漂亮的工具,underscore-cli,在打印出帮助/使用信息时会遇到最奇怪的行为。

在usage()函数中,我这样做是为了缩进文本块(例如,选项):

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

除了非常明显之外,这个正则表达式直接来自TJ Hollowaychuk的commander.js代码。正则表达式是正确的。

然而,我在使用文本的中间插入了bizzare空格。像这样:

  Commands:
...
     values              Retrieve all the values of an object's properties.
     extend <object>     Override properties in the input data.
     defaults <object>   Fill in missing properties in the input data.
     any <exp>           Return 'true' if any of the values in the input make the expression true.  Expression args: (value, key, list)
         all <exp>           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%的几率,这是V8中的一个错误。

任何人都知道为什么会发生这种情况,或者最简单的解决办法是什么?

是的,原来这个 IS 是一个V8错误,确切地说是1748。这是the workaround I used in the tool

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

2 个答案:

答案 0 :(得分: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' != ''.  at position 0x100
'X' != ''.  at position 0x200
'X' != ''.  at position 0x300
'X' != ''.  at position 0x400
'X' != ''.  at position 0x500
'X' != ''.  at position 0x600
...

在jsfiddle上,它什么都没打印(我的Chrome浏览器中的V8版本没有错误):

http://jsfiddle.net/PqDHk/


错误历史记录:

V8 changelog开始,该错误已在V8-3.6.5(2011-10-05)中修复。

Node.js changelog开始,Node-0.6.5应该使用V8-3.6.6.11!?!!?。 Node.js从V8-3.6.4更新到V8-3.7.0(Node-0.5.10),然后降级到V-3-8.6,用于Node-0.6.0。所以从理论上讲,这个bug应该在Node V0.6.0之前修复。为什么它仍然在Node-0.6.5上重现?奇

最新的人(Node-0.6.15)可以运行上面的测试片段并报告它是否会产生错误吗?或者我最终会解决它。

感谢ZachB在Node-0.6.15上确认此错误。我针对节点提交了一个问题(issue #3168),并且已经应用​​了修复程序(5d69bbf),并且应该包含在Node-0.6.16中。 :) :) :))

在此之前,解决方法是替换:

str.replace(/^/, indent);

使用:

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

更新:只是为了咯咯笑,我在当前节点版本v0.8.1上检查了这一点,并确认错误确实已修复。我没有打算回过头来确认这个bug是在0.6.16还是在某个时间和v0.8.X系列之间确定的。

答案 1 :(得分:1)

解决方法:捕获第一个字符,并用空格替换它本身

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

或,以确保该行尚未缩进

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