|
|
@ -102,8 +102,8 @@ func randomSource() *rand.Rand { |
|
|
|
// call the functions of the otto vm directly to circumvent the queue. These
|
|
|
|
// call the functions of the otto vm directly to circumvent the queue. These
|
|
|
|
// functions should be used if and only if running a routine that was already
|
|
|
|
// functions should be used if and only if running a routine that was already
|
|
|
|
// called from JS through an RPC call.
|
|
|
|
// called from JS through an RPC call.
|
|
|
|
func (self *JSRE) runEventLoop() { |
|
|
|
func (re *JSRE) runEventLoop() { |
|
|
|
defer close(self.closed) |
|
|
|
defer close(re.closed) |
|
|
|
|
|
|
|
|
|
|
|
vm := otto.New() |
|
|
|
vm := otto.New() |
|
|
|
r := randomSource() |
|
|
|
r := randomSource() |
|
|
@ -202,14 +202,14 @@ loop: |
|
|
|
break loop |
|
|
|
break loop |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
case req := <-self.evalQueue: |
|
|
|
case req := <-re.evalQueue: |
|
|
|
// run the code, send the result back
|
|
|
|
// run the code, send the result back
|
|
|
|
req.fn(vm) |
|
|
|
req.fn(vm) |
|
|
|
close(req.done) |
|
|
|
close(req.done) |
|
|
|
if waitForCallbacks && (len(registry) == 0) { |
|
|
|
if waitForCallbacks && (len(registry) == 0) { |
|
|
|
break loop |
|
|
|
break loop |
|
|
|
} |
|
|
|
} |
|
|
|
case waitForCallbacks = <-self.stopEventLoop: |
|
|
|
case waitForCallbacks = <-re.stopEventLoop: |
|
|
|
if !waitForCallbacks || (len(registry) == 0) { |
|
|
|
if !waitForCallbacks || (len(registry) == 0) { |
|
|
|
break loop |
|
|
|
break loop |
|
|
|
} |
|
|
|
} |
|
|
@ -223,31 +223,31 @@ loop: |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Do executes the given function on the JS event loop.
|
|
|
|
// Do executes the given function on the JS event loop.
|
|
|
|
func (self *JSRE) Do(fn func(*otto.Otto)) { |
|
|
|
func (re *JSRE) Do(fn func(*otto.Otto)) { |
|
|
|
done := make(chan bool) |
|
|
|
done := make(chan bool) |
|
|
|
req := &evalReq{fn, done} |
|
|
|
req := &evalReq{fn, done} |
|
|
|
self.evalQueue <- req |
|
|
|
re.evalQueue <- req |
|
|
|
<-done |
|
|
|
<-done |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// stops the event loop before exit, optionally waits for all timers to expire
|
|
|
|
// stops the event loop before exit, optionally waits for all timers to expire
|
|
|
|
func (self *JSRE) Stop(waitForCallbacks bool) { |
|
|
|
func (re *JSRE) Stop(waitForCallbacks bool) { |
|
|
|
select { |
|
|
|
select { |
|
|
|
case <-self.closed: |
|
|
|
case <-re.closed: |
|
|
|
case self.stopEventLoop <- waitForCallbacks: |
|
|
|
case re.stopEventLoop <- waitForCallbacks: |
|
|
|
<-self.closed |
|
|
|
<-re.closed |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Exec(file) loads and runs the contents of a file
|
|
|
|
// Exec(file) loads and runs the contents of a file
|
|
|
|
// if a relative path is given, the jsre's assetPath is used
|
|
|
|
// if a relative path is given, the jsre's assetPath is used
|
|
|
|
func (self *JSRE) Exec(file string) error { |
|
|
|
func (re *JSRE) Exec(file string) error { |
|
|
|
code, err := ioutil.ReadFile(common.AbsolutePath(self.assetPath, file)) |
|
|
|
code, err := ioutil.ReadFile(common.AbsolutePath(re.assetPath, file)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
var script *otto.Script |
|
|
|
var script *otto.Script |
|
|
|
self.Do(func(vm *otto.Otto) { |
|
|
|
re.Do(func(vm *otto.Otto) { |
|
|
|
script, err = vm.Compile(file, code) |
|
|
|
script, err = vm.Compile(file, code) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
return |
|
|
@ -259,36 +259,36 @@ func (self *JSRE) Exec(file string) error { |
|
|
|
|
|
|
|
|
|
|
|
// Bind assigns value v to a variable in the JS environment
|
|
|
|
// Bind assigns value v to a variable in the JS environment
|
|
|
|
// This method is deprecated, use Set.
|
|
|
|
// This method is deprecated, use Set.
|
|
|
|
func (self *JSRE) Bind(name string, v interface{}) error { |
|
|
|
func (re *JSRE) Bind(name string, v interface{}) error { |
|
|
|
return self.Set(name, v) |
|
|
|
return re.Set(name, v) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Run runs a piece of JS code.
|
|
|
|
// Run runs a piece of JS code.
|
|
|
|
func (self *JSRE) Run(code string) (v otto.Value, err error) { |
|
|
|
func (re *JSRE) Run(code string) (v otto.Value, err error) { |
|
|
|
self.Do(func(vm *otto.Otto) { v, err = vm.Run(code) }) |
|
|
|
re.Do(func(vm *otto.Otto) { v, err = vm.Run(code) }) |
|
|
|
return v, err |
|
|
|
return v, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Get returns the value of a variable in the JS environment.
|
|
|
|
// Get returns the value of a variable in the JS environment.
|
|
|
|
func (self *JSRE) Get(ns string) (v otto.Value, err error) { |
|
|
|
func (re *JSRE) Get(ns string) (v otto.Value, err error) { |
|
|
|
self.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) }) |
|
|
|
re.Do(func(vm *otto.Otto) { v, err = vm.Get(ns) }) |
|
|
|
return v, err |
|
|
|
return v, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Set assigns value v to a variable in the JS environment.
|
|
|
|
// Set assigns value v to a variable in the JS environment.
|
|
|
|
func (self *JSRE) Set(ns string, v interface{}) (err error) { |
|
|
|
func (re *JSRE) Set(ns string, v interface{}) (err error) { |
|
|
|
self.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) }) |
|
|
|
re.Do(func(vm *otto.Otto) { err = vm.Set(ns, v) }) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// loadScript executes a JS script from inside the currently executing JS code.
|
|
|
|
// loadScript executes a JS script from inside the currently executing JS code.
|
|
|
|
func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { |
|
|
|
func (re *JSRE) loadScript(call otto.FunctionCall) otto.Value { |
|
|
|
file, err := call.Argument(0).ToString() |
|
|
|
file, err := call.Argument(0).ToString() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
// TODO: throw exception
|
|
|
|
// TODO: throw exception
|
|
|
|
return otto.FalseValue() |
|
|
|
return otto.FalseValue() |
|
|
|
} |
|
|
|
} |
|
|
|
file = common.AbsolutePath(self.assetPath, file) |
|
|
|
file = common.AbsolutePath(re.assetPath, file) |
|
|
|
source, err := ioutil.ReadFile(file) |
|
|
|
source, err := ioutil.ReadFile(file) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
// TODO: throw exception
|
|
|
|
// TODO: throw exception
|
|
|
@ -305,10 +305,10 @@ func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { |
|
|
|
|
|
|
|
|
|
|
|
// Evaluate executes code and pretty prints the result to the specified output
|
|
|
|
// Evaluate executes code and pretty prints the result to the specified output
|
|
|
|
// stream.
|
|
|
|
// stream.
|
|
|
|
func (self *JSRE) Evaluate(code string, w io.Writer) error { |
|
|
|
func (re *JSRE) Evaluate(code string, w io.Writer) error { |
|
|
|
var fail error |
|
|
|
var fail error |
|
|
|
|
|
|
|
|
|
|
|
self.Do(func(vm *otto.Otto) { |
|
|
|
re.Do(func(vm *otto.Otto) { |
|
|
|
val, err := vm.Run(code) |
|
|
|
val, err := vm.Run(code) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
prettyError(vm, err, w) |
|
|
|
prettyError(vm, err, w) |
|
|
@ -321,8 +321,8 @@ func (self *JSRE) Evaluate(code string, w io.Writer) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Compile compiles and then runs a piece of JS code.
|
|
|
|
// Compile compiles and then runs a piece of JS code.
|
|
|
|
func (self *JSRE) Compile(filename string, src interface{}) (err error) { |
|
|
|
func (re *JSRE) Compile(filename string, src interface{}) (err error) { |
|
|
|
self.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) }) |
|
|
|
re.Do(func(vm *otto.Otto) { _, err = compileAndRun(vm, filename, src) }) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|