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

Bug in JavaScript V8 regex engine when matching beginning-of-line?

本文关键字:行首 错误 V8 正则表达式 引擎 JavaScript      更新时间:2023-09-26

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

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

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

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

然而,我在用法文本的中间插入了奇怪的空格。 喜欢这个:

 命令:...     值 检索对象属性的所有值。     extend &ltobject> 覆盖输入数据中的属性。     默认值 &ltobject> 填写输入数据中缺少的属性。     any &ltexp> 如果输入中的任何值使表达式为真,则返回"true"。 表达式参数:(值、键、列表)         all &ltexp> 如果输入中的所有值都使表达式为 true,则返回 'true'。 表达式参数:(值、键、列表)     isObject 如果输入数据是具有命名属性的对象,则返回"true"     isArray 如果输入数据是数组,则返回 'true'     isString 如果输入数据是字符串,则返回 'true'...

99%的机会,这一定是V8中的一个错误。

有谁知道为什么会发生这种情况,或者最简单的解决方法是什么?

的,事实证明这是一个 V8 错误,确切地说是 1748 年。 这是我在工具中使用的解决方法:

str.replace(/(^|'n), "$1    ");
这是

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 ?!!?. 节点.js从 V8-3.6.4 更新到 V8-3.7.0 (节点-0.5.10),然后降级到 V8-3.6.6 的节点 0.6.0。 所以从理论上讲,这个错误应该在 Node V0.6.0 之前修复。 为什么它仍然在节点 0.6.5 上重现??? 奇怪。

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

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

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

str.replace(/^/, indent);

跟:

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

更新:只是为了傻笑,我在当前节点版本 v0.8.1 上检查了这个,并确认该错误确实已修复。 我没有费心回去确认该错误是否在 0.6.16 中或与 v0.8.X 系列之间的某个时间修复。

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

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

或者,确保该行尚未缩进

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