node package manager
Easy sharing. Manage teams and permissions with one click. Create a free org »

terrarium

terrarium

build status

Terrarium is a sandbox for running JavaScript code with instrumentation. It's designed for interactive, learnable programming environments, but architecturally is more similar to code coverage tools.

Terrarium is not a security sandbox and is trivially easy to exploit.

How it Works

parse: Terrarium accepts a string of JavaScript source code. It parses this code with esprima. If this parse fails, it emits an error with the esprima-generated syntax error: this lets us normalize this class of errors across browsers and node versions.

transform: It then uses js-traverse to walk every node in the esprima-generated AST, finding comment nodes. Each comment is transformed into an instrumentation call. In node, that means using process.send.

generate: This AST is then turned back into JavaScript by escodegen.

run: The resulting JavaScript is run by either an iframe, or by process.fork, as specified below.

API

Terrarium provides two APIs: Terrarium.Browser and Terrarium.Node. They have the same behavior on separate platforms.

  • Browser runs code in a web browser by using an iframe and calling functions in window.top
  • Node runs code in a subprocess by using .fork and calling process.send

Terrarium.Browser is designed to be used with browserify.

The Terrarium.Browser API also accepts an options object to its constructor. The options include:

  • sandbox: an object of JavaScript objects to be transferred into the running context.

Example

var t = new Terrarium.Browser();
// or var t = new Terrarium.Node(); 
 
t.on('data', function(data) { /* instrumentation */ });
t.on('err', function(data) { /* errors */ });
 
t.run(JAVASCRIPT_SOURCE);
 
// later... 
t.destroy(); // shut down 

FAQ

  • Why not vm.runInContext: this was the previous approach. Terrarium now uses a child process because this allows it to bind to ports and effectively cancel listeners on close.
  • Why not eval(): eval doesn't provide variable sandboxing, so it's easy to overwrite existing variables on your page. It also doesn't allow you to control timers.