diff --git a/console/console.go b/console/console.go index e7e8723619..bf8d2667d5 100644 --- a/console/console.go +++ b/console/console.go @@ -64,13 +64,14 @@ type Config struct { // JavaScript console attached to a running node via an external or in-process RPC // client. type Console struct { - client *rpc.Client // RPC client to execute Ethereum requests through - jsre *jsre.JSRE // JavaScript runtime environment running the interpreter - prompt string // Input prompt prefix string - prompter UserPrompter // Input prompter to allow interactive user feedback - histPath string // Absolute path to the console scrollback history - history []string // Scroll history maintained by the console - printer io.Writer // Output writer to serialize any display strings to + client *rpc.Client // RPC client to execute Ethereum requests through + jsre *jsre.JSRE // JavaScript runtime environment running the interpreter + prompt string // Input prompt prefix string + prompter UserPrompter // Input prompter to allow interactive user feedback + histPath string // Absolute path to the console scrollback history + history []string // Scroll history maintained by the console + printer io.Writer // Output writer to serialize any display strings to + runtime *goja.Runtime // The javascript runtime } // New initializes a JavaScript interpreted runtime environment and sets defaults @@ -86,10 +87,15 @@ func New(config Config) (*Console, error) { if config.Printer == nil { config.Printer = colorable.NewColorableStdout() } + + // Create the JS runtime + runtime := goja.New() + // Initialize the console and return console := &Console{ + runtime: runtime, client: config.Client, - jsre: jsre.New(config.DocRoot, config.Printer), + jsre: jsre.New(config.DocRoot, config.Printer, runtime), prompt: config.Prompt, prompter: config.Prompter, printer: config.Printer, @@ -108,18 +114,25 @@ func New(config Config) (*Console, error) { // the console's JavaScript namespaces based on the exposed modules. func (c *Console) init(preload []string) error { // Initialize the JavaScript <-> Go RPC bridge - runtime := goja.New() - bridge := newBridge(c.client, c.prompter, c.printer, runtime) - c.jsre.Set("jeth", struct{}{}) - c.jsre.Set("console", struct{}{}) + bridge := newBridge(c.client, c.prompter, c.printer, c.runtime) + c.jsre.Run("jeth = {};") + c.jsre.Run("console = {};") - jethObj := c.jsre.Get("jeth").ToObject(runtime) - jethObj.Set("send", bridge.Send) - jethObj.Set("sendAsync", bridge.Send) + jethObj := c.jsre.Get("jeth").ToObject(c.runtime) + if err := jethObj.Set("send", bridge.Send); err != nil { + panic(err) + } + if err := jethObj.Set("sendAsync", bridge.Send); err != nil { + panic(err) + } - consoleObj := c.jsre.Get("console").ToObject(runtime) - consoleObj.Set("log", c.consoleOutput) - consoleObj.Set("error", c.consoleOutput) + consoleObj := c.runtime.Get("console").ToObject(c.runtime) + if err := consoleObj.Set("log", c.consoleOutput); err != nil { + panic(err) + } + if err := consoleObj.Set("error", c.consoleOutput); err != nil { + panic(err) + } // Load all the internal utility JavaScript libraries if err := c.jsre.Compile("bignumber.js", string(jsre.BignumberJs)); err != nil { @@ -150,7 +163,7 @@ func (c *Console) init(preload []string) error { return fmt.Errorf("%s.js: %v", api, err) } flatten += fmt.Sprintf("var %s = web3.%s; ", api, api) - } else if obj, err := c.jsre.Run("web3." + api); err == nil && obj.ToObject(runtime) != nil { + } else if obj, err := c.jsre.Run("web3." + api); err == nil && obj.ToObject(c.runtime) != nil { // Enable web3.js built-in extension if available. flatten += fmt.Sprintf("var %s = web3.%s; ", api, api) } @@ -173,7 +186,7 @@ func (c *Console) init(preload []string) error { // original web3 callbacks. These will be called by the jeth.* methods after // they got the password from the user and send the original web3 request to // the backend. - if obj := personal.ToObject(runtime); obj != nil { // make sure the personal api is enabled over the interface + if obj := personal.ToObject(c.runtime); obj != nil { // make sure the personal api is enabled over the interface if _, err = c.jsre.Run(`jeth.openWallet = personal.openWallet;`); err != nil { return fmt.Errorf("personal.openWallet: %v", err) } @@ -197,7 +210,7 @@ func (c *Console) init(preload []string) error { if admin == nil { return fmt.Errorf("Could not find admin") } - if obj := admin.ToObject(runtime); obj != nil { // make sure the admin api is enabled over the interface + if obj := admin.ToObject(c.runtime); obj != nil { // make sure the admin api is enabled over the interface obj.Set("sleepBlocks", bridge.SleepBlocks) obj.Set("sleep", bridge.Sleep) obj.Set("clearHistory", c.clearHistory) diff --git a/internal/jsre/jsre.go b/internal/jsre/jsre.go index 7a8b44278a..f6d3bc77f6 100644 --- a/internal/jsre/jsre.go +++ b/internal/jsre/jsre.go @@ -68,13 +68,14 @@ type evalReq struct { } // runtime must be stopped with Stop() after use and cannot be used after stopping -func New(assetPath string, output io.Writer) *JSRE { +func New(assetPath string, output io.Writer, vm *goja.Runtime) *JSRE { re := &JSRE{ assetPath: assetPath, output: output, closed: make(chan struct{}), evalQueue: make(chan *evalReq), stopEventLoop: make(chan bool), + vm: vm, } go re.runEventLoop() re.Set("loadScript", re.loadScript) @@ -106,7 +107,6 @@ func randomSource() *rand.Rand { func (re *JSRE) runEventLoop() { defer close(re.closed) - re.vm = goja.New() r := randomSource() re.vm.SetRandSource(r.Float64) diff --git a/vendor/github.com/dop251/goja/array.go b/vendor/github.com/dop251/goja/array.go index 55f75ebd00..abd24d8bf7 100644 --- a/vendor/github.com/dop251/goja/array.go +++ b/vendor/github.com/dop251/goja/array.go @@ -22,10 +22,6 @@ func (a *arrayObject) init() { a._put("length", &a.lengthProp) } -func (a *arrayObject) getLength() Value { - return intToValue(a.length) -} - func (a *arrayObject) _setLengthInt(l int64, throw bool) bool { if l >= 0 && l <= math.MaxUint32 { ret := true @@ -57,7 +53,7 @@ func (a *arrayObject) _setLengthInt(l int64, throw bool) bool { a.values = ar } else { ar := a.values[l:len(a.values)] - for i, _ := range ar { + for i := range ar { ar[i] = nil } a.values = a.values[:l] diff --git a/vendor/github.com/dop251/goja/array_sparse.go b/vendor/github.com/dop251/goja/array_sparse.go index f8fd8c5692..50340caf6a 100644 --- a/vendor/github.com/dop251/goja/array_sparse.go +++ b/vendor/github.com/dop251/goja/array_sparse.go @@ -27,10 +27,6 @@ func (a *sparseArrayObject) init() { a._put("length", &a.lengthProp) } -func (a *sparseArrayObject) getLength() Value { - return intToValue(a.length) -} - func (a *sparseArrayObject) findIdx(idx int64) int { return sort.Search(len(a.items), func(i int) bool { return a.items[i].idx >= idx @@ -64,7 +60,7 @@ func (a *sparseArrayObject) _setLengthInt(l int64, throw bool) bool { idx := a.findIdx(l) aa := a.items[idx:] - for i, _ := range aa { + for i := range aa { aa[i].value = nil } a.items = a.items[:idx] diff --git a/vendor/github.com/dop251/goja/compiler.go b/vendor/github.com/dop251/goja/compiler.go index 1a95e9c61f..385ac0dc25 100644 --- a/vendor/github.com/dop251/goja/compiler.go +++ b/vendor/github.com/dop251/goja/compiler.go @@ -278,7 +278,7 @@ func (c *compiler) compile(in *ast.Program) { } c.p.code = append(c.p.code, code...) - for i, _ := range c.p.srcMap { + for i := range c.p.srcMap { c.p.srcMap[i].pc += len(c.scope.names) } diff --git a/vendor/github.com/dop251/goja/compiler_expr.go b/vendor/github.com/dop251/goja/compiler_expr.go index 9d215ca0de..7b02025fde 100644 --- a/vendor/github.com/dop251/goja/compiler_expr.go +++ b/vendor/github.com/dop251/goja/compiler_expr.go @@ -770,11 +770,6 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) { needCallee = true } } - lenBefore := len(e.c.scope.names) - namesBefore := make([]string, 0, lenBefore) - for key, _ := range e.c.scope.names { - namesBefore = append(namesBefore, key) - } maxPreambleLen := 2 e.c.p.code = make([]instruction, maxPreambleLen) if needCallee { @@ -801,7 +796,7 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) { e.c.p.code = e.c.p.code[maxPreambleLen-1:] } e.c.convertFunctionToStashless(e.c.p.code, paramsCount) - for i, _ := range e.c.p.srcMap { + for i := range e.c.p.srcMap { e.c.p.srcMap[i].pc -= maxPreambleLen - l } } else { @@ -842,7 +837,7 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) { copy(code[l:], e.c.p.code[maxPreambleLen:]) e.c.p.code = code - for i, _ := range e.c.p.srcMap { + for i := range e.c.p.srcMap { e.c.p.srcMap[i].pc += l - maxPreambleLen } } diff --git a/vendor/github.com/dop251/goja/date.go b/vendor/github.com/dop251/goja/date.go index c17d597cf5..281ed94349 100644 --- a/vendor/github.com/dop251/goja/date.go +++ b/vendor/github.com/dop251/goja/date.go @@ -22,8 +22,6 @@ type dateObject struct { var ( dateLayoutList = []string{ - "2006-01-02T15:04:05.000Z0700", - "2006-01-02T15:04:05.000", "2006-01-02T15:04:05Z0700", "2006-01-02T15:04:05", "2006-01-02", @@ -46,18 +44,12 @@ var ( "2006T15:04:05", "2006-01T15:04:05", - "2006T15:04:05.000", - "2006-01T15:04:05.000", - "2006T15:04Z0700", "2006-01T15:04Z0700", "2006-01-02T15:04Z0700", "2006T15:04:05Z0700", "2006-01T15:04:05Z0700", - - "2006T15:04:05.000Z0700", - "2006-01T15:04:05.000Z0700", } ) diff --git a/vendor/github.com/dop251/goja/func.go b/vendor/github.com/dop251/goja/func.go index 5755c61169..a4927b0097 100644 --- a/vendor/github.com/dop251/goja/func.go +++ b/vendor/github.com/dop251/goja/func.go @@ -1,8 +1,6 @@ package goja -import ( - "reflect" -) +import "reflect" type baseFuncObject struct { baseObject diff --git a/vendor/github.com/dop251/goja/object_goreflect.go b/vendor/github.com/dop251/goja/object_goreflect.go index a946f174ab..4d94d61bc6 100644 --- a/vendor/github.com/dop251/goja/object_goreflect.go +++ b/vendor/github.com/dop251/goja/object_goreflect.go @@ -18,7 +18,7 @@ type FieldNameMapper interface { // If this method returns "" the field becomes hidden. FieldName(t reflect.Type, f reflect.StructField) string - // FieldName returns a JavaScript name for the given method in the given type. + // MethodName returns a JavaScript name for the given method in the given type. // If this method returns "" the method becomes hidden. MethodName(t reflect.Type, m reflect.Method) string } @@ -216,25 +216,23 @@ func (r *Runtime) checkHostObjectPropertyDescr(name string, descr propertyDescr, } func (o *objectGoReflect) defineOwnProperty(n Value, descr propertyDescr, throw bool) bool { - name := n.String() - if ast.IsExported(name) { - if o.value.Kind() == reflect.Struct { - if v := o._getField(name); v.IsValid() { - if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) { - return false - } - val := descr.Value - if val == nil { - val = _undefined - } - vv, err := o.val.runtime.toReflectValue(val, v.Type()) - if err != nil { - o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err) - return false - } - v.Set(vv) - return true + if o.value.Kind() == reflect.Struct { + name := n.String() + if v := o._getField(name); v.IsValid() { + if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) { + return false } + val := descr.Value + if val == nil { + val = _undefined + } + vv, err := o.val.runtime.toReflectValue(val, v.Type()) + if err != nil { + o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err) + return false + } + v.Set(vv) + return true } } @@ -242,9 +240,6 @@ func (o *objectGoReflect) defineOwnProperty(n Value, descr propertyDescr, throw } func (o *objectGoReflect) _has(name string) bool { - if !ast.IsExported(name) { - return false - } if o.value.Kind() == reflect.Struct { if v := o._getField(name); v.IsValid() { return true @@ -508,7 +503,7 @@ func (r *Runtime) typeInfo(t reflect.Type) (info *reflectTypeInfo) { return } -// Sets a custom field name mapper for Go types. It can be called at any time, however +// SetFieldNameMapper sets a custom field name mapper for Go types. It can be called at any time, however // the mapping for any given value is fixed at the point of creation. // Setting this to nil restores the default behaviour which is all exported fields and methods are mapped to their // original unchanged names. diff --git a/vendor/github.com/dop251/goja/runtime.go b/vendor/github.com/dop251/goja/runtime.go index d1484edf62..26c62e703e 100644 --- a/vendor/github.com/dop251/goja/runtime.go +++ b/vendor/github.com/dop251/goja/runtime.go @@ -974,7 +974,7 @@ func (r *Runtime) ToValue(i interface{}) Value { case int64: return intToValue(i) case uint: - if int64(i) <= math.MaxInt64 { + if uint64(i) <= math.MaxInt64 { return intToValue(int64(i)) } else { return floatToValue(float64(i)) @@ -995,6 +995,9 @@ func (r *Runtime) ToValue(i interface{}) Value { case float64: return floatToValue(i) case map[string]interface{}: + if i == nil { + return _null + } obj := &Object{runtime: r} m := &objectGoMapSimple{ baseObject: baseObject{ @@ -1007,6 +1010,9 @@ func (r *Runtime) ToValue(i interface{}) Value { m.init() return obj case []interface{}: + if i == nil { + return _null + } obj := &Object{runtime: r} a := &objectGoSlice{ baseObject: baseObject{ @@ -1018,6 +1024,9 @@ func (r *Runtime) ToValue(i interface{}) Value { a.init() return obj case *[]interface{}: + if i == nil { + return _null + } obj := &Object{runtime: r} a := &objectGoSlice{ baseObject: baseObject{ diff --git a/vendor/github.com/dop251/goja/value.go b/vendor/github.com/dop251/goja/value.go index 8bf103afc9..39225dbd0d 100644 --- a/vendor/github.com/dop251/goja/value.go +++ b/vendor/github.com/dop251/goja/value.go @@ -436,7 +436,7 @@ func (p *valueProperty) get(this Value) Value { } return _undefined } - call, r := p.getterFunc.self.assertCallable() + call, _ := p.getterFunc.self.assertCallable() return call(FunctionCall{ This: this, }) diff --git a/vendor/github.com/dop251/goja/vm.go b/vendor/github.com/dop251/goja/vm.go index c62e9ddb3c..96005aa42a 100644 --- a/vendor/github.com/dop251/goja/vm.go +++ b/vendor/github.com/dop251/goja/vm.go @@ -2,7 +2,6 @@ package goja import ( "fmt" - "log" "math" "runtime" "strconv" @@ -364,11 +363,14 @@ func (vm *vm) try(f func()) (ex *Exception) { case *Exception: ex = x1 default: - if vm.prg != nil { - vm.prg.dumpCode(log.Printf) - } - //log.Print("Stack: ", string(debug.Stack())) - panic(fmt.Errorf("Panic at %d: %v", vm.pc, x)) + /* + if vm.prg != nil { + vm.prg.dumpCode(log.Printf) + } + log.Print("Stack: ", string(debug.Stack())) + panic(fmt.Errorf("Panic at %d: %v", vm.pc, x)) + */ + panic(x) } ex.stack = vm.captureStack(ex.stack, ctxOffset) } diff --git a/vendor/vendor.json b/vendor/vendor.json index 9da6231155..849133dcab 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -75,10 +75,10 @@ "revisionTime": "2018-06-25T18:44:42Z" }, { - "checksumSHA1": "h5A0DLu0ZXvpW1F0Lh2oNOlKWf0=", + "checksumSHA1": "2oeluLsV3EQS1b0kjmgLc/i2d7E=", "path": "github.com/dop251/goja", - "revision": "cc13d3ec34f7c6e4e73dddbfe0a7e868cd3b5c93", - "revisionTime": "2019-06-21T10:59:25Z" + "revision": "aa89e6a4c7339be720f99bae0a56a8f6055b5b3e", + "revisionTime": "2019-09-12T22:33:29Z" }, { "checksumSHA1": "zYnPsNAVm1/ViwCkN++dX2JQhBo=",