-
Notifications
You must be signed in to change notification settings - Fork 1
Overview
Stability: 3 - Beta
V8 comes with an extensive debugger which is accessible out-of-process via a simple TCP protocol. I have forked the built-in debugger client in nodejs to adapt it to be more featureful and follow the gdb and trepan command set better.
## ExampleTo use this debugger, run the trepanjs
script. For example:
% trepanjs example/myscript.js
debugger listening on port 5858
connecting to port 5858... ok
break in example/myscript.js at line 2
1 // myscript.js
-> 2 x = 5;
3 setTimeout(function () {
What's going on above is that a child process of the debugger is spawned and that then stops and listens on port 5858 for debugger commands.
trepanjs's debugger client doesn't support the full range of commands,
but simple step and inspection is possible. By putting the statement
debugger;
into the source code of your script, you will enable a
breakpoint.
For example, suppose myscript.js
looked like this:
// myscript.js
x = 5;
setTimeout(function () {
debugger;
console.log("world");
}, 1000);
console.log("hello");
Then once the debugger is run, it will break on line 4.
% trepanjs example/myscript.js
node ./bin/trepanjs --no-highlight example/myscript.js 3 5
debugger listening on port 5858
connecting to port 5858... ok
break in example/myscript.js at line 2
1 // myscript.js
-> 2 x = 5;
3 setTimeout(function () {
(trepanjs) continue
hello
break in example/myscript.js at line 4
3 setTimeout(function () {
-> 4 debugger;
5 console.log("world");
(trepanjs) next
break in example/myscript.js at line 5
4 debugger;
-> 5 console.log("world");
6 }, 1000);
(trepanjs) shell
Type .quit or press Ctrl + C (SIGINT) to leave shell.
Ctrl + D (EOF) leaves everything!
.help gives REPL help
> x
5
> 2+2
4
> .quit
(trepanjs)
If the first token of input is not a debugger command, the line is evaluated in the context of the debugged program. Of course there may be expressions that conflict with debugger commands. For example, you may have a variable called s and that will interfere with the debugger alias for step.
The shell
command allows you to evaluate code remotely. Without
going into a full REPL as the shell command , you can force
evaluation using the debugger's eval() command, e.g. eval('s')
.
The next
command steps over to the next line. There are a few other
commands available and more to come. Type help
to see others.
As we saw above, the V8 debugger can be enabled and accessed either by starting via trepanjs, but there are other ways go get into the debugger
Using either the --debug
, or --debug-brk
command-line flags or by
signaling an existing with SIGUSR1
, the debugger will go into
debug mode. Once a process is in debug mode with this it can be
connected to with trepanjs using the --attach
flag. For example:
$ node --debug myprogram.js # or node --debug-brk ...
In another terminal:
$ trepanjs --attach # add --port or --host if needed
The most obvious difference between this debugger and other gdb-like debuggers is that commands that get evaluated are Javascript commands. So when you need to pass arguments to a debugger command you enclose it in parenthesis. For example:
list(5) // list source code starting from line 5
As a special hack, an evaluation preprocessing step turns list 5
info list(5)
and list
into list()
. But it doesn't catch more elaborate things like set('listsize', 10)
or adding quotes around parameters such as would be needed for help *
to make it help '*'
or help('*')
.
And while on the topic of the list command... Although the command name hasn't changed, the way it works behaves differently. The one here is more like gdb. Subsequent list commands continue from where you last left off. And if you supply a number parameter, it is the starting line location, not a number of lines before and after the current line. A optional second parameter gives the ending line to stop listing at; however if that number is less than the starting line it is interpreted as a number of lines to count instead.
We retain the setBreakpoint command, but we add aliases b, and break. The reason break, and continue are aliases rather than the command name is that these are also JavaScript reserved words. We have some fancy magic for taking your input transforming it for aliases. We however don't do that for command names.
## Command ReferenceNote: this lags a little behind in detail from what you can get from the help inside the debugger.
### Displays-
display
– add a display expression -
undisplay
– remove a previously set display expression
You can display expression and variable values while debugging your code. On every breakpoint each expression from the display list will be evaluated in the current context and displayed just before the breakpoint's source code listing.
To start watching an expression, type display("my_expression")
. info('display')
prints the active watchers. To remove a watcher, type
undisplay("my_expression")
.
-
cont
,continue
,c
– Continue execution -
next
,n
– Step over -
step
,s
– Step in -
finish
,fin
– Step out -
pause
– Pause running code (like pause button in Developer Tools)
-
setBreakpoint()
,break
,b()
– Set breakpoint on current line -
setBreakpoint(line)
,break(line)
,b(line)
– Set breakpoint on specific line -
setBreakpoint('fn()')
,break(fn()
,b(fn())
– Set breakpoint on a first statement in fn's function body -
setBreakpoint('script.js', 1)
,b(...)
– Set breakpoint on first line of script.js -
clearBreakpoint
,cb(...)
– Clear breakpoint
It is also possible to set a breakpoint in a file (module) that isn't loaded yet:
% ./trepanjs test/fixtures/break-in-module/main.js
debugger listening on port 5858
connecting to port 5858... ok
break in test/fixtures/break-in-module/main.js:1
1 var mod = require('./mod.js');
2 mod.hello();
3 mod.hello();
(trepanjs) setBreakpoint('mod.js', 23)
Warning: script 'mod.js' was not loaded yet.
1 var mod = require('./mod.js');
2 mod.hello();
3 mod.hello();
(trepanjs) c
break in test/fixtures/break-in-module/mod.js:23
21
22 exports.hello = function() {
23 return 'hello from module';
24 };
25
(trepanjs)
-
backtrace
,bt
– Print backtrace of current execution frame -
list()
– List scripts source code. You can also give a starting line and an ending line breakpoint like this:list(43,45)
. If the ending line is less than the starting line, then it is taken to be a count. Solist(43,3)
is the same thing. -
shell
– Open node repl but evaluation is in debugging script's context. -
eval
,eval?
– evaluate in the context of the debugged program.
-
run
– Run script (automatically runs on debugger's start) -
restart
– Restart script -
quit
q
,exit
– terminate debugger. You can pass a number to set the exit code. For examplequit(1)
will quit with exit code 1. The default exit code is 0.
-
show('args')
– debugged program invocation arguments. These are used onrun
andrestart
-
show('listsize')
– number of lines displayed in alist
command -
show('version')
– Display trepanjs' and v8's version -
show('width)
– terminal width
For those that are used to the nodejs debugger command set, note that I've added an alias command you used to get those other names in.
A number of the status and error messages are different as they more closely follow message in the other trepannning debuggers. Often give status is given a debugger command succeeds rather than the old Unix-style of no output just prompt.
Frame-changing commands, up, down, and frame have been added. Evaluation changes with the context of the current frame set.
Evaluation of input whose first token is not a debugger command is
done in the context of the debugged program. This differs from node
debug. If you have a variable myvar in your program, and you enter
myvar
, you'll see that value. In node debug, you'll get a
reference error because myvar is not a debugger command.
Here is a table of specific command differences:
trepanjs | nodejs |
---|---|
info('breakpoints') | breakpoints |
display | watch |
undisplay | unwatch |
info('files') | scripts |
finish | out |
shell | repl |
show('version') | version |