@@ -28,12 +28,12 @@ import (
2828 "strings"
2929 "syscall"
3030
31+ "github.com/dop251/goja"
3132 "github.com/ethereum/go-ethereum/internal/jsre"
3233 "github.com/ethereum/go-ethereum/internal/web3ext"
3334 "github.com/ethereum/go-ethereum/rpc"
3435 "github.com/mattn/go-colorable"
3536 "github.com/peterh/liner"
36- "github.com/robertkrimen/otto"
3737)
3838
3939var (
@@ -64,13 +64,14 @@ type Config struct {
6464// JavaScript console attached to a running node via an external or in-process RPC
6565// client.
6666type Console struct {
67- client * rpc.Client // RPC client to execute Ethereum requests through
68- jsre * jsre.JSRE // JavaScript runtime environment running the interpreter
69- prompt string // Input prompt prefix string
70- prompter UserPrompter // Input prompter to allow interactive user feedback
71- histPath string // Absolute path to the console scrollback history
72- history []string // Scroll history maintained by the console
73- printer io.Writer // Output writer to serialize any display strings to
67+ client * rpc.Client // RPC client to execute Ethereum requests through
68+ jsre * jsre.JSRE // JavaScript runtime environment running the interpreter
69+ prompt string // Input prompt prefix string
70+ prompter UserPrompter // Input prompter to allow interactive user feedback
71+ histPath string // Absolute path to the console scrollback history
72+ history []string // Scroll history maintained by the console
73+ printer io.Writer // Output writer to serialize any display strings to
74+ runtime * goja.Runtime // The javascript runtime
7475}
7576
7677// New initializes a JavaScript interpreted runtime environment and sets defaults
@@ -86,10 +87,15 @@ func New(config Config) (*Console, error) {
8687 if config .Printer == nil {
8788 config .Printer = colorable .NewColorableStdout ()
8889 }
90+
91+ // Create the JS runtime
92+ runtime := goja .New ()
93+
8994 // Initialize the console and return
9095 console := & Console {
96+ runtime : runtime ,
9197 client : config .Client ,
92- jsre : jsre .New (config .DocRoot , config .Printer ),
98+ jsre : jsre .New (config .DocRoot , config .Printer , runtime ),
9399 prompt : config .Prompt ,
94100 prompter : config .Prompter ,
95101 printer : config .Printer ,
@@ -108,22 +114,31 @@ func New(config Config) (*Console, error) {
108114// the console's JavaScript namespaces based on the exposed modules.
109115func (c * Console ) init (preload []string ) error {
110116 // Initialize the JavaScript <-> Go RPC bridge
111- bridge := newBridge (c .client , c .prompter , c .printer )
112- c .jsre .Set ("jeth" , struct {}{})
117+ bridge := newBridge (c .client , c .prompter , c .printer , c .runtime )
118+ c .jsre .Run ("jeth = {};" )
119+ c .jsre .Run ("console = {};" )
113120
114- jethObj , _ := c .jsre .Get ("jeth" )
115- jethObj .Object ().Set ("send" , bridge .Send )
116- jethObj .Object ().Set ("sendAsync" , bridge .Send )
121+ jethObj := c .jsre .Get ("jeth" ).ToObject (c .runtime )
122+ if err := jethObj .Set ("send" , bridge .Send ); err != nil {
123+ panic (err )
124+ }
125+ if err := jethObj .Set ("sendAsync" , bridge .Send ); err != nil {
126+ panic (err )
127+ }
117128
118- consoleObj , _ := c .jsre .Get ("console" )
119- consoleObj .Object ().Set ("log" , c .consoleOutput )
120- consoleObj .Object ().Set ("error" , c .consoleOutput )
129+ consoleObj := c .runtime .Get ("console" ).ToObject (c .runtime )
130+ if err := consoleObj .Set ("log" , c .consoleOutput ); err != nil {
131+ panic (err )
132+ }
133+ if err := consoleObj .Set ("error" , c .consoleOutput ); err != nil {
134+ panic (err )
135+ }
121136
122137 // Load all the internal utility JavaScript libraries
123- if err := c .jsre .Compile ("bignumber.js" , jsre .BignumberJs ); err != nil {
138+ if err := c .jsre .Compile ("bignumber.js" , string ( jsre .BignumberJs ) ); err != nil {
124139 return fmt .Errorf ("bignumber.js: %v" , err )
125140 }
126- if err := c .jsre .Compile ("web3.js" , jsre .Web3Js ); err != nil {
141+ if err := c .jsre .Compile ("web3.js" , string ( jsre .Web3Js ) ); err != nil {
127142 return fmt .Errorf ("web3.js: %v" , err )
128143 }
129144 if _ , err := c .jsre .Run ("var Web3 = require('web3');" ); err != nil {
@@ -148,7 +163,7 @@ func (c *Console) init(preload []string) error {
148163 return fmt .Errorf ("%s.js: %v" , api , err )
149164 }
150165 flatten += fmt .Sprintf ("var %s = web3.%s; " , api , api )
151- } else if obj , err := c .jsre .Run ("web3." + api ); err == nil && obj .IsObject () {
166+ } else if obj , err := c .jsre .Run ("web3." + api ); err == nil && obj .ToObject ( c . runtime ) != nil {
152167 // Enable web3.js built-in extension if available.
153168 flatten += fmt .Sprintf ("var %s = web3.%s; " , api , api )
154169 }
@@ -162,16 +177,16 @@ func (c *Console) init(preload []string) error {
162177 // If the console is in interactive mode, instrument password related methods to query the user
163178 if c .prompter != nil {
164179 // Retrieve the account management object to instrument
165- personal , err := c .jsre .Get ("personal" )
166- if err ! = nil {
167- return err
180+ personal := c .jsre .Get ("personal" )
181+ if personal = = nil {
182+ return fmt . Errorf ( "Could not find personal" )
168183 }
169184 // Override the openWallet, unlockAccount, newAccount and sign methods since
170185 // these require user interaction. Assign these method in the Console the
171186 // original web3 callbacks. These will be called by the jeth.* methods after
172187 // they got the password from the user and send the original web3 request to
173188 // the backend.
174- if obj := personal .Object ( ); obj != nil { // make sure the personal api is enabled over the interface
189+ if obj := personal .ToObject ( c . runtime ); obj != nil { // make sure the personal api is enabled over the interface
175190 if _ , err = c .jsre .Run (`jeth.openWallet = personal.openWallet;` ); err != nil {
176191 return fmt .Errorf ("personal.openWallet: %v" , err )
177192 }
@@ -191,11 +206,11 @@ func (c *Console) init(preload []string) error {
191206 }
192207 }
193208 // The admin.sleep and admin.sleepBlocks are offered by the console and not by the RPC layer.
194- admin , err := c .jsre .Get ("admin" )
195- if err ! = nil {
196- return err
209+ admin := c .jsre .Get ("admin" )
210+ if admin = = nil {
211+ return fmt . Errorf ( "Could not find admin" )
197212 }
198- if obj := admin .Object ( ); obj != nil { // make sure the admin api is enabled over the interface
213+ if obj := admin .ToObject ( c . runtime ); obj != nil { // make sure the admin api is enabled over the interface
199214 obj .Set ("sleepBlocks" , bridge .SleepBlocks )
200215 obj .Set ("sleep" , bridge .Sleep )
201216 obj .Set ("clearHistory" , c .clearHistory )
@@ -204,8 +219,8 @@ func (c *Console) init(preload []string) error {
204219 for _ , path := range preload {
205220 if err := c .jsre .Exec (path ); err != nil {
206221 failure := err .Error ()
207- if ottoErr , ok := err .(* otto. Error ); ok {
208- failure = ottoErr .String ()
222+ if gojaErr , ok := err .(* goja. Exception ); ok {
223+ failure = gojaErr .String ()
209224 }
210225 return fmt .Errorf ("%s: %v" , path , failure )
211226 }
@@ -235,13 +250,13 @@ func (c *Console) clearHistory() {
235250
236251// consoleOutput is an override for the console.log and console.error methods to
237252// stream the output into the configured output stream instead of stdout.
238- func (c * Console ) consoleOutput (call otto .FunctionCall ) otto .Value {
253+ func (c * Console ) consoleOutput (call goja .FunctionCall ) goja .Value {
239254 var output []string
240- for _ , argument := range call .ArgumentList {
255+ for _ , argument := range call .Arguments {
241256 output = append (output , fmt .Sprintf ("%v" , argument ))
242257 }
243258 fmt .Fprintln (c .printer , strings .Join (output , " " ))
244- return otto. Value {}
259+ return goja . Null ()
245260}
246261
247262// AutoCompleteInput is a pre-assembled word completer to be used by the user
0 commit comments