/ Interp

An interp encapsulates the run-time state of a javascript interpreter. We can dynamically configure and/or query interp options as follows:

{ args:[  ], callTrace:0, compat:false, ... }

In Jsi there are 3 ways to change an interps options:


jsish --I typeCheck:error foo.s
JSI_INTERP_OPTS='{typeCheck:["parse"]}' jsish foo.js


A sub-interp provides a separated environment in which to run scripts, eg.

var interp1 = new Interp();
delete interp1;

When we use eval to execute code in an interp, execution is normally in the foreground.

To use asynchronous execution we set the second argument to true.

var i = new Interp();
i.eval("doWork();", true);

See the Interp Reference for interface details about creating and using sub-interps.


Sub-interps may be created with the isSafe option for restricting access to the file system:

var interp1 = new Interp({isSafe:true});
File.write('/tmp/stuff.txt', abc'); // This will throw an error...

Additional options are available to relax these limitations, such as:

var interp1 = new Interp({isSafe:true, safeWriteDirs:['/tmp'], , safeReadDirs:['/tmp']});

From the command-line, safe execution of scripts can be invoked via -S:

jsish -S tests/while.js a b c
jsish -S tests/file.js a b c;  // kicks a file access error.
jsish -S         // With no arguments runs the safe interp in interactive mode

The implemenatation is here.


A sub-interp can be created in a threaded:

var interp1 = new Interp({subthread:true, scriptFile:'mythrd.js'});
interp1.eval("doWork();", true);

Note: If a scriptFile/scriptStr option is not given at create time, the thread blocks waiting for events.

Using a non-asynchronous eval() on a threaded interp, will block the caller until the thread calls sleep() or update() with sleep time. The same goes for source() and uplevel().

Several Interp commands are not supported with threads, such as:


Interpreters can create alias commands with prepended arguments.

function foo(a,b) {
  puts('A='+a+' B='+b);

Interp.alias('bar', foo, [3]);

Similarly an alias can be set in a sub-interp.

var i = new Interp();

function myAlias(interp,name,arg1,arg2) {
   puts('myAlias: interp name arg1 '+arg2);

function myAlias2(arg1,arg2) {
   puts('myAlias2: arg1 '+arg2);

i.alias('foo', myAlias, [i, 'foo']);
i.alias('bar', myAlias2,null);
puts(i.alias()); puts(i.alias('foo'));
puts(i.alias('foo', myAlias));
i.eval('var bb = {x:1};');
i.alias('bb.fig', myAlias, [i, 'bb.fig']);
i.alias('bb.fig', myAlias, [i, 'bb.FIG']);

To delete an aliases just redefine as null.

i.alias('bb.fig', null, null);
try { i.eval('bb.fig(1)'); } catch(e) { puts("CAUGHT ERROR: "+e); }; puts("OK");

Warning: Aliases can not be create in a threaded sub-interpreter.


When we create an interpreter, we can pass in an number of options. The available options are described here.

We can also set or get options for the current interpreter in the usual way:

Note: Options marked as initOnly may only be set at interpreter creation time.

Interp.conf(); // Dump all options
Interp.conf('strict'); // Get one option
Interp.conf({strict:false, maxDepth:99}); // Set one or more options.


Events in javascript are traditionally created by the standard setTimeout()/setInterval() methods.

In Jsi, various commands and extensions (eg. websockets) implement asynchronous features that use events.

Events explicitly get processed by calls to update(). For more details see Events.


Due to overhead of parsing, eval() is actually the least efficient way to run commands.

The two other, faster alternatives are call() and send().

call() will invoke a method that is already defined in an interp.

This is much more efficient as there is no parsing involved, and just like eval() it takes an async argument.

var cmd = "
    function recv2(s) { puts('recv2: '+s.toString()); return {x:8, y:9}; };
    thrd = Info.interp().thread;
    puts('Child starting: '+(thrd?'true':'false'));
    while (thrd) {

var cnt=0, i = new Interp({subthread:true, scriptStr:cmd});

var obj = {AA:1,BB:2};
var aobj = [obj];
var ret;
while (cnt<10) {
  if (((cnt++)%3)==0)
      i.eval("puts('Hello from main**Note**:**Note**:**Note**:**Note**:**Note**:**Note**:**Note**:**Note**:');");
  ret = i.call('recv2',aobj);


send() is used to pass messages via the function named in the recvCallback option of the interps.

This asynchronous function, which simply receives an array of messages, is actually the most efficient way to communicate between interps.

var cmd = *"
    function recv(s) { puts('recv: '+s.toString()); };
    thrd = Info.interp().thread;
    puts('Child starting: '+(thrd?'true':'false'));
    while (thrd) {

function myrecv(s) { puts('>>>>>>>>>>MYRECV: '+s.toString()); };

var cnt=0, i = new Interp({subthread:true, scriptStr:cmd, recvCallback:'recv'});

var obj = {AA:1,BB:2};
var aobj = [obj];
while (cnt<10) {

Interps and Data

To reduce coupling and increase integrity within interpreters, data objects are never shared.

To accomplish this, all data is internally converted to and from JSON at the Interp-Interp interface.

This all happens automatically, so normally users don't need to be worry about the details.

But there are potential performance issues with this JSON translation.


The environment variable JSIINTERPOPTS can be used for running scripts with certain Interp options set:

JSI_INTERP_OPTS="{memDebug:1, maxOpCnt:1000000}" jsish myscript.js

This is important as it allows options to be set before an interpreter starts.

For example, in the case of memDebug, it is vital that no Value memory be allocated before hand, otherwise detection of memory leaks will not be accurate.

Thus this is the only way this particular option can be set.

Backward Compatibility

The compat option is provided to support backward compatibility with code written which uses options available in future releases of Jsi. Running such code with an older Jsi can cause script parse errors due to unknown options. We can prevent this by adding to the script:


This provides an alternative to adding conditionals with Info.version().

The application may still not work correctly, but at least parsing won't fail.