Browse Source

jsre:
- require became loadScript(), no require is supplied
- bignumber_js.go: heredoc v2.0.3 minified fixed for otto Regexp incompatibility https://github.com/robertkrimen/otto#regular-expression-incompatibility
- bignumber.min.js also updated in mist/assets/ext
- ethereum_js.go: latest master minified
- assetPath in constructor
- Eval/Exec/Handle/ToVal nice API
- jsre tests

zelig 10 years ago
parent
commit
da44097800

File diff suppressed because it is too large
+ 0 - 1
cmd/mist/assets/ext/bignumber.min.js


+ 0 - 103
javascript/javascript_runtime.go

@@ -1,103 +0,0 @@
-package javascript
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path"
-	"path/filepath"
-
-	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/xeth"
-	"github.com/obscuren/otto"
-)
-
-var jsrelogger = logger.NewLogger("JSRE")
-
-type JSRE struct {
-	Vm   *otto.Otto
-	xeth *xeth.XEth
-
-	objectCb map[string][]otto.Value
-}
-
-func (jsre *JSRE) LoadExtFile(path string) {
-	result, err := ioutil.ReadFile(path)
-	if err == nil {
-		jsre.Vm.Run(result)
-	} else {
-		jsrelogger.Infoln("Could not load file:", path)
-	}
-}
-
-func (jsre *JSRE) LoadIntFile(file string) {
-	assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
-	jsre.LoadExtFile(path.Join(assetPath, file))
-}
-
-func NewJSRE(xeth *xeth.XEth) *JSRE {
-	re := &JSRE{
-		otto.New(),
-		xeth,
-		make(map[string][]otto.Value),
-	}
-
-	// Init the JS lib
-	re.Vm.Run(jsLib)
-
-	// Load extra javascript files
-	re.LoadIntFile("bignumber.min.js")
-
-	re.Bind("eth", &JSEthereum{re.xeth, re.Vm})
-
-	re.initStdFuncs()
-
-	jsrelogger.Infoln("started")
-
-	return re
-}
-
-func (self *JSRE) Bind(name string, v interface{}) {
-	self.Vm.Set(name, v)
-}
-
-func (self *JSRE) Run(code string) (otto.Value, error) {
-	return self.Vm.Run(code)
-}
-
-func (self *JSRE) initStdFuncs() {
-	t, _ := self.Vm.Get("eth")
-	eth := t.Object()
-	eth.Set("require", self.require)
-}
-
-func (self *JSRE) Require(file string) error {
-	if len(filepath.Ext(file)) == 0 {
-		file += ".js"
-	}
-
-	fh, err := os.Open(file)
-	if err != nil {
-		return err
-	}
-
-	content, _ := ioutil.ReadAll(fh)
-	self.Run("exports = {};(function() {" + string(content) + "})();")
-
-	return nil
-}
-
-func (self *JSRE) require(call otto.FunctionCall) otto.Value {
-	file, err := call.Argument(0).ToString()
-	if err != nil {
-		return otto.UndefinedValue()
-	}
-	if err := self.Require(file); err != nil {
-		fmt.Println("err:", err)
-		return otto.UndefinedValue()
-	}
-
-	t, _ := self.Vm.Get("exports")
-
-	return t
-}

+ 0 - 94
javascript/types.go

@@ -1,94 +0,0 @@
-package javascript
-
-import (
-	"fmt"
-	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/ethereum/go-ethereum/state"
-	"github.com/ethereum/go-ethereum/xeth"
-	"github.com/obscuren/otto"
-)
-
-type JSStateObject struct {
-	*xeth.Object
-	eth *JSEthereum
-}
-
-func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value {
-	cb := call.Argument(0)
-
-	it := self.Object.Trie().Iterator()
-	for it.Next() {
-		cb.Call(self.eth.toVal(self), self.eth.toVal(ethutil.Bytes2Hex(it.Key)), self.eth.toVal(ethutil.Bytes2Hex(it.Value)))
-	}
-
-	return otto.UndefinedValue()
-}
-
-// The JSEthereum object attempts to wrap the PEthereum object and returns
-// meaningful javascript objects
-type JSBlock struct {
-	*xeth.Block
-	eth *JSEthereum
-}
-
-func (self *JSBlock) GetTransaction(hash string) otto.Value {
-	return self.eth.toVal(self.Block.GetTransaction(hash))
-}
-
-type JSLog struct {
-	Address string   `json:address`
-	Topics  []string `json:topics`
-	Number  int32    `json:number`
-	Data    string   `json:data`
-}
-
-func NewJSLog(log state.Log) JSLog {
-	return JSLog{
-		Address: ethutil.Bytes2Hex(log.Address()),
-		Topics:  nil, //ethutil.Bytes2Hex(log.Address()),
-		Number:  0,
-		Data:    ethutil.Bytes2Hex(log.Data()),
-	}
-}
-
-type JSEthereum struct {
-	*xeth.XEth
-	vm *otto.Otto
-}
-
-func (self *JSEthereum) Block(v interface{}) otto.Value {
-	if number, ok := v.(int64); ok {
-		return self.toVal(&JSBlock{self.XEth.BlockByNumber(number), self})
-	} else if hash, ok := v.(string); ok {
-		return self.toVal(&JSBlock{self.XEth.BlockByHash(hash), self})
-	}
-
-	return otto.UndefinedValue()
-}
-
-func (self *JSEthereum) GetStateObject(addr string) otto.Value {
-	return self.toVal(&JSStateObject{self.XEth.State().SafeGet(addr), self})
-}
-
-func (self *JSEthereum) Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
-	r, err := self.XEth.Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr)
-	if err != nil {
-		fmt.Println(err)
-
-		return otto.UndefinedValue()
-	}
-
-	return self.toVal(r)
-}
-
-func (self *JSEthereum) toVal(v interface{}) otto.Value {
-	result, err := self.vm.ToValue(v)
-
-	if err != nil {
-		fmt.Println("Value unknown:", err)
-
-		return otto.UndefinedValue()
-	}
-
-	return result
-}

File diff suppressed because it is too large
+ 4 - 0
jsre/bignumber_js.go


File diff suppressed because it is too large
+ 2 - 0
jsre/ethereum_js.go


+ 115 - 0
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
+}

+ 85 - 0
jsre/jsre_test.go

@@ -0,0 +1,85 @@
+package jsre
+
+import (
+	"github.com/obscuren/otto"
+	"os"
+	"path"
+	"testing"
+
+	"github.com/ethereum/go-ethereum/ethutil"
+)
+
+var defaultAssetPath = path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
+
+type testNativeObjectBinding struct {
+	toVal func(interface{}) otto.Value
+}
+
+type msg struct {
+	Msg string
+}
+
+func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value {
+	m, err := call.Argument(0).ToString()
+	if err != nil {
+		return otto.UndefinedValue()
+	}
+	return no.toVal(&msg{m})
+}
+
+func TestExec(t *testing.T) {
+	jsre := New("/tmp")
+
+	ethutil.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
+	err := jsre.Exec("test.js")
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+	val, err := jsre.Run("msg")
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+	if !val.IsString() {
+		t.Errorf("expected string value, got %v", val)
+	}
+
+	// this errors
+	err = jsre.Exec(path.Join(defaultAssetPath, "bignumber.min.js"))
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+	_, err = jsre.Run("x = new BigNumber(123.4567);")
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+}
+
+func TestBind(t *testing.T) {
+	jsre := New(defaultAssetPath)
+
+	jsre.Bind("no", &testNativeObjectBinding{jsre.ToVal})
+
+	val, err := jsre.Run(`no.testMethod("testMsg")`)
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+	pp, err := jsre.PrettyPrint(val)
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+	t.Logf("no: %v", pp)
+}
+
+func TestRequire(t *testing.T) {
+	jsre := New(defaultAssetPath)
+
+	_, err := jsre.Run("x = new BigNumber(123.4567);")
+	if err == nil {
+		t.Errorf("expected error, got nothing")
+	}
+	_, err = jsre.Run(`loadScript("bignumber.min.js"); x = new BigNumber(123.4567)`)
+	if err != nil {
+		t.Errorf("expected no error, got %v", err)
+	}
+
+}

+ 3 - 3
javascript/js_lib.go → jsre/pp_js.go

@@ -1,6 +1,6 @@
-package javascript
+package jsre
 
 
-const jsLib = `
+const pp_js = `
 function pp(object) {
 function pp(object) {
     var str = "";
     var str = "";
 
 
@@ -34,7 +34,7 @@ function pp(object) {
     } else if(typeof(object) === "function") {
     } else if(typeof(object) === "function") {
 	str += "\033[35m[Function]";
 	str += "\033[35m[Function]";
     } else {
     } else {
-        str += object;                    
+        str += object;
     }
     }
 
 
     str += "\033[0m";
     str += "\033[0m";

Some files were not shown because too many files changed in this diff