- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我花了一些时间在 NodeJS 测试套件中调试一个奇怪的无限循环问题。它只在极少数情况下发生,但我可以在附加到 chrome 调试器时重现它。
我认为这与 V8 对 stack traces in exceptions 的处理有关。以及 vows library 的扩展名对 AssertionError
对象做了(誓言添加了一个 toString
方法)。也有可能是我弄错了,所以想问问我对V8实现的理解是否正确。
这是重现错误的最小示例:
$ git clone https://github.com/flatiron/vows.git
$ cd vows && npm install && npm install should
$ cat > example.js
var should = require('should');
var error = require('./lib/assert/error.js');
try {
'x'.should.be.json;
} catch (e) {
console.log(e.toString());
}
// without debug, it should fail as expected
$ node example.js
expected 'x' to have property 'headers' // should.js:61
// now with debug
$ node-inspector &
$ node --debug-brk example.js
// 1) open http://127.0.0.1:8080/debug?port=5858 in Chrome
// 2) set breakpoint at lib/assert/error.js#79 (the toString method)
// 3) Resume script execution (F8)
现在程序进入了一个无限循环:toString
方法(由 vows 库添加)在 this.stack
在第 83 行的正则表达式。
require('assert').AssertionError.prototype.toString = function () {
var that = this, // line 79: breakpoint
source;
if (this.stack) {
source = this.stack.match(/([a-zA-Z0-9._-]+\.(?:js|coffee))(:\d+):\d+/); // line 83: infinite loop takes place here (however, this.stack is undefined)
}
当我在调试器中检查 this
时,它显示它是一个 AssertionError
但它的 stack
属性是 undefined
。但是,当我将鼠标悬停在它上面时,它会显示实际的堆栈跟踪。
我认为这种现象是由 V8 的惰性优化引起的。它仅按需计算堆栈跟踪。这样做会干扰 vows 添加的 toString
方法。 toString
方法再次访问堆栈跟踪 (this.stack
),因此循环继续。
这个结论正确吗?如果是这样,有没有办法修补 vows 代码,使其适用于 V8(或者我至少可以将其报告为 vows 项目中的错误)?
我在 Ubuntu 下使用 node v0.10.28。
更新:没有誓言的简化示例
这是一个简化版本。它不再依赖于誓言,而是我只复制了它的 toString
扩展的相关部分:
var should = require('should');
require('assert').AssertionError.prototype.toString = function () {
var that = this,
source;
if (this.stack) {
source = this.stack.match(/([a-zA-Z0-9._-]+\.(?:js|coffee))(:\d+):\d+/);
}
return '<dummy-result>';
};
try {
'x'.should.be.json;
} catch (e) {
console.log(e.toString());
}
// expected result (without debug mode)
$ node example.js
<dummy-result>
在 Debug模式下,递归发生在 if
语句中。
更新:带有 ReferenceError 的更简单版本
ReferenceError.prototype.toString = function () {
var that = this,
source;
if (this.stack) {
source = this.stack.match(/([a-zA-Z0-9._-]+\.(?:js|coffee))(:\d+):\d+/);
}
return '<dummy-result>';
};
try {
throw new ReferenceError('ABC');
} catch (e) {
console.log(e.toString());
}
(我还创建了一个 jsfiddle 示例,但我无法在那里重现无限循环,只能使用 Node 。)
最佳答案
是的,这绝对是该版本 Node 中 V8 版本中的一个错误。
V8 版本中的代码您的 Node 版本使用的代码类似于:
function FormatStackTrace(error, frames) {
var lines = [];
try {
lines.push(error.toString());
} catch (e) {
try {
lines.push("<error: " + e + ">");
} catch (ee) {
lines.push("<error>");
}
}
这是 NodeJS uses 版本的实际代码.
它正在做 error.toString()
的事实本身导致了循环,this.stack
访问 FormatStackTrace
反过来又在做 .toString()
。你的观察是正确的。
如果这有什么好处的话,那段代码在新版本的 V8 中看起来很不一样。在 Node 0.11 中,this bug is already fixed .
这里是 commit that fixed it一年半前由 Vyacheslav Egorov 提交.
好吧,你的选择是有限的,但既然这是为了调试,总能阻止第二次迭代并停止循环:
ReferenceError.prototype.toString = function () {
var source;
if(this.alreadyCalled) return "ReferenceError";
this.alreadyCalled = true;
if (this.stack) {
source = this.stack.match(/([a-zA-Z0-9._-]+\.(?:js|coffee))(:\d+):\d+/);
}
return '<dummy-result>';
};
没有表现出同样的问题。如果不访问核心代码,您将无能为力。
关于javascript - V8 延迟生成堆栈跟踪似乎导致 vows 库中的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23877022/
谁能帮我解决这个问题?我有一个 Tomcat 和简单的 JSF 应用程序:https://github.com/gooamoko/jsfbilling/ .当我在 Tomcat 上运行应用程序时,它运
我有两个这样的域类,第一个是 Manager : package com.mnm class Manager { String name; static hasMany = [ pro
当我运行以下代码时,打印输出似乎不正确。 void thread_Calc(int *pos) { printf("recieved %d\n", *pos); sig = -1; man
这个问题在这里已经有了答案: How to access a local variable from a different function using pointers? (10 个答案) 关闭
我编写了一个程序,其中列表构建器方法返回 IEnumerable of string,其中包括大量字符串(100 万个项目),我将其存储在 List of string 中,然后它将所有项目附加到 中
我正在尝试编写一个 IRC 类型的聊天客户端,它具有可以连接到服务器的客户端。我试图让它在本地 atm 上工作(使用 FIFOS 而不是套接字)。 我遇到了以下我似乎无法解决的问题: 接受新的客户端连
我的一个 cronjobs 每天发送一封电子邮件 35 6 * * * cd $EZPUBLISHROOT && $PHP runcronjobs.php -q 2>&1 我停止使用 cron sud
我使用 WPF 打印路径来处理在我们的应用程序中创建的大型图表。整个图表由视觉效果组成。 所谓的“DesignerPaginator”对图表进行分页(非常简单)。 从这一点来说,我做了以下三件事: -
我尝试在更新之前跟踪系统应用程序并使用: public static boolean isSystemApplication(Context ctx, IContent content) {
我在这里附上了一个查询分析结果,https://explain.depesz.com/s/x9BN 这是查询 EXPLAIN ANALYZE SELECT branche
我正在做一个 CXF(spring) 项目 (HUB)。部署后,我可以看到肥皂和休息服务列表,我通过两个地址打开它。一种是使用本地主机,第二种是使用我电脑的 ip。所以我得到了这些输出。 使用本地主机
这是一个 AnyHashable 不支持枚举转换的简单案例。 enum testEnum: String { case Test } let myObject: AnyHashable = t
我的主要目标是比较存储在数据库和 XLSX 文件中的数据。 为此,我按以下方式创建了两个列表: private class ProductList { public string produc
我从 CMake 3.6 更新到任何最新版本 (3.12.0-rc2),现在我的一个程序无法编译。 奇怪的是,错误消息显示了标准库本身中的 undefined symbol 。这是错误消息: Unde
我希望将我的自定义对话框动画化为从特定点出现,但我无法为对话框设置动画。 该对话框是一个基本的 RelativeLayout,设置为 extends Dialog 类中的布局。 正如这里的一些答案所建
我已经在这个论坛上调查过很多类似的问题,但似乎没有一个能解决我的问题。 我会在底部列出我在这个论坛上看到的一些问题页面,但让我先谈谈我对这个问题的看法。 我正在使用 codeigniter v 2.x
我正在尝试在 RHEL 7 上启动一个 docker-compose 项目作为 systemd 服务。这是我的 systemd 脚本 (/etc/systemd/system/wp.service):
这个问题已经有答案了: "Notice: Undefined variable", "Notice: Undefined index", "Warning: Undefined array key",
我正在尝试在 RHEL 7 上启动一个 docker-compose 项目作为 systemd 服务。这是我的 systemd 脚本 (/etc/systemd/system/wp.service):
此问题出现在my last question here之后。我想将每个按钮聚焦和失去焦点背景设置为主菜单(ContentPane 即 JPanel)下方的背景颜色,因此按钮看起来像选项卡。它在不同的环
我是一名优秀的程序员,十分优秀!