Skip to content
R. Bernstein edited this page May 12, 2015 · 30 revisions
Table of Contents
# Debugger
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.

## Example

To 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.

## Other ways to enter the debugger

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
## Debugger Command Syntax

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 Reference

Note: 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").

### Stepping Commands
  • 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)
### Breakpoints
  • 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)
### Program State
  • 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. So list(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.
### Execution control
  • 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 example quit(1) will quit with exit code 1. The default exit code is 0.
### Set * `set('args')` – set debugged program invocation arguments. These are used on `run` and `restart` * `set('listsize')` – set number of lines displayed in a `list` command * `show('width)` – set terminal width ### Show
  • show('args') – debugged program invocation arguments. These are used on run and restart
  • show('listsize') – number of lines displayed in a list command
  • show('version') – Display trepanjs' and v8's version
  • show('width) – terminal width
### Info * `info('args)` – List argument variables of a stack frame * `info('breakpoints')` – List registered breakpoints * `info('display')` – List all displays * `info('files')` – List all loaded scripts * `info('frame)` – List information about a stack frame * `info('locals)` – Show the local variables of a stack frame * `info('program)` – Execution status of the program * `info('return)` – Show return value ## Differences from gdb and the Trepanning debugger family

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.

Command differences

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
Clone this wiki locally