jail

package
v0.0.0-...-adbc7b5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2018 License: MPL-2.0 Imports: 19 Imported by: 0

README

jail GoDoc

jail - jailed environment for executing JS code.

Download:

go get github.com/status-im/status-go/geth/jail

jail - jailed environment for executing JS code.

Package jail implements "jailed" environment for executing arbitrary JavaScript code using Otto JS interpreter (https://github.com/robertkrimen/otto).

Jail create multiple Cells, one cell per status client chat. Each cell runs own Otto virtual machine and lives forever, but that may change in the future.

+----------------------------------------------+
|                     Jail                     |
+----------------------------------------------+
+---------+ +---------+ +---------+  +---------+
|  Cell   | |  Cell   | |  Cell   |  |  Cell   |
|ChatID 1 | |ChatID 2 | |ChatID 3 |  |ChatID N |
|+-------+| |+-------+| |+-------+|  |+-------+|
||Otto VM|| ||Otto VM|| ||Otto VM||  ||Otto VM||
|+-------+| |+-------+| |+-------+|  |+-------+|
|| Loop  || || Loop  || || Loop  ||  || Loop  ||
++-------++ ++-------++ ++-------++  ++-------++

Cells

Each Cell object embeds *VM from 'jail/vm' for concurrency safe wrapper around *otto.VM functions. This is important when dealing with setTimeout and Fetch API functions (see below).

Get and Set

(*VM).Get/Set functions provide transparent and concurrently safe wrappers for Otto VM Get and Set functions respectively. See Otto documentation for usage examples: https://godoc.org/github.com/robertkrimen/otto

Call and Run

(*VM).Call/Run functions allows executing arbitrary JS in the cell. They're also wrappers around Otto VM functions of the same name. Run accepts raw JS strings for execution while Call takes a JS function name (defined in VM) and parameters.

Timeouts and intervals support

Default Otto VM interpreter doesn't support setTimeout() / setInterval() JS functions, because they're not part of ECMA-262 spec, but properties of the window object in browser.

We add support for them using own implementation of Event Loop, heavily based on ottoext package. See loop/fetch/promise packages under jail/internal/.

Each cell starts a new loop in a separate goroutine, registers functions for setTimeout / setInterval calls and associate them with this loop. All JS code executed as callback to setTimeout/setInterval will be handled by this loop.

For example, following code:

cell.Run(`setTimeout(function(){ value = "42" }, 2000);`)

will execute setTimeout and return immediately, but callback function will be executed after 2 seconds in the loop that was started upon current cell.

In order to capture response one may use following approach:

err = cell.Set("__captureResponse", func(val string) otto.Value {
	fmt.Println("Captured response from callback:", val)
	return otto.UndefinedValue()
})
cell.Run(`setTimeout(function(){ __captureResponse("OK") }, 2000);`)

Fetch support

Fetch API is implemented in a similar way using the same loop. When Cell is created, corresponding handlers are registered within VM and associated event loop.

Due to asynchronous nature of Fetch API, the following code will return immediately:

cell.Run(`fetch('http://example.com/').then(function(data) { ... })`)

and callback function in a promise will be executed in a event loop in the background. Thus, it's user responsibility to register a corresponding callback function before:

cell.Set("__captureSuccess", func(res otto.Value) { ... })

cell.Run(`fetch('http://example.com').then(function(r) {
	return r.text()
}).then(function(data) {
	// user code
	__captureSuccess(data)
}))

Automatically generated by autoreadme on 2018.02.08

Documentation

Overview

jail - jailed environment for executing JS code.

Package jail implements "jailed" environment for executing arbitrary JavaScript code using Otto JS interpreter (https://github.com/robertkrimen/otto).

Jail create multiple Cells, one cell per status client chat. Each cell runs own Otto virtual machine and lives forever, but that may change in the future.

+----------------------------------------------+
|                     Jail                     |
+----------------------------------------------+
+---------+ +---------+ +---------+  +---------+
|  Cell   | |  Cell   | |  Cell   |  |  Cell   |
|ChatID 1 | |ChatID 2 | |ChatID 3 |  |ChatID N |
|+-------+| |+-------+| |+-------+|  |+-------+|
||Otto VM|| ||Otto VM|| ||Otto VM||  ||Otto VM||
|+-------+| |+-------+| |+-------+|  |+-------+|
|| Loop  || || Loop  || || Loop  ||  || Loop  ||
++-------++ ++-------++ ++-------++  ++-------++

## Cells Each Cell object embeds *VM from 'jail/vm' for concurrency safe wrapper around *otto.VM functions. This is important when dealing with setTimeout and Fetch API functions (see below).

## Get and Set (*VM).Get/Set functions provide transparent and concurrently safe wrappers for Otto VM Get and Set functions respectively. See Otto documentation for usage examples: https://godoc.org/github.com/robertkrimen/otto

## Call and Run (*VM).Call/Run functions allows executing arbitrary JS in the cell. They're also wrappers around Otto VM functions of the same name. `Run` accepts raw JS strings for execution while `Call` takes a JS function name (defined in VM) and parameters.

## Timeouts and intervals support Default Otto VM interpreter doesn't support setTimeout() / setInterval() JS functions, because they're not part of ECMA-262 spec, but properties of the window object in browser.

We add support for them using own implementation of Event Loop, heavily based on [ottoext package](https://github.com/deoxxa/ottoext). See loop/fetch/promise packages under [jail/internal/](https://github.com/status-im/status-go/tree/develop/geth/jail/internal).

Each cell starts a new loop in a separate goroutine, registers functions for setTimeout / setInterval calls and associate them with this loop. All JS code executed as callback to setTimeout/setInterval will be handled by this loop.

For example, following code:

cell.Run(`setTimeout(function(){ value = "42" }, 2000);`)

will execute setTimeout and return immediately, but callback function will be executed after 2 seconds in the loop that was started upon current cell.

In order to capture response one may use following approach:

err = cell.Set("__captureResponse", func(val string) otto.Value {
	fmt.Println("Captured response from callback:", val)
	return otto.UndefinedValue()
})
cell.Run(`setTimeout(function(){ __captureResponse("OK") }, 2000);`)

## Fetch support

Fetch API is implemented in a similar way using the same loop. When Cell is created, corresponding handlers are registered within VM and associated event loop.

Due to asynchronous nature of Fetch API, the following code will return immediately:

cell.Run(`fetch('http://example.com/').then(function(data) { ... })`)

and callback function in a promise will be executed in a event loop in the background. Thus, it's user responsibility to register a corresponding callback function before:

cell.Set("__captureSuccess", func(res otto.Value) { ... })

cell.Run(`fetch('http://example.com').then(function(r) {
	return r.text()
}).then(function(data) {
	// user code
	__captureSuccess(data)
}))

Index

Constants

View Source
const (

	// EmptyResponse is returned when cell is successfully created and initialized
	// but no additional JS was provided to the initialization method.
	EmptyResponse = `{"result": ""}`
)
View Source
const (
	// EventSignal is a signal from jail.
	EventSignal = "jail.signal"
)

Variables

View Source
var (

	// ErrNoRPCClient is returned when an RPC client is required but it's nil.
	ErrNoRPCClient = errors.New("RPC client is not available")
)

Functions

This section is empty.

Types

type Cell

type Cell struct {
	*vm.VM
	// contains filtered or unexported fields
}

Cell represents a single jail cell, which is basically a JavaScript VM.

func NewCell

func NewCell(id string) (*Cell, error)

NewCell encapsulates what we need to create a new jailCell from the provided vm and eventloop instance.

func (*Cell) CallAsync

func (c *Cell) CallAsync(fn otto.Value, args ...interface{}) error

CallAsync puts otto's function with given args into event queue loop and schedules for immediate execution. Intended to be used by any cell user that want's to run async call, like callback.

func (*Cell) Stop

func (c *Cell) Stop() error

Stop halts event loop associated with cell.

type Jail

type Jail struct {
	// contains filtered or unexported fields
}

Jail manages multiple JavaScript execution contexts (JavaScript VMs) called cells. Each cell is a separate VM with web3.js set up.

As rpc.Client might not be available during Jail initialization, a provider function is used.

func New

func New(provider RPCClientProvider) *Jail

New returns a new Jail.

func NewWithBaseJS

func NewWithBaseJS(provider RPCClientProvider, code string) *Jail

NewWithBaseJS returns a new Jail with base JS configured.

func (*Jail) Call

func (j *Jail) Call(chatID, commandPath, args string) string

Call executes the `call` function within a cell with chatID. Returns a string being a valid JS code. In case of a successful result, it's {"result": any}. In case of an error: {"error": "some error"}.

Call calls commands from `_status_catalog`. commandPath is an array of properties to retrieve a function. For instance:

`["prop1", "prop2"]` is translated to `_status_catalog["prop1"]["prop2"]`.

func (*Jail) Cell

func (j *Jail) Cell(chatID string) (common.JailCell, error)

Cell returns a cell by chatID. If it does not exist, error is returned. Required by the Backend.

func (*Jail) CreateAndInitCell

func (j *Jail) CreateAndInitCell(chatID string, code ...string) string

CreateAndInitCell creates and initializes new Cell.

func (*Jail) CreateCell

func (j *Jail) CreateCell(chatID string) (common.JailCell, error)

CreateCell creates a new cell. It returns an error if a cell with a given ID already exists.

func (*Jail) Execute

func (j *Jail) Execute(chatID, code string) string

Execute allows to run arbitrary JS code within a cell.

func (*Jail) Parse

func (j *Jail) Parse(chatID, code string) string

Parse creates a new jail cell context, with the given chatID as identifier. New context executes provided JavaScript code, right after the initialization. DEPRECATED in favour of CreateAndInitCell.

func (*Jail) RPCClient

func (j *Jail) RPCClient() *rpc.Client

RPCClient returns an rpc.Client.

func (*Jail) SetBaseJS

func (j *Jail) SetBaseJS(js string)

SetBaseJS sets initial JavaScript code loaded to each new cell.

func (*Jail) Stop

func (j *Jail) Stop()

Stop stops jail and all assosiacted cells.

type RPCClientProvider

type RPCClientProvider interface {
	RPCClient() *rpc.Client
}

RPCClientProvider is an interface that provides a way to obtain an rpc.Client.

Directories

Path Synopsis
Package ottoext contains some extensions for the otto JavaScript interpreter.
Package ottoext contains some extensions for the otto JavaScript interpreter.
vm

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL