6

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

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

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

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

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

  命令:
...
     values 检索对象属性的所有值。
     扩展 <object> 覆盖输入数据中的属性。
     defaults <object> 填写输入数据中缺失的属性。
     any <exp> 如果输入中的任何值使表达式为真,则返回“真”。表达式参数:(值、键、列表)
         all <exp> 如果输入中的所有值都使表达式为真,则返回“真”。表达式参数:(值、键、列表)
     isObject 如果输入数据是具有命名属性的对象,则返回“真”
     isArray 如果输入数据是数组,则返回 'true'
     isString 如果输入数据是字符串,则返回 'true'
...

99% 的可能性,这必须是 V8 中的错误。

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

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

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。所以理论上,这个bug应该在Node V0.6.0之前就已经修复了。为什么它仍然在 Node-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 系列之间得到修复。

于 2012-04-14T01:26:26.860 回答
1

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

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

或者,确保该行尚未缩进

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