javascript_runtime.go 1.89 KB
Newer Older
1
package javascript
obscuren's avatar
obscuren committed
2 3 4

import (
	"fmt"
obscuren's avatar
obscuren committed
5 6 7 8
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
obscuren's avatar
obscuren committed
9
	"github.com/ethereum/go-ethereum/logger"
10
	"github.com/ethereum/go-ethereum/xeth"
11
	"github.com/obscuren/otto"
obscuren's avatar
obscuren committed
12 13
)

obscuren's avatar
obscuren committed
14
var jsrelogger = logger.NewLogger("JSRE")
zelig's avatar
zelig committed
15

obscuren's avatar
obscuren committed
16
type JSRE struct {
obscuren's avatar
obscuren committed
17 18
	Vm   *otto.Otto
	xeth *xeth.XEth
obscuren's avatar
obscuren committed
19 20

	objectCb map[string][]otto.Value
obscuren's avatar
obscuren committed
21 22
}

23 24 25
func (jsre *JSRE) LoadExtFile(path string) {
	result, err := ioutil.ReadFile(path)
	if err == nil {
26
		jsre.Vm.Run(result)
27
	} else {
28
		jsrelogger.Infoln("Could not load file:", path)
29 30 31 32
	}
}

func (jsre *JSRE) LoadIntFile(file string) {
33
	assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
34 35 36
	jsre.LoadExtFile(path.Join(assetPath, file))
}

obscuren's avatar
obscuren committed
37
func NewJSRE(xeth *xeth.XEth) *JSRE {
obscuren's avatar
obscuren committed
38 39
	re := &JSRE{
		otto.New(),
obscuren's avatar
obscuren committed
40
		xeth,
obscuren's avatar
obscuren committed
41 42 43
		make(map[string][]otto.Value),
	}

obscuren's avatar
obscuren committed
44
	// Init the JS lib
45
	re.Vm.Run(jsLib)
obscuren's avatar
obscuren committed
46

47
	// Load extra javascript files
48
	re.LoadIntFile("bignumber.min.js")
49

obscuren's avatar
obscuren committed
50
	re.Bind("eth", &JSEthereum{re.xeth, re.Vm})
obscuren's avatar
obscuren committed
51

obscuren's avatar
obscuren committed
52
	re.initStdFuncs()
obscuren's avatar
obscuren committed
53

zelig's avatar
zelig committed
54 55
	jsrelogger.Infoln("started")

obscuren's avatar
obscuren committed
56 57
	return re
}
obscuren's avatar
obscuren committed
58

obscuren's avatar
obscuren committed
59
func (self *JSRE) Bind(name string, v interface{}) {
60
	self.Vm.Set(name, v)
obscuren's avatar
obscuren committed
61
}
obscuren's avatar
obscuren committed
62

obscuren's avatar
obscuren committed
63
func (self *JSRE) Run(code string) (otto.Value, error) {
64
	return self.Vm.Run(code)
obscuren's avatar
obscuren committed
65 66
}

obscuren's avatar
obscuren committed
67 68 69 70 71 72
func (self *JSRE) initStdFuncs() {
	t, _ := self.Vm.Get("eth")
	eth := t.Object()
	eth.Set("require", self.require)
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
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 {
92
		return otto.UndefinedValue()
93 94 95 96 97 98
	}
	if err := self.Require(file); err != nil {
		fmt.Println("err:", err)
		return otto.UndefinedValue()
	}

99
	t, _ := self.Vm.Get("exports")
100

101
	return t
obscuren's avatar
obscuren committed
102
}