Documentation ¶
Overview ¶
Package jail is a generated GoMock package.
Package 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/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
- Variables
- type Cell
- func (c *Cell) Call(item string, this interface{}, args ...interface{}) (JSValue, error)
- func (c *Cell) CallAsync(fn otto.Value, args ...interface{}) error
- func (c *Cell) Get(key string) (JSValue, error)
- func (c *Cell) GetObjectValue(v otto.Value, name string) (JSValue, error)
- func (c *Cell) Run(src interface{}) (JSValue, error)
- func (c *Cell) Set(key string, val interface{}) error
- func (c *Cell) Stop() error
- type JSCell
- type JSValue
- type Jail
- func (j *Jail) Call(chatID, commandPath, args string) string
- func (j *Jail) Cell(chatID string) (JSCell, error)
- func (j *Jail) CreateAndInitCell(chatID string, code ...string) string
- func (j *Jail) CreateCell(chatID string) (JSCell, error)
- func (j *Jail) Execute(chatID, code string) string
- func (j *Jail) Parse(chatID, code string) string
- func (j *Jail) RPCClient() *rpc.Client
- func (j *Jail) SetBaseJS(js string)
- func (j *Jail) Stop()
- type Manager
- type MockJSCell
- func (m *MockJSCell) Call(item string, this interface{}, args ...interface{}) (JSValue, error)
- func (m *MockJSCell) EXPECT() *MockJSCellMockRecorder
- func (m *MockJSCell) Get(arg0 string) (JSValue, error)
- func (m *MockJSCell) Run(arg0 interface{}) (JSValue, error)
- func (m *MockJSCell) Set(arg0 string, arg1 interface{}) error
- func (m *MockJSCell) Stop() error
- type MockJSCellMockRecorder
- func (mr *MockJSCellMockRecorder) Call(item, this interface{}, args ...interface{}) *gomock.Call
- func (mr *MockJSCellMockRecorder) Get(arg0 interface{}) *gomock.Call
- func (mr *MockJSCellMockRecorder) Run(arg0 interface{}) *gomock.Call
- func (mr *MockJSCellMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call
- func (mr *MockJSCellMockRecorder) Stop() *gomock.Call
- type MockManager
- func (m *MockManager) Call(chatID, this, args string) string
- func (m *MockManager) Cell(chatID string) (JSCell, error)
- func (m *MockManager) CreateAndInitCell(chatID string, code ...string) string
- func (m *MockManager) CreateCell(chatID string) (JSCell, error)
- func (m *MockManager) EXPECT() *MockManagerMockRecorder
- func (m *MockManager) Execute(chatID, code string) string
- func (m *MockManager) Parse(chatID, js string) string
- func (m *MockManager) SetBaseJS(js string)
- func (m *MockManager) Stop()
- type MockManagerMockRecorder
- func (mr *MockManagerMockRecorder) Call(chatID, this, args interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) Cell(chatID interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) CreateAndInitCell(chatID interface{}, code ...interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) CreateCell(chatID interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) Execute(chatID, code interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) Parse(chatID, js interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) SetBaseJS(js interface{}) *gomock.Call
- func (mr *MockManagerMockRecorder) Stop() *gomock.Call
- type RPCClientProvider
Constants ¶
const ( // EmptyResponse is returned when cell is successfully created and initialized // but no additional JS was provided to the initialization method. EmptyResponse = `{"result": ""}` )
Variables ¶
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 {
// contains filtered or unexported fields
}
Cell represents a single jail cell, which is basically a JavaScript VM.
func NewCell ¶
NewCell encapsulates what we need to create a new jailCell from the provided vm and eventloop instance.
func (*Cell) Call ¶
Call calls Call on the underlying JavaScript VM and returns a wrapper around the otto.Value.
func (*Cell) CallAsync ¶
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) Get ¶
Get calls Get on the underlying JavaScript VM and returns a wrapper around the otto.Value.
func (*Cell) GetObjectValue ¶
GetObjectValue calls GetObjectValue on the underlying JavaScript VM and returns a wrapper around the otto.Value.
func (*Cell) Run ¶
Run calls Run on the underlying JavaScript VM and returns a wrapper around the otto.Value.
type JSCell ¶
type JSCell interface { // Set a value inside VM. Set(string, interface{}) error // Get a value from VM. Get(string) (JSValue, error) // Run an arbitrary JS code. Input maybe string or otto.Script. Run(interface{}) (JSValue, error) // Call an arbitrary JS function by name and args. Call(item string, this interface{}, args ...interface{}) (JSValue, error) // Stop stops background execution of cell. Stop() error }
JSCell represents single jail cell, which is basically a JavaScript VM. It's designed to be a transparent wrapper around otto.VM's methods.
type JSValue ¶
type JSValue struct {
// contains filtered or unexported fields
}
JSValue is a wrapper around an otto.Value.
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 NewWithBaseJS ¶
func NewWithBaseJS(provider RPCClientProvider, code string) *Jail
NewWithBaseJS returns a new Jail with base JS configured.
func (*Jail) Call ¶
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 ¶
Cell returns a cell by chatID. If it does not exist, error is returned. Required by the Backend.
func (*Jail) CreateAndInitCell ¶
CreateAndInitCell creates and initializes new Cell.
func (*Jail) CreateCell ¶
CreateCell creates a new cell. It returns an error if a cell with a given ID already exists.
func (*Jail) Parse ¶
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.
type Manager ¶
type Manager interface { // Call executes given JavaScript function w/i a jail cell context identified by the chatID. Call(chatID, this, args string) string // CreateCell creates a new jail cell. CreateCell(chatID string) (JSCell, error) // 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. Parse(chatID, js string) string // CreateAndInitCell creates a new jail cell and initialize it // with web3 and other handlers. CreateAndInitCell(chatID string, code ...string) string // Cell returns an existing instance of JSCell. Cell(chatID string) (JSCell, error) // Execute allows to run arbitrary JS code within a cell. Execute(chatID, code string) string // SetBaseJS allows to setup initial JavaScript to be loaded on each jail.CreateAndInitCell(). SetBaseJS(js string) // Stop stops all background activity of jail Stop() }
Manager defines methods for managing jailed environments
type MockJSCell ¶
type MockJSCell struct {
// contains filtered or unexported fields
}
MockJSCell is a mock of JSCell interface
func NewMockJSCell ¶
func NewMockJSCell(ctrl *gomock.Controller) *MockJSCell
NewMockJSCell creates a new mock instance
func (*MockJSCell) Call ¶
func (m *MockJSCell) Call(item string, this interface{}, args ...interface{}) (JSValue, error)
Call mocks base method
func (*MockJSCell) EXPECT ¶
func (m *MockJSCell) EXPECT() *MockJSCellMockRecorder
EXPECT returns an object that allows the caller to indicate expected use
func (*MockJSCell) Get ¶
func (m *MockJSCell) Get(arg0 string) (JSValue, error)
Get mocks base method
func (*MockJSCell) Run ¶
func (m *MockJSCell) Run(arg0 interface{}) (JSValue, error)
Run mocks base method
func (*MockJSCell) Set ¶
func (m *MockJSCell) Set(arg0 string, arg1 interface{}) error
Set mocks base method
type MockJSCellMockRecorder ¶
type MockJSCellMockRecorder struct {
// contains filtered or unexported fields
}
MockJSCellMockRecorder is the mock recorder for MockJSCell
func (*MockJSCellMockRecorder) Call ¶
func (mr *MockJSCellMockRecorder) Call(item, this interface{}, args ...interface{}) *gomock.Call
Call indicates an expected call of Call
func (*MockJSCellMockRecorder) Get ¶
func (mr *MockJSCellMockRecorder) Get(arg0 interface{}) *gomock.Call
Get indicates an expected call of Get
func (*MockJSCellMockRecorder) Run ¶
func (mr *MockJSCellMockRecorder) Run(arg0 interface{}) *gomock.Call
Run indicates an expected call of Run
func (*MockJSCellMockRecorder) Set ¶
func (mr *MockJSCellMockRecorder) Set(arg0, arg1 interface{}) *gomock.Call
Set indicates an expected call of Set
func (*MockJSCellMockRecorder) Stop ¶
func (mr *MockJSCellMockRecorder) Stop() *gomock.Call
Stop indicates an expected call of Stop
type MockManager ¶
type MockManager struct {
// contains filtered or unexported fields
}
MockManager is a mock of Manager interface
func NewMockManager ¶
func NewMockManager(ctrl *gomock.Controller) *MockManager
NewMockManager creates a new mock instance
func (*MockManager) Call ¶
func (m *MockManager) Call(chatID, this, args string) string
Call mocks base method
func (*MockManager) Cell ¶
func (m *MockManager) Cell(chatID string) (JSCell, error)
Cell mocks base method
func (*MockManager) CreateAndInitCell ¶
func (m *MockManager) CreateAndInitCell(chatID string, code ...string) string
CreateAndInitCell mocks base method
func (*MockManager) CreateCell ¶
func (m *MockManager) CreateCell(chatID string) (JSCell, error)
CreateCell mocks base method
func (*MockManager) EXPECT ¶
func (m *MockManager) EXPECT() *MockManagerMockRecorder
EXPECT returns an object that allows the caller to indicate expected use
func (*MockManager) Execute ¶
func (m *MockManager) Execute(chatID, code string) string
Execute mocks base method
func (*MockManager) Parse ¶
func (m *MockManager) Parse(chatID, js string) string
Parse mocks base method
func (*MockManager) SetBaseJS ¶
func (m *MockManager) SetBaseJS(js string)
SetBaseJS mocks base method
type MockManagerMockRecorder ¶
type MockManagerMockRecorder struct {
// contains filtered or unexported fields
}
MockManagerMockRecorder is the mock recorder for MockManager
func (*MockManagerMockRecorder) Call ¶
func (mr *MockManagerMockRecorder) Call(chatID, this, args interface{}) *gomock.Call
Call indicates an expected call of Call
func (*MockManagerMockRecorder) Cell ¶
func (mr *MockManagerMockRecorder) Cell(chatID interface{}) *gomock.Call
Cell indicates an expected call of Cell
func (*MockManagerMockRecorder) CreateAndInitCell ¶
func (mr *MockManagerMockRecorder) CreateAndInitCell(chatID interface{}, code ...interface{}) *gomock.Call
CreateAndInitCell indicates an expected call of CreateAndInitCell
func (*MockManagerMockRecorder) CreateCell ¶
func (mr *MockManagerMockRecorder) CreateCell(chatID interface{}) *gomock.Call
CreateCell indicates an expected call of CreateCell
func (*MockManagerMockRecorder) Execute ¶
func (mr *MockManagerMockRecorder) Execute(chatID, code interface{}) *gomock.Call
Execute indicates an expected call of Execute
func (*MockManagerMockRecorder) Parse ¶
func (mr *MockManagerMockRecorder) Parse(chatID, js interface{}) *gomock.Call
Parse indicates an expected call of Parse
func (*MockManagerMockRecorder) SetBaseJS ¶
func (mr *MockManagerMockRecorder) SetBaseJS(js interface{}) *gomock.Call
SetBaseJS indicates an expected call of SetBaseJS
func (*MockManagerMockRecorder) Stop ¶
func (mr *MockManagerMockRecorder) Stop() *gomock.Call
Stop indicates an expected call of Stop
type RPCClientProvider ¶
RPCClientProvider is an interface that provides a way to obtain an rpc.Client.