Not logged in

The logging facilitity in Jsi outputs messages in a way that is particularly useful for debugging applications.

Log Bindings

Jsi provides a set of bindings that output messages that include a prefix and the file and line number, for example:

var i = 0;
while  (i++ < 3) {
    LogInfo("test loop: %d", i);

which outputs:

mytest.jsi:3, "INFO:  test loop: 1", 
mytest.jsi:3, "INFO:  test loop: 2", 
mytest.jsi:3, "INFO:  test loop: 3", 

This can be useful when running scripts from geany, where you can navigate through the messages just as you would compiler warnings.

The available Log commands are:

Command Notes
LogDebug Outputs only when interp logOpts.debug is true
LogTrace Outputs only when interp logOpts.trace is true
LogTest Outputs only when interp logOpts.test is true

Remember that these commands use printf style formatting, so a percent should be escaped with %%.

Debug Logging

The commands LogDebug, LogTrace, and LogTest are special in that unless they are enabled, there is no output.

We enable LogDebug with "use debug" as in this example:

"use debug,test";
var i = 0;
while  (i++ < 2) {
    LogDebug("test loop: %d", i);
    LogTrace("test loop: %d", i);
    LogTest("test loop: %d", i);

which outputs:

mydebug.jsi:4, "DEBUG: test loop: 1", 
mydebug.jsi:5, "TRACE: test loop: 1", 
mydebug.jsi:4, "DEBUG: test loop: 2", 
mydebug.jsi:5, "TRACE: test loop: 2", 

In the discussion below, descriptions mentioning LogDebug apply equally to LogTrace, and LogTest.

Enabling Logs

As shown above, one way logging can be enable is by inserting a use directive.

There are two other ways of doing it, from the command-line:

jsish -T debug,trace mydebug2.jsi 
JSI_INTERP_OPTS='{logOpts:{debug:true,trace:true}}' jsish mydebug2.jsi

Note however that command-line options are overriden by use directives:

"use !debug";
LogDebug("can't appear");

No-Op Arguments

It is important to understand that when disabled, the LogDebug functions and their arguments are essentially No-Ops, as in this example:

var i = 0, k = 0;
while  (i++ < 3) {
    LogDebug("test loop: %d, %d", i, k++);
printf("K=%d\n", k);

Running the above may seem confusing at first:

jsish myincr.jsi

jsish -T debug myincr.jsi
myincr.jsi:3, "DEBUG: test loop: 1, 0", 
myincr.jsi:3, "DEBUG: test loop: 2, 1", 
myincr.jsi:3, "DEBUG: test loop: 3, 2", 

But the explanation is simply that when debugging is disabled, both calls and argument marshalling code are elided and have no effect.

This may seem counter-intuitive, but it means that code may be peppered with LogDebug commands while experiencing virtually no runtime penalty (until enabled).

Local Logging

In larger applications, it may be undesirable to turn on logging globally.

Here is an example using Jsi_Logs() to enable function local logging:

function test(msg, debug) {
    Jsi_Logs({debug:debug}, this);
    LogDebug("testing 1, 2, 3: %s", msg);
test('call1', false);
test('call2', true);

which produces:

jsish myincr.jsi
mycall.jsi:3, "DEBUG: testing 1, 2, 3: call2", test()

jsish -T debug mycall.jsi
mycall.jsi:3, "DEBUG: testing 1, 2, 3: call1", test()
mycall.jsi:3, "DEBUG: testing 1, 2, 3: call2", test()

This demonstrates that logging can be local, global or both.

Modules and Jsi_Opts

Here is a simple but working example using Jsi_Opts with logging:

function mytest1(args:array, opts:object=void) {
    var options = { // Here is my test.
        debug       :false,     // Debugging output
        trace       :false,     // Tracing output
        test        :false,     // Testing output
        label       :''         // Some other argument
    var that = {
        count: 0
    Jsi_Opts(that, options, opts, this);
    // Jsi_Logs(opts, this); /* or could have done this */
    for (var msg in args) {
        LogDebug("testing: %q", msg);

LogDebug("Loading test1");
if (Info.isMain())

This allows us to turn on module-local debugging from the command line:

jsish mytest1.jsi a b c

jsish mytest1.jsi -debug true a b c
mytest1.jsi:16, "DEBUG: testing: 0", mytest1()
mytest1.jsi:16, "DEBUG: testing: 1", mytest1()
mytest1.jsi:16, "DEBUG: testing: 2", mytest1()

jsish mytest1.jsi -h
/zvfs/lib/JsiUtil.jsi:121: error: throw: 
	-debug	 	false
	-label	 	""
	-test	 	false
	-trace	 	false


Interp logOpts

The interp option logOpts is used to control when the above commands are to output the current file, line and function.

It can also arrange for all such messages to be directed to a log file.

If you are debugging a program and need to find where a puts is coming from, try adding to the top


The same can be done from the command-line as in ../tests/assert.js:

"use assert";
JSI_INTERP_OPTS='{logOpts:{puts:true}}'   jsish tests/assert.js
"caught error" --> assert.js:16
"K" --> assert.js:24
"caught error2" --> assert.js:28
"this assert failed" --> assert.js:31
"assert also failed" --> assert.js:34
"done" --> assert.js:36


The low level output commands are:
Command Description
puts Quotes arguments to stdout
printf Format arguments to stdout
log Like puts but includes line info
console.log Like log but outputs to stderr
console.logf Combines printf and console.log

All commands except printf automatically add a newline.

See System and console.


The puts command quotes all of it's arguments and outputs them to stdout. eg.

puts("Batman begins");
var X = {a:1, b:"two"};
puts(X.a, X.b);

which outputs:

Batman begins
{ a:1, b:"two" }
1 two


The printf command processes arguments according to format and outputs to stdout. eg.

printf("Batman begins: %d %s\n", X.a, X.b);

log(arg, ...)

The log command is like puts, but includes the current file, line and function.

console.log(arg, ...)

The console.log is like log, but output goes to stderr.

console.logf(fmt, ...)

The console.logf is like printf and log: it output to stderr and includes the current file, line and function with newline.

assert(expr, msg, noThrow)

assert(expr:boolean|number|function, msg:string, noThrow=false)

The assert command is used for checking constraints.

The assert statement takes 2 or 3 arguments: an expression and a string to throw on error, and the optional boolean noThrow.

When the expression evaluates to false, an error is thrown, eg.

"use assert";
var m = 1, n = -1;
assert(n>=0 && n<100, "passed bad n");

An expression can also be a function whose return value is used.

Note that by default assert is disabled, which means it is a No-Op. Moreover, even arguments are not evaluted, when disable.

Thus the following outputs 0 when assert is disabled.

var m = 0;

When the argument noThrow is true, assert just outputs a message along with current file, line and function.