diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-12-21 19:56:11 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-21 19:56:11 +0800 |
commit | 5258785c81959109138ebeca613f12c277188abc (patch) | |
tree | b3d21fc2f38927841f44541a3717b69f5a3c5ec1 /vendor/gopkg.in/olebedev/go-duktape.v3/timers.go | |
parent | 1a5425779b026587e36f5d21a6e50efe17cc6a9d (diff) | |
download | go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar.gz go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar.bz2 go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar.lz go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar.xz go-tangerine-5258785c81959109138ebeca613f12c277188abc.tar.zst go-tangerine-5258785c81959109138ebeca613f12c277188abc.zip |
cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
Diffstat (limited to 'vendor/gopkg.in/olebedev/go-duktape.v3/timers.go')
-rw-r--r-- | vendor/gopkg.in/olebedev/go-duktape.v3/timers.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/gopkg.in/olebedev/go-duktape.v3/timers.go b/vendor/gopkg.in/olebedev/go-duktape.v3/timers.go new file mode 100644 index 000000000..e12ee1f2e --- /dev/null +++ b/vendor/gopkg.in/olebedev/go-duktape.v3/timers.go @@ -0,0 +1,136 @@ +package duktape + +import ( + "errors" + "fmt" + "time" +) + +// DefineTimers defines `setTimeout`, `clearTimeout`, `setInterval`, +// `clearInterval` into global context. +func (d *Context) PushTimers() error { + d.PushGlobalStash() + // check if timers already exists + if !d.HasPropString(-1, "timers") { + d.PushObject() + d.PutPropString(-2, "timers") // stash -> [ timers:{} ] + d.Pop() + + d.PushGlobalGoFunction("setTimeout", setTimeout) + d.PushGlobalGoFunction("setInterval", setInterval) + d.PushGlobalGoFunction("clearTimeout", clearTimeout) + d.PushGlobalGoFunction("clearInterval", clearTimeout) + return nil + } else { + d.Pop() + return errors.New("Timers are already defined") + } +} + +func (d *Context) FlushTimers() { + d.PushGlobalStash() + d.PushObject() + d.PutPropString(-2, "timers") // stash -> [ timers:{} ] + d.Pop() +} + +func setTimeout(c *Context) int { + id := c.pushTimer(0) + timeout := c.ToNumber(1) + if timeout < 1 { + timeout = 1 + } + go func(id float64) { + <-time.After(time.Duration(timeout) * time.Millisecond) + c.Lock() + defer c.Unlock() + if c.duk_context == nil { + fmt.Println("[duktape] Warning!\nsetTimeout invokes callback after the context was destroyed.") + return + } + + // check if timer still exists + c.putTimer(id) + if c.GetType(-1).IsObject() { + c.Pcall(0 /* nargs */) + } + c.dropTimer(id) + }(id) + c.PushNumber(id) + return 1 +} + +func clearTimeout(c *Context) int { + if c.GetType(0).IsNumber() { + c.dropTimer(c.GetNumber(0)) + c.Pop() + } + return 0 +} + +func setInterval(c *Context) int { + id := c.pushTimer(0) + timeout := c.ToNumber(1) + if timeout < 1 { + timeout = 1 + } + go func(id float64) { + ticker := time.NewTicker(time.Duration(timeout) * time.Millisecond) + for _ = range ticker.C { + c.Lock() + // check if duktape context exists + if c.duk_context == nil { + c.dropTimer(id) + c.Pop() + ticker.Stop() + fmt.Println("[duktape] Warning!\nsetInterval invokes callback after the context was destroyed.") + c.Unlock() + continue + } + + // check if timer still exists + c.putTimer(id) + if c.GetType(-1).IsObject() { + c.Pcall(0 /* nargs */) + c.Pop() + } else { + c.dropTimer(id) + c.Pop() + ticker.Stop() + } + c.Unlock() + } + }(id) + c.PushNumber(id) + return 1 +} + +func (d *Context) pushTimer(index int) float64 { + id := d.timerIndex.get() + + d.PushGlobalStash() + d.GetPropString(-1, "timers") + d.PushNumber(id) + d.Dup(index) + d.PutProp(-3) + d.Pop2() + + return id +} + +func (d *Context) dropTimer(id float64) { + d.PushGlobalStash() + d.GetPropString(-1, "timers") + d.PushNumber(id) + d.DelProp(-2) + d.Pop2() +} + +func (d *Context) putTimer(id float64) { + d.PushGlobalStash() // stash -> [ ..., timers: { <id>: { func: true } } ] + d.GetPropString(-1, "timers") // stash -> [ ..., timers: { <id>: { func: true } } }, { <id>: { func: true } ] + d.PushNumber(id) + d.GetProp(-2) // stash -> [ ..., timers: { <id>: { func: true } } }, { <id>: { func: true }, { func: true } ] + d.Replace(-3) + d.Pop() +} |