@@ -27,6 +27,7 @@ import (
2727 "math/rand"
2828 "os"
2929 "strings"
30+ "sync"
3031 "time"
3132
3233 "github.com/robertkrimen/otto"
@@ -55,6 +56,7 @@ type jsTimer struct {
5556// Runtime is a Skydive JavaScript runtime environment
5657type Runtime struct {
5758 * otto.Otto
59+ sync.Mutex
5860 evalQueue chan * evalReq
5961 stopEventLoop chan bool
6062 closed chan struct {}
@@ -386,19 +388,70 @@ func (r *Runtime) Do(fn func(*otto.Otto)) {
386388 <- done
387389}
388390
389- // Exec executes some JavaScript code
391+ // Exec queues the execution of some JavaScript code
390392func (r * Runtime ) Exec (code string ) (v otto.Value , err error ) {
391393 r .Do (func (vm * otto.Otto ) { v , err = vm .Run (code ) })
392394 return v , err
393395}
394396
397+ // ExecFunction queues a CallFunction method
398+ func (r * Runtime ) ExecFunction (source string , params ... interface {}) (v otto.Value , err error ) {
399+ r .Do (func (vm * otto.Otto ) { v , err = r .CallFunction (source , params ... ) })
400+ return v , err
401+ }
402+
403+ // ExecPromise executes a promise and return its result
404+ func (r * Runtime ) ExecPromise (source string , params ... interface {}) (v otto.Value , err error ) {
405+ var done chan otto.Value
406+ r .Do (func (vm * otto.Otto ) { done , err = r .CallPromise (source , params ... ) })
407+ v = <- done
408+ return v , err
409+ }
410+
411+ // CallFunction takes the source of a function and evaluate it with the specifed parameters
412+ func (r * Runtime ) CallFunction (source string , params ... interface {}) (otto.Value , error ) {
413+ result , err := r .Run ("(" + source + ")" )
414+ if err != nil {
415+ return otto .UndefinedValue (), fmt .Errorf ("Error while compile source %s: %s" , source , result .String ())
416+ }
417+
418+ return result .Call (result , params ... )
419+ }
420+
421+ // CallPromise takes the source of a promise and evaluate it with the specifed parameters
422+ func (r * Runtime ) CallPromise (source string , params ... interface {}) (chan otto.Value , error ) {
423+ result , err := r .CallFunction (source , params ... )
424+ if err != nil {
425+ return nil , fmt .Errorf ("Error while executing function: %s" , err )
426+ }
427+
428+ if ! result .IsObject () {
429+ return nil , fmt .Errorf ("Workflow is expected to return a promise, returned %s" , result .Class ())
430+ }
431+
432+ done := make (chan otto.Value )
433+ promise := result .Object ()
434+ finally , err := r .ToValue (func (call otto.FunctionCall ) otto.Value {
435+ result = call .Argument (0 )
436+ done <- result
437+ return result
438+ })
439+
440+ result , _ = promise .Call ("then" , finally )
441+ promise = result .Object ()
442+ promise .Call ("catch" , finally )
443+
444+ return done , nil
445+ }
446+
395447// Start the runtime evaluation loop
396448func (r * Runtime ) Start () {
397449 go r .runEventLoop ()
398450}
399451
400452// Stop the runtime evaluation loop
401453func (r * Runtime ) Stop () {
454+ r .stopEventLoop <- true
402455}
403456
404457// NewRuntime returns a new JavaScript runtime environment
0 commit comments