mirror of https://github.com/status-im/op-geth.git
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
This commit is contained in:
parent
a6ca8fd268
commit
87ae0df476
|
@ -123,7 +123,7 @@ func (self *jsre) batch(statement string) {
|
||||||
err := self.re.EvalAndPrettyPrint(statement)
|
err := self.re.EvalAndPrettyPrint(statement)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("%v", jsErrorString(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.atexit != nil {
|
if self.atexit != nil {
|
||||||
|
@ -301,21 +301,19 @@ func (self *jsre) preloadJSFiles(ctx *cli.Context) error {
|
||||||
for _, file := range jsFiles {
|
for _, file := range jsFiles {
|
||||||
filename := common.AbsolutePath(assetPath, strings.TrimSpace(file))
|
filename := common.AbsolutePath(assetPath, strings.TrimSpace(file))
|
||||||
if err := self.re.Exec(filename); err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec executes the JS file with the given filename and stops the JSRE
|
// jsErrorString adds a backtrace to errors generated by otto.
|
||||||
func (self *jsre) exec(filename string) error {
|
func jsErrorString(err error) string {
|
||||||
if err := self.re.Exec(filename); err != nil {
|
if ottoErr, ok := err.(*otto.Error); ok {
|
||||||
self.re.Stop(false)
|
return ottoErr.String()
|
||||||
return fmt.Errorf("Javascript Error: %v", err)
|
|
||||||
}
|
}
|
||||||
self.re.Stop(true)
|
return err.Error()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *jsre) interactive() {
|
func (self *jsre) interactive() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -353,7 +354,7 @@ func console(ctx *cli.Context) {
|
||||||
// preload user defined JS files into the console
|
// preload user defined JS files into the console
|
||||||
err = repl.preloadJSFiles(ctx)
|
err = repl.preloadJSFiles(ctx)
|
||||||
if err != nil {
|
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
|
// 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
|
// Create and start the node based on the CLI flags
|
||||||
node := utils.MakeSystemNode(ClientIdentifier, nodeNameVersion, makeDefaultExtra(), ctx)
|
node := utils.MakeSystemNode(ClientIdentifier, nodeNameVersion, makeDefaultExtra(), ctx)
|
||||||
startNode(ctx, node)
|
startNode(ctx, node)
|
||||||
|
defer node.Stop()
|
||||||
|
|
||||||
// Attach to the newly started node and execute the given scripts
|
// Attach to the newly started node and execute the given scripts
|
||||||
client, err := node.Attach()
|
client, err := node.Attach()
|
||||||
|
@ -383,10 +385,24 @@ func execScripts(ctx *cli.Context) {
|
||||||
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
|
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
|
||||||
client, false)
|
client, false)
|
||||||
|
|
||||||
|
// Run all given files.
|
||||||
for _, file := range ctx.Args() {
|
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
|
// startNode boots up the system node and all registered protocols, after which
|
||||||
|
|
|
@ -235,7 +235,14 @@ func (self *JSRE) Exec(file string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue