window.markdeepOptions={tocStyle:"medium"} Develop


  1.1  Modules
    1.1.1  Options
    1.1.2  Templates
    1.1.3  Help
    1.1.4  Structure
  1.2  Files
    1.2.1  Source
    1.2.2  Load
    1.2.3  Provide
    1.2.4  Require
    1.2.5  PkgDirs
    1.2.6  Autoload
    1.2.7  AutoFiles
  1.3  Debugging
    1.3.1  Logging
    1.3.2  Debugger
    1.3.3  Execution Trace
    1.3.4  Code Profile
    1.3.5  Code Coverage
  1.4  Web
    1.4.1  Client
    1.4.2  Server
  1.5  Sqlite
    1.5.1  Usage
  1.6  GUI
    1.6.1  Database Dump
  1.7  Applications
    1.7.1  Ledger

Javascript Shell Interpreter

Types Builtin Reference  Index  Fossil  Demos Log Test Debug Misc



Code in Jsish is usually developed as modules, which are usable either by code or the command-line.



The most basic Jsi module is a function with array parameter:

function add(args) { return args.join(', '); }

When the file rootname matches the function name, we can invoke it with "-m”:

jsish -m add.jsi Able Baker Charlie
Able, Baker, Charlie

Note "-m” is equivalent to adding an explicit runModule():

function add(args) { return args.join(', '); } runModule(add);


A Jsi module that can handle switches uses parseOpts:

function add(args, conf) { var self = {}; parseOpts(self, {start:0, name:''}, conf); return', '); } runModule(add);

This places leading switches into self:

jsish foo3.jsi -name 'Dog: ' -start 1 Able Baker Charlie
Dog: Baker, Charlie

A Jsi module can:



Creating a new module with a template is simple, eg:

jsish -m -create append.jsi

which produces:

#!/usr/bin/env jsish function append(args:array, conf:object=void) { var options = { // A Jsi template module. rootdir :'' // Root directory. }; var self = { }; parseOpts(self, options, conf); function main() { LogDebug('Starting'); if (self.rootdir === '') self.rootdir=Info.scriptDir(); debugger; LogDebug('Done'); } return main(); } provide(append, 1); if (isMain()) runModule(append);

For web modules there is a special template:

jsish -m -create httpd.jsi -web true


Modules support "-h” and "—help”:

jsish add.jsi -h
/home/user/src/ii/add.jsi:3: help: ... . Options are: -name -start Use --help for long help.

Long Help

For longer help we need a more complete module with type-checking and comments:

function add(args:array, conf:object=void) { var self = {}; var options = { // Concat args into list. start:0, // Start position. name:'' // Name prefix. }; parseOpts(self, options, conf); return', '); } runModule(add);

Then comments will be extracted from options:

jsish add.jsi --help
/home/user/src/ii/add.jsi:7: help: ... Concat args into list.. Options are: -name "" // Name prefix. -start 0 // Start position. Accepted by all .jsi modules: -Debug, -Trace, -Test.

Help Limitations

Help information gets extracted from options by parseOpts, with the following limitations:



The various sections of a module are:

Section Description
function All code is wrapped in a function with the same name as the file basename, providing bindings for incoming arguments.
options The var options = object itemizes the all options that can come in via the opts parameter.
self Local object state is stored in the self object. All defined and incoming options will be copied into self.
parseOpts The call parseOpts(self, options, opts) performs option parsing as well as implementing -h help output
provide The provide statement makes the module available as a package.
Info.isMain The isMain() command returns true if the current file was invoked from the command-line.
runModule The runModule() command parses command-line options and then invokes the current module.



Various commands are involved in dealing with files of source code.



function source(val:string|array, options:object=void):void

include file of javascript.

First argument is either a file or array of files.

source('scripts/foo.js'); source(['foo.js'*,*'bar.js']);

A second parameter may be used for setting the following options:

Option Type Description
debug INT Debug level.
auto BOOL Setup for load of autoload.jsi files.
isMain BOOL Force isMain() to true.

Various source related options can be configured/examined in the usual way:

Interp.conf({maxIncDepth:10}); var cur = Info.script(); var dir = Info.scriptDir();

The above changes the recursive maximum depth of source from it's default of 100.



function load(shlib:string):void

load shared library extension into memory.

On Windows, the extensions .dll is used instead of .so.


For more details see Extensions.



function provide(name:string, version:number=1):void

Used to make the current file name available for a require.

A package file is of the form name.EXT or name/name.EXT; name may contain only the characters _ 0-9 a-z A-Z.

This file is either a Jsi script (.jsi) containing a provide(name) call, or shared library (.so/.dll) containing a Jsi_PkgProvide().



function require(name:string=void, version:number=1):number|array|object

Require is used to load/query packages.

If a version argument is given, and it is greater than package version, a warning is generated.


Package files are searched for in the following paths:



Packages are searched for are specified by pkgDirs, which can be set pkgDirs using:

Interp.conf({pkgDirs:['/usr/local/lib', '/usr/share']});

When a package is not found in pkgDirs, the executable and main script directories are checked.

Sub-interps inherit pkgDirs from the parent.



Because it is sometimes desirable to defer loading code until first invocation, Jsi provides a mechanism using member values in the object Jsi_Auto to evaluate. For example, given the file myfunc.js:

provide('myfunc'); function double(n) { return n*2; }; function half(n) { return n/2; };

We can arrange for dynamic sourcing with:

Jsi_Auto.double = Jsi_Auto.half = 'require("myfunc");'; double(4); // Load is triggered! half(4);

This also works for object commands:

Jsi_Auto.MySql = "require('MySql')"; //... var db = new MySql({user:'root', database:'jsitest'});


Jsi_Auto can be dynamically setup.

When Jsi first tries to invoke an undefined function, it first traverses a list of files given in the interp option autoFiles.

The default jsish value is:

[ "/zvfs/lib/autoload.jsi" ]

Which means it loads the file Zip-FS on /zvfs.

After this Jsi_Auto members are accessed to load the function.

Additionally, if an application is run from a .zip file, it's autoload.jsi file gets added to autoFiles automatically.

This 2-stage approach results in no overhead, until a function call fails.


Object Functions

Autoloading non-constructor object functions can use the following approach (the example ignores the fact that JSON is not actually loadable):

var JSON = { parse: function() { require('JSON'); return JSON.parse.apply(this,arguments); }, stringify: function() { require('JSON'); return JSON.stringify.apply(this,arguments); } //... } JSON.parse(str); // Load is triggered!

Although that works, it suffers from one problem: the first call will not type-check functions.

We could fix this shortcoming with:

var JSON = { check: function(str:string, strict:boolean=false):boolean { require('JSON'); return JSON.check.apply(this,arguments); }, //... };

But correctly transcribing function signatures is more complicated.

Fortunately there is a helper:

function Jsi_AutoMake(objName:string):string

This can be used to generate the auto file:

File.write( Jsi_AutoMake('JSON'), 'autoload.jsi');

The file autoload.jsi now contains calls and load and type-check correctly:

var JSON = { check: function(str:string, strict:boolean=true):boolean { require('JSON'); return JSON.check.apply(this,arguments); }, parse: function(str:string, strict:boolean=true):any { require('JSON'); return JSON.parse.apply(this,arguments); }, stringify: function(obj:object, strict:boolean=true):string { require('JSON'); return JSON.stringify.apply(this,arguments); }, };




LogDebug statements appear only when a module is run with "-Debug”:

function foo(args, conf) {
    var self = {};
    parseOpts(self, {start:0, name:''}, conf);
    LogDebug('Starting', args);
    return', ');
jsish foo.jsi -Debug true  a b
"DEBUG: Starting [ "a", "b" ]", foo.jsi:4, foo() a, b

Similarly for LogTrace and LogTest.

When logging is disabled, log op-Codes are ignored by Jsi, so no resources get used.



There are two debuggers. The command-line:

jsish -d myscr.jsi arg1

And the Web-GUI:

jsish -D myscr.jsi arg1

See debuggers.


Execution Trace

Jsi provides a number of program tracing options. Perhaps the easiest to use is from the command-line with -t:

jsish -t tests/module.js
/home/user/jsi/jsi/tests/module.js:12 #1: > mod([]) /home/user/jsi/jsi/tests/module.js:12 #1: < mod() <-- { process:function (a) {...}, x:1, y:2 } /home/user/jsi/jsi/tests/module.js:22 #1: > process([ 9 ]) /home/user/jsi/jsi/tests/module.js:17 #2: > sub([ 10 ]) /home/user/jsi/jsi/tests/module.js:17 #2: < sub() <-- 20 /home/user/jsi/jsi/tests/module.js:22 #1: < process() <-- 20 20 1 /home/user/jsi/jsi/tests/module.js:36 #1: > fmod([]) /home/user/jsi/jsi/tests/module.js:36 #1: < fmod() <-- { process:function (a) {...}, x:1, y:2 } /home/user/jsi/jsi/tests/module.js:37 #1: > process([ 9 ]) /home/user/jsi/jsi/tests/module.js:31 #2: > sub([ 10 ]) /home/user/jsi/jsi/tests/module.js:31 #2: < sub() <-- 20 /home/user/jsi/jsi/tests/module.js:37 #1: < process() <-- 20 20 1

The output may seem overly verbose, but is advantageous when executed from within geany (or vim) in that we can click to navigate through the file.

If simpler traces are desired, try:

jsish -ItraceCall funcs,args tests/module.js
#1: > mod([]) in module.js:12 #1: > process([ 9 ]) in module.js:22 #2: > sub([ 10 ]) in module.js:17 20 1 #1: > fmod([]) in module.js:36 #1: > process([ 9 ]) in module.js:37 #2: > sub([ 10 ]) in module.js:31 20 1

Code Profile

Jsi can output detailed execution profile information for functions using:

jsish -Iprofile true  SCRIPT

The following demonstrates this on unix:

jsish -Iprofile true  /tmp/while2.js   2>&1 | grep ^PROFILE: | sort -g -r -t= -k2
PROFILE: TOTAL: time=4.169039, func=3.099403, cmd=1.068323, #funcs=10003, #cmds=300001, cover=58.0%, #values=1860447, #objs=610397 PROFILE: self=3.000902 all=4.069200 #calls=10000 self/call=0.000300 all/call=0.000407 cover=100.0% func=foo file=/tmp/while2.js:29 PROFILE: self=1.068298 all=1.068298 #calls=300000 self/call=0.000004 all/call=0.000004 cmd=Info.funcs PROFILE: self=0.098484 all=4.167684 #calls=1 self/call=0.098484 all/call=4.167684 cover= 75.0% func=bar file=/tmp/while2.js:44 PROFILE: self=0.000024 all=0.000024 #calls=1 self/call=0.000024 all/call=0.000024 cmd=puts PROFILE: self=0.000017 all=4.167700 #calls=1 self/call=0.000017 all/call=4.167700 cover=100.0% func=aa file=/tmp/while2.js:27 PROFILE: self=0.000002 all=0.000002 #calls=1 self/call=0.000002 all/call=0.000002 cover= 7.0% func=cc file=/tmp/while2.js:7

All times are in seconds, and output is sorted by self time (descending).

Following is a list of fields in the PROFILE: TOTAL: line:

Field Description
time Total amount of CPU used by the program run
func Total mount of CPU used by functions
cmd Total mount of CPU used by commands
#funcs Total number of function calls
#cmds Total number of command calls (non-functions)
cover Total code coverage in percent (functions only)
#values Total number of Jsi_Value allocations
#objs Total number of Jsi_Obj allocations

Following is a list of fields in each PROFILE line:

Field Description
self Amount of CPU used by the function
all Amount of CPU used by function and it's descendants
#calls Number of times function was called
self/call Per-call CPU used by the function
all/call Per-call CPU used by the function and it's descendants
cover Code coverage for function, in percent
func Name of the function
cmd Name of the command
file File and line number of function


Code Coverage

In addition to the simple coverage statistics available with profile, detailed code coverage can be obtained with -Icoverage, eg:

jsish -Icoverage true  /tmp/while2.js   2>&1 | grep ^COVERAGE: | sort -g -r -t= -k4
COVERAGE: func=bar file=/tmp/while2.js:48 cover=75.0% hits=6, all=8, misses=56-57 COVERAGE: func=cc file=/tmp/while2.js:7 cover=30.0% hits=4, all=13, misses=10-13,18-22 COVERAGE: func=bb file=/tmp/while2.js:27 cover=0%

Output is produced only for functions with less than 100% coverage. Uncalled functions are indicated by cover=0% with remaining fields omitted.

Following is a list of the COVERAGE fields:

Field Description
func Name of the function
file File and line number for start of function
cover Code coverage in percent for the function
hits Number of distinct lines executed in the function
all Total number of executable lines in the function
misses List of line-ranges not executed





To download a file from the web we can use:

jsish -w -O


The builtin web server can open it in a local browser and serve out html to it, from the command-line:

jsish -W index.html

and programmatically:





Basic Sqlite usage:

var db = new Sqlite('mydata.db');
db.query('SELECT * FROM tbl');
[ { a:99, b:1 }, { a:95, b:2 }, { a:91, b:3 } ]


The database GUI is invoked using:

jsish -S mydata.db

Database Dump

To dump a database use:

jsish -S -dump true mydata.db

which produces output like the sqlite .dump command.





fossil clone jsi-app.fossil
jsish -a jsi-app.fossil Ledger

var startOfMarkDeep=true; window.alreadyProcessedMarkdeep||('visible'); document.title=location.pathname.match(/\/([\w]+)1;

formatted by Markdeep 1.03