使用节点检查器调试 V8
Posted
技术标签:
【中文标题】使用节点检查器调试 V8【英文标题】:debug V8 with node-inspector 【发布时间】:2014-04-04 21:02:56 【问题描述】:我正在尝试使用node-inspector 调试在 V8 中运行的 javascript 脚本。在应用程序方面,我只是这样做了
v8::Debug::EnableAgent("MyApp", 5858);
节点检查器连接良好,甚至能够暂停/取消暂停并显示代码。但是,逐步执行不起作用,断点也不起作用,可能还有很多其他事情。当我尝试做这些事情时,我从 Node-inspector 收到这些错误:
Node Inspector v0.7.0
Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setSkipAllPauses
Received request for a method not implemented: Debugger.setBreakpoint
Received request for a method not implemented: Debugger.setBreakpoint
Received request for a method not implemented: Debugger.setBreakpoint
所以我想我错过了什么。
我不确定我正在尝试做的事情是否得到支持——因为我猜,node-inspector 是为 Node.js 而不是为任意 V8 设计的,对吧?如果是这样,需要什么才能使其发挥作用?
感谢 Miroslav 的帮助,尤其是。运行DEBUG=node-inspector:protocol:* node-inspector
,我走得更远了。逐步执行现在可以工作,并且在大多数情况下断点也可以(除非您选择了错误的源文件 - 见下文)。
我提供了一个像这样的全局process
对象:
// process object: http://nodejs.org/api/process.html#process_process
process.stdout = ...
process.stderr = ...
process._baseDir = ...
process.mainModule = filename: process._baseDir + "/main.js"
process.argv = ["myapp.exe", process.mainModule.filename]
process.cwd = function() return process._baseDir;
现在我在控制台中收到错误 Internal error: TypeError: Cannot read property 'line' of null
。在节点检查器中,我得到了这个:
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:v8-debug request: "seq":170,"type":"request","command":"backtrace","arguments":"inlineRefs":true,"fromFrame":0,"toFrame":50,"maxStringLength":10000
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:devtools frontend: "method":"Debugger.setOverlayMessage","id":48
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:devtools backend: "id":48
Wed, 19 Mar 2014 11:58:43 GMT node-inspector:protocol:v8-debug response: "seq":41,"request_seq":170,"type":"response","success":false,"message":"Internal error: TypeError: Cannot read property 'line' of null"
另一件事是脚本文件并不总是正确的。在 C++ 方面,我现在像这样加载它们:
ReturnType execJsFile(const std::string& jsSourceDir, const std::string& extfilename)
v8::TryCatch try_catch;
std::string fullfilename = jsSourceDir + "/" + extfilename;
std::string sourceStr;
CHECK_RETURN(readFile(fullfilename, sourceStr));
// The origin is for the debugger, e.g. node-inspector. It expects an URL.
Local<String> origin = jsStr("file:///" + fullfilename);
Local<String> source = jsStr(sourceStr);
Local<v8::Script> script = Script::Compile(source, origin);
if(script.IsEmpty())
assert(try_catch.HasCaught());
return "JS compile failed: " + jsReportExceptionToString(Isolate::GetCurrent(), &try_catch);;
Local<Value> result = script->Run();
if(result.IsEmpty())
assert(try_catch.HasCaught());
return "JS script execution failed: " + jsReportExceptionToString(Isolate::GetCurrent(), &try_catch);
return true;
这会将file://
域下的所有文件放在源列表中。但是,main.js
在(no domain)
下获得了一个额外的条目。当我做出改变时
process.mainModule = filename: "file:///" + process._baseDir + "/main.js"
它消失了,然而,根据doc,这不是我所期望的那样。
当我在 main.js 中暂停/中断执行时,它会出现在另一个 Source [VM] main.js
中,并获得黄色背景。
此外,file://
下 Sources 中的所有文件都会在源代码的第一行添加 (function (exports, require, module, __filename, __dirname)
前缀。该行不是来自我的代码,而是来自节点检查器。为什么要在这里添加?尤其是。很奇怪,因为我的代码添加了一个稍微不同的前缀 ( function(module, exports)
。
【问题讨论】:
【参考方案1】:这里有一个使用 node-inspector 调试 V8 的解决方案:
首先,最新版本 (0.12.3) 有许多用于调试 node.js 脚本的扩展,所以我使用了旧版本 (0.5.0),它对 node.js 的责任较小。
我使用以下命令在 Node.js 命令提示符下安装 v0.5.0:
npm install node-inspector@0.5.0
默认安装在文件夹“%USERPROFILE%\node_modules”中。
我在 %USERPROFILE%\node_modules\node-inspector\lib\PageAgent.js 中添加了一行代码:
getResourceTree: function(params, done)
return; //return empty tree
...
这样就完成了安装。
这里是调试使用 ClearScript .NET 库执行的 javascript 文件的指南:
打开命令提示符并执行以下命令:
%USERPROFILE%\node_modules\.bin\node-inspector.cmd
如果 node-inspector 运行成功,您应该会看到以下几行。
Node Inspector v0.5.0
info - socket.io started
Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.
按照以下代码行(VB.NET 代码)初始化您的 V8 引擎:
Dim engine As New V8ScriptEngine("global", V8ScriptEngineFlags.EnableDebugging, 9222)
在代码中的这一行之后放置一个断点并运行应用程序以到达该断点。
确保您有“调试器;” JavaScript 代码的第一行中的语句。
打开 Chrome 浏览器并导航到以下地址:
http://127.0.0.1:8080/debug?port=9222
在 Vİsual Studio 工具栏中按“继续调试”按钮。
现在您应该看到您的脚本代码在第一个“调试器”处停止;在 Chrome 浏览器中行。
您可以从这里继续调试。
【讨论】:
【参考方案2】:运行DEBUG=node-inspector:protocol:* node-inspector
并检查消息,您也许可以在那里找到更多信息。您也可以尝试使用旧版本,例如0.1.9,它可能对特定于节点的东西的依赖较少。
我会说 95% 的 Node Inspector 代码仅使用 V8 协议。查找 DebuggerClient.prototype.evaluateGlobal
的用法以查找使用节点特定功能的位置。
首先要更改的是getResourceTree
中的lib/PageAgent.js
。要么实现你自己的方式来列出所有源文件(包括那些尚未加载的),要么返回一个空树。
更新
首先尝试 Node 的 CLI 调试器:
$ node debug localhost:5858
据我所知,CLI 调试器仅使用 V8 调试器协议功能,没有特定于节点。当您能够使用 CLI 调试您的 V8 应用程序时,您将知道任何其他问题都在 Node Inspector 中,而不是在您的 V8 应用程序中。
【讨论】:
我刚刚意识到你是 node-inspector 的维护者。 :) 感谢您的回答,我会尽快尝试。你认为这对于节点检查器来说可能是一个很好的特性,能够调试通用 V8 吗?或者可能提供一个额外的包以包含在 V8 应用程序中,以便使用节点检查器进行调试。 @Albert Node Inspector 需要知道应用程序在哪里运行才能找到所有项目文件。另外,我们正在检测 Node 版本(V8 版本)以检测某些调试器功能的存在,例如“setVariableValue”。鉴于我必须在 Node Inspector 上工作的时间有限,如果您更改您的 V8 应用程序以支持这几个 Node API 会更好。 感谢您的帮助。我更进一步并扩展了我的问题。现在,我正在尝试不修改节点检查器并通过类似 Nodejs 的全局对象扩展我的 V8(例如,我添加了process
)。以上是关于使用节点检查器调试 V8的主要内容,如果未能解决你的问题,请参考以下文章