Albert
Albert

Reputation: 68360

debug V8 with node-inspector

I'm trying to debug my JavaScript scripts, which are running in V8, with node-inspector. On the app side, I just did

v8::Debug::EnableAgent("MyApp", 5858);

Node-inspector connects fine and even is able to pause/unpause and to show the code. However, step-wise execution does not work, neither breakpoints and probably a lot of other things. When I try to do such things, I get these errors from 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

So I guess I'm missing something.

I'm not sure if what I'm trying to do is even supported - because I guess, node-inspector is meant for Node.js and not for arbitrary V8, right? If so, what would be needed to make it work?


Thanks for the help by Miroslav, esp. to run DEBUG=node-inspector:protocol:* node-inspector, I got a bit further. Step-wise execution works now, and breakpoints do to in most cases (except when you select the wrong Source file - see below).

I provided a global process object like this:

// 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; }

Now I get the error Internal error: TypeError: Cannot read property 'line' of null in the console. In node-inspector, I get this:

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"}

Another thing is that the script files are not always correct. On the C++ side, I'm loading them now like this:

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;
}

That puts all files under the file:// domain in the Sources list. However, main.js gets an extra entry under (no domain). When I make the change

process.mainModule = {filename: "file:///" + process._baseDir + "/main.js"}

it goes away, however, that is not how I would have expected ìt to be according to the doc.

When I pause/break the execution in main.js, it shows up in yet another Source [VM] main.js and gets a yellow-ish background.

Also, all files in Sources under file:// get the (function (exports, require, module, __filename, __dirname) { prefix added in the first line of the source. That line does not come from my code but from node-inspector. Why does it add that here? It is esp. strange because my code adds a slightly different prefix ( function(module, exports) {.

Upvotes: 2

Views: 3640

Answers (2)

Ahmet Uzun
Ahmet Uzun

Reputation: 81

Here is a solution for debugging V8 with node-inspector:

First of all, the latest version (0.12.3) has many extensions for debugging node.js scripts so I used an older version (0.5.0) which has less liability to node.js.

I used the following command to install v0.5.0 in Node.js command prompt:

npm install node-inspector@0.5.0

It is installed in folder "%USERPROFILE%\node_modules" by default.

I added one line of code to %USERPROFILE%\node_modules\node-inspector\lib\PageAgent.js:

getResourceTree: function(params, done) {
    return; //return empty tree
...

This completes the installation.

Here is the guide to debug a javascript file executed by using the ClearScript .NET library:

Open a command prompt and execute the following command:

%USERPROFILE%\node_modules\.bin\node-inspector.cmd

You should see the following lines if node-inspector is running successfully.

Node Inspector v0.5.0
info - socket.io started 
Visit http://127.0.0.1:8080/debug?port=5858 to start debugging.

Initialize your V8 engine as in the following code line (VB.NET code):

Dim engine As New V8ScriptEngine("global", V8ScriptEngineFlags.EnableDebugging, 9222)

Put a breakpoint right after this line in your code and run your application to reach this breakpoint.

Make sure you have "debugger;" statement in the first line of your JavaScript code.

Open a Chrome browser and navigate to the following address:

http://127.0.0.1:8080/debug?port=9222

Press "Continue Debugging" button in Vİsual Studio toolbar.

Now you should see your script code stopped at the first "debugger;" line in Chrome browser.

You can continue debugging from here.

Upvotes: 0

Miroslav Bajtoš
Miroslav Bajtoš

Reputation: 10795

Run DEBUG=node-inspector:protocol:* node-inspector and inspect the messages, you might be able to find more information there. You can also try to use an older version, e.g. 0.1.9, it may have less dependencies on Node-specific stuff.

I'd say 95% of Node Inspector code uses V8 protocol only. Look for usages of DebuggerClient.prototype.evaluateGlobal to find where Node-specific functionality is used.

The first thing to change is getResourceTree in lib/PageAgent.js. Either implement your own way of listing all source files (including those not loaded yet), or return an empty tree.

UPDATE

Try Node's CLI debugger first:

$ node debug localhost:5858

To my best knowledge, the CLI debugger uses only the V8 debugger protocol features, nothing Node specific. When you are able to debug your V8 app using the CLI, you will know that any other problems are in Node Inspector and not in your V8 app.

Upvotes: 1

Related Questions