错误的JavaScript V8的正则expression式引擎时匹配的开始行?

我有一个非常漂亮的工具, 下划线 ,这是在打印出帮助/使用信息时得到最奇怪的行为。

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

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

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

然而,我在我的使用文本中间插入了一些bizzare空格。 喜欢这个:

 命令:
 ...
     值检索对象属性的所有值。
     扩展&ltobject>覆盖input数据中的属性。
     默认值&ltobject>填写input数据中缺less的属性。
      any&ltexp>如果input中的任何值使expression式为真,则返回“true”。 expression式参数:(值,键,列表)
          all&ltexp>如果input中的所有值都使expression式为true,则返回“true”。 expression式参数:(值,键,列表)
      isObject如果input数据是具有命名属性的对象,则返回“true”
      isArray如果input数据是数组,则返回“true”
      isString如果input数据是string,则返回“true”
 ...

99%的机会,这是V8中的一个bug。

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

是的,事实certificate这一个V8的错误,1748是确切的。 以下是我在该工具中使用的解决方法 :

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

这是V8中的错误(bug 1748):

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

这是一个错误的testing:

 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版本没有这个bug):

http://jsfiddle.net/PqDHk/

历史logging:

从V8更新日志中 ,该bug在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。 所以从理论上讲,这个bug在Node V0.6.0之前就已经修复了。 为什么它仍然在Node-0.6.5上重现? 奇。

有人可以使用最新的(Node-0.6.15)运行上面的testing代码并报告是否会产生错误? 或者我会最终解决它。

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

在此之前,解决方法是replace:

 str.replace(/^/, indent); 

附:

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

更新:只是为了咯咯,我在当前节点版本v0.8.1上检查了这个,并且确认这个bug确实已经修复了。 我并没有费心去回头确认这个bug是否在0.6.16或v0.8.X系列之间。

解决方法:捕获第一个字符,并将其replace为空格和本身

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

或者,确保该行尚未缩进

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