Commit e221a449 authored by Felix Lange's avatar Felix Lange

cmd/geth, jsre, rpc: run all JS code on the event loop

Some JSRE methods (PrettyPrint, ToVal) bypassed the event loop. All
calls to the JS VM are now wrapped. In order to make this somewhat more
foolproof, the otto VM is now a local variable inside the event loop.
parent 394826f5
...@@ -144,7 +144,8 @@ func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value { ...@@ -144,7 +144,8 @@ func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
} }
} }
return js.re.ToVal(ltxs) v, _ := call.Otto.ToValue(ltxs)
return v
} }
func (js *jsre) resend(call otto.FunctionCall) otto.Value { func (js *jsre) resend(call otto.FunctionCall) otto.Value {
...@@ -175,7 +176,8 @@ func (js *jsre) resend(call otto.FunctionCall) otto.Value { ...@@ -175,7 +176,8 @@ func (js *jsre) resend(call otto.FunctionCall) otto.Value {
} }
js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx}) js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
return js.re.ToVal(ret) v, _ := call.Otto.ToValue(ret)
return v
} }
fmt.Println("first argument must be a transaction") fmt.Println("first argument must be a transaction")
...@@ -198,12 +200,13 @@ func (js *jsre) sign(call otto.FunctionCall) otto.Value { ...@@ -198,12 +200,13 @@ func (js *jsre) sign(call otto.FunctionCall) otto.Value {
fmt.Println(err) fmt.Println(err)
return otto.UndefinedValue() return otto.UndefinedValue()
} }
v, err := js.xeth.Sign(signer, data, false) signed, err := js.xeth.Sign(signer, data, false)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return otto.UndefinedValue() return otto.UndefinedValue()
} }
return js.re.ToVal(v) v, _ := call.Otto.ToValue(signed)
return v
} }
func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value { func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
...@@ -237,8 +240,8 @@ func (js *jsre) setHead(call otto.FunctionCall) otto.Value { ...@@ -237,8 +240,8 @@ func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value { func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value {
current, max := js.ethereum.Downloader().Stats() current, max := js.ethereum.Downloader().Stats()
v, _ := call.Otto.ToValue(fmt.Sprintf("%d/%d", current, max))
return js.re.ToVal(fmt.Sprintf("%d/%d", current, max)) return v
} }
func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value { func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
...@@ -248,7 +251,8 @@ func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value { ...@@ -248,7 +251,8 @@ func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() return otto.UndefinedValue()
} }
encoded, _ := rlp.EncodeToBytes(block) encoded, _ := rlp.EncodeToBytes(block)
return js.re.ToVal(fmt.Sprintf("%x", encoded)) v, _ := call.Otto.ToValue(fmt.Sprintf("%x", encoded))
return v
} }
func (js *jsre) setExtra(call otto.FunctionCall) otto.Value { func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
...@@ -278,8 +282,9 @@ func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value { ...@@ -278,8 +282,9 @@ func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() return otto.UndefinedValue()
} }
func (js *jsre) hashrate(otto.FunctionCall) otto.Value { func (js *jsre) hashrate(call otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.Miner().HashRate()) v, _ := call.Otto.ToValue(js.ethereum.Miner().HashRate())
return v
} }
func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value { func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value {
...@@ -495,15 +500,18 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value { ...@@ -495,15 +500,18 @@ func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
fmt.Printf("Could not create the account: %v", err) fmt.Printf("Could not create the account: %v", err)
return otto.UndefinedValue() return otto.UndefinedValue()
} }
return js.re.ToVal(acct.Address.Hex()) v, _ := call.Otto.ToValue(acct.Address.Hex())
return v
} }
func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value { func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.NodeInfo()) v, _ := call.Otto.ToValue(js.ethereum.NodeInfo())
return v
} }
func (js *jsre) peers(call otto.FunctionCall) otto.Value { func (js *jsre) peers(call otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.PeersInfo()) v, _ := call.Otto.ToValue(js.ethereum.PeersInfo())
return v
} }
func (js *jsre) importChain(call otto.FunctionCall) otto.Value { func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
...@@ -562,7 +570,8 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value { ...@@ -562,7 +570,8 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
statedb := state.New(block.Root(), js.ethereum.StateDb()) statedb := state.New(block.Root(), js.ethereum.StateDb())
dump := statedb.RawDump() dump := statedb.RawDump()
return js.re.ToVal(dump) v, _ := call.Otto.ToValue(dump)
return v
} }
func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value { func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
...@@ -611,7 +620,8 @@ func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value { ...@@ -611,7 +620,8 @@ func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() return otto.UndefinedValue()
case height = <-wait: case height = <-wait:
} }
return js.re.ToVal(height.Uint64()) v, _ := call.Otto.ToValue(height.Uint64())
return v
} }
func (js *jsre) sleep(call otto.FunctionCall) otto.Value { func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
...@@ -704,8 +714,8 @@ func (js *jsre) register(call otto.FunctionCall) otto.Value { ...@@ -704,8 +714,8 @@ func (js *jsre) register(call otto.FunctionCall) otto.Value {
return otto.UndefinedValue() return otto.UndefinedValue()
} }
return js.re.ToVal(contenthash.Hex()) v, _ := call.Otto.ToValue(contenthash.Hex())
return v
} }
func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value { func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
...@@ -764,7 +774,8 @@ func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value { ...@@ -764,7 +774,8 @@ func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
fmt.Println(err) fmt.Println(err)
return otto.UndefinedValue() return otto.UndefinedValue()
} }
return js.re.ToVal(info) v, _ := call.Otto.ToValue(info)
return v
} }
func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value { func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value {
......
...@@ -104,7 +104,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive boo ...@@ -104,7 +104,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive boo
func (js *jsre) apiBindings(f xeth.Frontend) { func (js *jsre) apiBindings(f xeth.Frontend) {
xe := xeth.New(js.ethereum, f) xe := xeth.New(js.ethereum, f)
ethApi := rpc.NewEthereumApi(xe) ethApi := rpc.NewEthereumApi(xe)
jeth := rpc.NewJeth(ethApi, js.re.ToVal, js.re) jeth := rpc.NewJeth(ethApi, js.re)
js.re.Set("jeth", struct{}{}) js.re.Set("jeth", struct{}{})
t, _ := js.re.Get("jeth") t, _ := js.re.Get("jeth")
......
This diff is collapsed.
package jsre package jsre
import ( import (
"github.com/robertkrimen/otto"
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/robertkrimen/otto"
) )
type testNativeObjectBinding struct { type testNativeObjectBinding struct{}
toVal func(interface{}) otto.Value
}
type msg struct { type msg struct {
Msg string Msg string
...@@ -21,7 +20,8 @@ func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value ...@@ -21,7 +20,8 @@ func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value
if err != nil { if err != nil {
return otto.UndefinedValue() return otto.UndefinedValue()
} }
return no.toVal(&msg{m}) v, _ := call.Otto.ToValue(&msg{m})
return v
} }
func TestExec(t *testing.T) { func TestExec(t *testing.T) {
...@@ -74,7 +74,7 @@ func TestNatto(t *testing.T) { ...@@ -74,7 +74,7 @@ func TestNatto(t *testing.T) {
func TestBind(t *testing.T) { func TestBind(t *testing.T) {
jsre := New("/tmp") jsre := New("/tmp")
jsre.Bind("no", &testNativeObjectBinding{jsre.ToVal}) jsre.Bind("no", &testNativeObjectBinding{})
val, err := jsre.Run(`no.TestMethod("testMsg")`) val, err := jsre.Run(`no.TestMethod("testMsg")`)
if err != nil { if err != nil {
......
...@@ -3,18 +3,18 @@ package rpc ...@@ -3,18 +3,18 @@ package rpc
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/jsre" "github.com/ethereum/go-ethereum/jsre"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )
type Jeth struct { type Jeth struct {
ethApi *EthereumApi ethApi *EthereumApi
toVal func(interface{}) otto.Value
re *jsre.JSRE re *jsre.JSRE
} }
func NewJeth(ethApi *EthereumApi, toVal func(interface{}) otto.Value, re *jsre.JSRE) *Jeth { func NewJeth(ethApi *EthereumApi, re *jsre.JSRE) *Jeth {
return &Jeth{ethApi, toVal, re} return &Jeth{ethApi, re}
} }
func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) { func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment