aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2016-04-21 05:17:00 +0800
committerFelix Lange <fjl@twurst.com>2016-04-21 05:33:43 +0800
commit87ae0df476cf6b413795ee54207e8ec86e178dbc (patch)
tree0a3a42c72845507ce40ff8e6767188d9809fa361
parenta6ca8fd26884807c80b649bd2a0e780aa93ced22 (diff)
downloaddexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar.gz
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar.bz2
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar.lz
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar.xz
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.tar.zst
dexon-87ae0df476cf6b413795ee54207e8ec86e178dbc.zip
cmd/geth, jsre: improve the js command
geth js stopped the JS runtime after running the first input file and blocked for pending callbacks. This commit makes it process all files and enables quitting with Ctrl-C regardless of callbacks. Error reporting is also improved. If a script fails to load, the error is printed and includes the backtrace. package jsre now ensures that otto is aware of the filename, the backtrace will contain them. Before: $ geth js bad.js; echo "exit $?" ... log messages ... exit 0 After: $ geth js bad.js; echo "exit $?" ... log messages ... Fatal: JavaScript Error: Invalid number of input parameters at web3.js:3109:20 at web3.js:4917:15 at web3.js:4960:5 at web3.js:4984:23 at checkWork (bad.js:11:9) at bad.js:19:1 exit 1
-rw-r--r--cmd/geth/js.go16
-rw-r--r--cmd/geth/main.go22
-rw-r--r--jsre/jsre.go9
3 files changed, 34 insertions, 13 deletions
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 767b513c1..2b64303b2 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -123,7 +123,7 @@ func (self *jsre) batch(statement string) {
err := self.re.EvalAndPrettyPrint(statement)
if err != nil {
- fmt.Printf("error: %v", err)
+ fmt.Printf("%v", jsErrorString(err))
}
if self.atexit != nil {
@@ -301,21 +301,19 @@ func (self *jsre) preloadJSFiles(ctx *cli.Context) error {
for _, file := range jsFiles {
filename := common.AbsolutePath(assetPath, strings.TrimSpace(file))
if err := self.re.Exec(filename); err != nil {
- return fmt.Errorf("%s: %v", file, err)
+ return fmt.Errorf("%s: %v", file, jsErrorString(err))
}
}
}
return nil
}
-// exec executes the JS file with the given filename and stops the JSRE
-func (self *jsre) exec(filename string) error {
- if err := self.re.Exec(filename); err != nil {
- self.re.Stop(false)
- return fmt.Errorf("Javascript Error: %v", err)
+// jsErrorString adds a backtrace to errors generated by otto.
+func jsErrorString(err error) string {
+ if ottoErr, ok := err.(*otto.Error); ok {
+ return ottoErr.String()
}
- self.re.Stop(true)
- return nil
+ return err.Error()
}
func (self *jsre) interactive() {
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 512a5f183..4f3946200 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -21,6 +21,7 @@ import (
"fmt"
"io/ioutil"
"os"
+ "os/signal"
"path/filepath"
"runtime"
"strconv"
@@ -353,7 +354,7 @@ func console(ctx *cli.Context) {
// preload user defined JS files into the console
err = repl.preloadJSFiles(ctx)
if err != nil {
- utils.Fatalf("unable to preload JS file %v", err)
+ utils.Fatalf("%v", err)
}
// in case the exec flag holds a JS statement execute it and return
@@ -372,6 +373,7 @@ func execScripts(ctx *cli.Context) {
// Create and start the node based on the CLI flags
node := utils.MakeSystemNode(ClientIdentifier, nodeNameVersion, makeDefaultExtra(), ctx)
startNode(ctx, node)
+ defer node.Stop()
// Attach to the newly started node and execute the given scripts
client, err := node.Attach()
@@ -383,10 +385,24 @@ func execScripts(ctx *cli.Context) {
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
client, false)
+ // Run all given files.
for _, file := range ctx.Args() {
- repl.exec(file)
+ if err = repl.re.Exec(file); err != nil {
+ break
+ }
}
- node.Stop()
+ if err != nil {
+ utils.Fatalf("JavaScript Error: %v", jsErrorString(err))
+ }
+ // JS files loaded successfully.
+ // Wait for pending callbacks, but stop for Ctrl-C.
+ abort := make(chan os.Signal, 1)
+ signal.Notify(abort, os.Interrupt)
+ go func() {
+ <-abort
+ repl.re.Stop(false)
+ }()
+ repl.re.Stop(true)
}
// startNode boots up the system node and all registered protocols, after which
diff --git a/jsre/jsre.go b/jsre/jsre.go
index 7df022cb1..59730bc0d 100644
--- a/jsre/jsre.go
+++ b/jsre/jsre.go
@@ -235,7 +235,14 @@ func (self *JSRE) Exec(file string) error {
if err != nil {
return err
}
- self.Do(func(vm *otto.Otto) { _, err = vm.Run(code) })
+ var script *otto.Script
+ self.Do(func(vm *otto.Otto) {
+ script, err = vm.Compile(file, code)
+ if err != nil {
+ return
+ }
+ _, err = vm.Run(script)
+ })
return err
}