jsish
Debugger
Not logged in

Jsi comes with two debuggers, command-line and GUI.

But before resorting to debugging a script it's usually a good idea to enable strict mode.

Strict Mode

Enhanced script checking is enabled by adding the "use strict" directive to the file:

"use strict";
function foo (a:number, b:string='ok'):number {}

Among other things, strict-mode will generate an error when:

The directive can go at the top of the file (to be global), or inside individual functions (local).


Debugger GUI

Although Jsi's provides a command-line debugger (described below) a web based GUI is also available when Jsi is built with WebSockets, eg:

jsish -D simple.jsi

The DebugUI shares the same commands as the command-line debugger, but adds full-screen Gui features such as source navigation and double-click to set a breakpoint.

The source: ../lib/Jsi_DebugUI/Jsi_DebugUI.jsi


Debugger

Jsi comes with a built-in gdb-like command-line debugger, which is invoked with -d:

jsish -d simple.jsi

The debugger will stop automatically when a debugger; statement is encountered, or anytime an error or warning occurs (eg. during "strict mode").

The source: ../lib/Jsi_Debug.jsi

Commands

The usual debugger commands are supported:

CommandArgumentDescription
break file:line|funcBreak execution at a named function, line or file
continueContinue execution
deleteidDelete one or all breakpoints
disable idDisable one or all breakpoints
downcountMove down one or more stack levels
enableidEnable one or all breakpoints
evalexpressionEvaluate expression in program context
finishRun till return of current function
helpstringDisplay command usage
infobreakpoints|variablesShow status info
listproc|line countList file lines
nextSingle-step over function calls
print namePrint value of variable
quitQuit debugging current program and exit
stepSingle-step into function calls
tbreak Set a temporary breakpoint that is disabled when hit
upcountMove up one or more stack levels
where Display current location
xeval expressionDoes eval in debugger context

Debugging

Here is a sample session on ../tests/simple.js:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> s   
CMD: step
#2:/tmp/simple.js:12    var x = 88; <in function foo()>
#2==> 
#2:/tmp/simple.js:13    foo1(); <in function foo()>
#2==> 
#3:/tmp/simple.js:7    var x = 99; <in function foo1()>
#3==> c
CMD: continue
#4:/tmp/simple.js:3    debugger; <in function foo2()>
#4==> up
CMD: up
#3:/tmp/simple.js:8    foo2(); <in function foo1()>
#3==> p x
CMD: print
RESULT= "99"
#3==> up
CMD: up
#2:/tmp/simple.js:13    foo1(); <in function foo()>
#2==> p x
CMD: print
RESULT= "88"
#2==> 

Note that just like gdb, an empty commands repeats the previous command.

Listing

Source file lines can be displayed with the list command:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> c
CMD: continue
#4:/tmp/simple.js:3    debugger; <in function foo2()>
#2==> l 1 20
CMD: list
FILE: /tmp/simple.js:1
1    : // Simple test script for the debugger.
2    : function foo2() {
3    :   debugger;
4    : }
5    : 
6    : function foo1() {
7    :   var x = 99;
8    :   foo2();
9    : }
10   : 
11   : function foo() {
12   :   var x = 88;

Optional arguments are: startLine|func numLines file

With no arguments the default is to list 10 lines starting from the current line in the current file.

Print

The print command can be used to display the value of variables:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> s
CMD: step
#2:/tmp/simple.js:12    var x = 88; <in function foo()>
#2==> s
CMD: step
#2:/tmp/simple.js:13    foo1(); <in function foo()>
#2==> p x
CMD: print
RESULT= "88"

Eval

The eval command can be used to evaluate expresssions or modify values:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> c
CMD: continue
#4:/tmp/simple.js:3    debugger; <in function foo2()>
#4==> up
CMD: up
#3:/tmp/simple.js:8    foo2(); <in function foo1()>
#3==> p x
CMD: print
RESULT= "99"
#3==> ev x=9
CMD: eval
RESULT= 9
#3==> p x
CMD: print
RESULT= "9"

Breakpoints

Breakpoints can be set, cleared and queried as in the following example:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> s
CMD: step
#2:/tmp/simple.js:12    var x = 88; <in function foo()>
#2==> b
CMD: break
breakpoint #1 set: /tmp/simple.js:12
#2==> b foo
CMD: break
breakpoint #2 set: foo
#2==> c
CMD: continue
Stopped at breakpoint #2
#2:/tmp/simple.js:13    foo1(); <in function foo()>
#2==> info
CMD: info
#1    : enabled=true, hits=0, file=/tmp/simple.js:12
#2    : enabled=true, hits=1, func=foo
#2==> dis 1
CMD: disable
#2==> info
CMD: info
#1    : enabled=false, hits=0, file=/tmp/simple.js:12
#2    : enabled=true,  hits=1, func=foo

Note that the debugger will stop whenever a debugger statement is encountered.

Where

The where command outputs a stack backtrace:

jsish -d /tmp/simple.js
#1:/tmp/simple.js:16  foo(); 
#1==> c
CMD: continue
#4:/tmp/simple.js:3    debugger; <in function foo2()>
#4==> wh
CMD: where
{ fileName:"/tmp/simple.js", funcName:"foo2", level:4, line:3 }
{ fileName:"/tmp/simple.js", funcName:"foo1", level:3, line:8 }
{ fileName:"/tmp/simple.js", funcName:"foo", level:2, line:13 }
{ fileName:"/tmp/simple.js", funcName:"", level:1, line:16 }
#4==> up 2
CMD: up
#2:/tmp/simple.js:13    foo1(); <in function foo()>
#2==> wh
CMD: where
{ fileName:"/tmp/simple.js", funcName:"foo", level:2, line:13 }
{ fileName:"/tmp/simple.js", funcName:"", level:1, line:16 }
#2==>

Implementation Details

The debugger runs the target script in a sub-interpreter. Jsi also bends the rules a bit for debugging mode to make this work seamlessly. A side-effect of this is that a small amount of memory may leak during a debug session (on the order of 6k).