使用节点检查器调试 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的主要内容,如果未能解决你的问题,请参考以下文章

带有 mocha 的节点检查器无法使用“调试器”命令

使用 mocha 运行节点检查器

将节点检查器与 Grunt 任务一起使用

纱线未安装在 nvm 版本节点版本中

Android Studio 4.0+ 中新的 UI 层次结构调试工具

使用 Safari Web 检查器调试内存泄漏?