diff options
Diffstat (limited to 'jsre/jsre.go')
-rw-r--r-- | jsre/jsre.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/jsre/jsre.go b/jsre/jsre.go new file mode 100644 index 000000000..7ae5be742 --- /dev/null +++ b/jsre/jsre.go @@ -0,0 +1,115 @@ +package jsre + +import ( + "fmt" + "github.com/obscuren/otto" + "io/ioutil" + + "github.com/ethereum/go-ethereum/ethutil" +) + +/* +JSRE is a generic JS runtime environment embedding the otto JS interpreter. +It provides some helper functions to +- load code from files +- run code snippets +- require libraries +- bind native go objects +*/ +type JSRE struct { + assetPath string + vm *otto.Otto +} + +func New(assetPath string) *JSRE { + re := &JSRE{ + assetPath, + otto.New(), + } + + // load prettyprint func definition + re.vm.Run(pp_js) + re.vm.Set("loadScript", re.loadScript) + + return re +} + +// Exec(file) loads and runs the contents of a file +// if a relative path is given, the jsre's assetPath is used +func (self *JSRE) Exec(file string) error { + return self.exec(ethutil.AbsolutePath(self.assetPath, file)) +} + +func (self *JSRE) exec(path string) error { + code, err := ioutil.ReadFile(path) + if err != nil { + return err + } + _, err = self.vm.Run(code) + return err +} + +func (self *JSRE) Bind(name string, v interface{}) (err error) { + self.vm.Set(name, v) + return +} + +func (self *JSRE) Run(code string) (otto.Value, error) { + return self.vm.Run(code) +} + +func (self *JSRE) Get(ns string) (otto.Value, error) { + return self.vm.Get(ns) +} + +func (self *JSRE) Set(ns string, v interface{}) error { + return self.vm.Set(ns, v) +} + +func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value { + file, err := call.Argument(0).ToString() + if err != nil { + return otto.FalseValue() + } + if err := self.Exec(file); err != nil { + fmt.Println("err:", err) + return otto.FalseValue() + } + + return otto.TrueValue() +} + +func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) { + var method otto.Value + v, err = self.vm.ToValue(v) + if err != nil { + return + } + method, err = self.vm.Get("prettyPrint") + if err != nil { + return + } + return method.Call(method, v) +} + +func (self *JSRE) ToVal(v interface{}) otto.Value { + result, err := self.vm.ToValue(v) + if err != nil { + fmt.Println("Value unknown:", err) + return otto.UndefinedValue() + } + return result +} + +func (self *JSRE) Eval(code string) (s string, err error) { + var val otto.Value + val, err = self.Run(code) + if err != nil { + return + } + val, err = self.PrettyPrint(val) + if err != nil { + return + } + return fmt.Sprintf("%v", val), nil +} |