|
@@ -24,7 +24,6 @@ import (
|
|
|
"io"
|
|
"io"
|
|
|
"io/ioutil"
|
|
"io/ioutil"
|
|
|
"math/rand"
|
|
"math/rand"
|
|
|
- "sync"
|
|
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
@@ -44,7 +43,7 @@ type JSRE struct {
|
|
|
output io.Writer
|
|
output io.Writer
|
|
|
evalQueue chan *evalReq
|
|
evalQueue chan *evalReq
|
|
|
stopEventLoop chan bool
|
|
stopEventLoop chan bool
|
|
|
- loopWg sync.WaitGroup
|
|
|
|
|
|
|
+ closed chan struct{}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// jsTimer is a single timer instance with a callback function
|
|
// jsTimer is a single timer instance with a callback function
|
|
@@ -66,10 +65,10 @@ func New(assetPath string, output io.Writer) *JSRE {
|
|
|
re := &JSRE{
|
|
re := &JSRE{
|
|
|
assetPath: assetPath,
|
|
assetPath: assetPath,
|
|
|
output: output,
|
|
output: output,
|
|
|
|
|
+ closed: make(chan struct{}),
|
|
|
evalQueue: make(chan *evalReq),
|
|
evalQueue: make(chan *evalReq),
|
|
|
stopEventLoop: make(chan bool),
|
|
stopEventLoop: make(chan bool),
|
|
|
}
|
|
}
|
|
|
- re.loopWg.Add(1)
|
|
|
|
|
go re.runEventLoop()
|
|
go re.runEventLoop()
|
|
|
re.Set("loadScript", re.loadScript)
|
|
re.Set("loadScript", re.loadScript)
|
|
|
re.Set("inspect", prettyPrintJS)
|
|
re.Set("inspect", prettyPrintJS)
|
|
@@ -98,6 +97,8 @@ func randomSource() *rand.Rand {
|
|
|
// 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 (self *JSRE) runEventLoop() {
|
|
|
|
|
+ defer close(self.closed)
|
|
|
|
|
+
|
|
|
vm := otto.New()
|
|
vm := otto.New()
|
|
|
r := randomSource()
|
|
r := randomSource()
|
|
|
vm.SetRandomSource(r.Float64)
|
|
vm.SetRandomSource(r.Float64)
|
|
@@ -213,8 +214,6 @@ loop:
|
|
|
timer.timer.Stop()
|
|
timer.timer.Stop()
|
|
|
delete(registry, timer)
|
|
delete(registry, timer)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- self.loopWg.Done()
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Do executes the given function on the JS event loop.
|
|
// Do executes the given function on the JS event loop.
|
|
@@ -227,8 +226,11 @@ func (self *JSRE) Do(fn func(*otto.Otto)) {
|
|
|
|
|
|
|
|
// 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 (self *JSRE) Stop(waitForCallbacks bool) {
|
|
|
- self.stopEventLoop <- waitForCallbacks
|
|
|
|
|
- self.loopWg.Wait()
|
|
|
|
|
|
|
+ select {
|
|
|
|
|
+ case <-self.closed:
|
|
|
|
|
+ case self.stopEventLoop <- waitForCallbacks:
|
|
|
|
|
+ <-self.closed
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Exec(file) loads and runs the contents of a file
|
|
// Exec(file) loads and runs the contents of a file
|