Skip to content

Commit

Permalink
Merge pull request #94 from Bit-Nation/feature/duktape_migration
Browse files Browse the repository at this point in the history
Feature/duktape migration
  • Loading branch information
florianlenz authored Sep 5, 2018
2 parents dd3bb53 + a713071 commit d886554
Show file tree
Hide file tree
Showing 28 changed files with 922 additions and 883 deletions.
24 changes: 11 additions & 13 deletions dapp/dapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (
storm "github.com/asdine/storm"
log "github.com/ipfs/go-log"
logger "github.com/op/go-logging"
otto "github.com/robertkrimen/otto"
duktape "gopkg.in/olebedev/go-duktape.v3"
)

var sysLog = log.Logger("dapp")

type DApp struct {
vm *otto.Otto
vm *duktape.Context
logger *logger.Logger
app *Data
// will be called when the app shut down
Expand All @@ -34,15 +34,14 @@ type DApp struct {

// close DApp
func (d *DApp) Close() {
d.vm.Interrupt <- func() {
d.logger.Info(fmt.Sprintf("shutting down: %s (%s)", hex.EncodeToString(d.app.UsedSigningKey), d.app.Name))
for _, mod := range d.vmModules {
if err := mod.Close(); err != nil {
sysLog.Error(err)
}
defer d.vm.DestroyHeap()
d.logger.Info(fmt.Sprintf("shutting down: %s (%s)", hex.EncodeToString(d.app.UsedSigningKey), d.app.Name))
for _, mod := range d.vmModules {
if err := mod.Close(); err != nil {
sysLog.Error(err)
}
d.closeChan <- d.app
}
d.closeChan <- d.app
}

func (d *DApp) ID() string {
Expand Down Expand Up @@ -74,8 +73,7 @@ func New(l *logger.Logger, app *Data, vmModules []module.Module, closer chan<- *
}

// create VM
vm := otto.New()
vm.Interrupt = make(chan func(), 1)
vm := duktape.New()

// register all vm modules
for _, m := range vmModules {
Expand Down Expand Up @@ -132,7 +130,8 @@ func New(l *logger.Logger, app *Data, vmModules []module.Module, closer chan<- *

// start the DApp async
go func() {
_, err := vm.Run(app.Code)
// Synonymous to vm.Run in Otto
err := vm.PevalString(string(app.Code))
if err != nil {
l.Errorf(err.Error())
}
Expand All @@ -147,7 +146,6 @@ func New(l *logger.Logger, app *Data, vmModules []module.Module, closer chan<- *
}
return dApp, nil
case <-time.After(timeOut):
vm.Interrupt <- func() {}
closer <- app
return nil, errors.New("timeout - failed to start DApp")
}
Expand Down
2 changes: 1 addition & 1 deletion dapp/dapp_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func TestBoltDAppStorage_Get(t *testing.T) {
}

func createDB() *bolt.DB {
dbPath, err := filepath.Abs(os.TempDir() + "/" + time.Now().String())
dbPath, err := filepath.Abs(os.TempDir() + "/" + fmt.Sprint(time.Now().UnixNano()))
if err != nil {
panic(err)
}
Expand Down
104 changes: 53 additions & 51 deletions dapp/module/callbacks/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
validator "github.com/Bit-Nation/panthalassa/dapp/validator"
log "github.com/ipfs/go-log"
logger "github.com/op/go-logging"
otto "github.com/robertkrimen/otto"
duktape "gopkg.in/olebedev/go-duktape.v3"
)

var debugger = log.Logger("callbacks")
Expand All @@ -34,7 +34,7 @@ func New(l *logger.Logger) *Module {

var count uint

functions := map[uint]*otto.Value{}
functions := map[uint]*duktape.Context{}
cbChans := map[*chan error]bool{}

for {
Expand Down Expand Up @@ -110,7 +110,7 @@ func New(l *logger.Logger) *Module {
}

type addFunction struct {
fn *otto.Value
fn *duktape.Context
respChan chan struct {
id uint
error error
Expand All @@ -119,12 +119,12 @@ type addFunction struct {

type fetchFunction struct {
id uint
respChan chan *otto.Value
respChan chan *duktape.Context
}

type Module struct {
logger *logger.Logger
vm *otto.Otto
vm *duktape.Context
reqLim *reqLim.Count
addFunctionChan chan addFunction
fetchFunctionChan chan fetchFunction
Expand All @@ -146,37 +146,33 @@ func (m *Module) Close() error {
// e.g. myRegisteredFunction(payloadObj, cb)
// the callback must be called in order to "return" from the function
func (m *Module) CallFunction(id uint, payload string) error {

debugger.Debug(fmt.Errorf("call function with id: %d and payload: %s", id, payload))

respChan := make(chan *otto.Value)
respChan := make(chan *duktape.Context)
m.fetchFunctionChan <- fetchFunction{
id: id,
respChan: respChan,
}
fn := <-respChan
vm := <-respChan

if fn == nil {
if vm == nil || vm.GetType(0).IsNone() {
return errors.New(fmt.Sprintf("function with id: %d does not exist", id))
}

// check if function is registered
if !fn.IsFunction() {
if !vm.IsFunction(0) {
return errors.New(fmt.Sprintf("function with id: %d does not exist", id))
}

// parse params
objArgs, err := m.vm.Object("(" + payload + ")")
if err != nil {
return err
}
objArgs := "(" + payload + ")"

done := make(chan error, 1)
m.addCBChan <- &done

alreadyCalled := false

_, err = fn.Call(*fn, objArgs, func(call otto.FunctionCall) otto.Value {
_, err := vm.PushGlobalGoFunction("callbackCallFunction", func(context *duktape.Context) int {

defer func() {
m.rmCBChan <- &done
Expand All @@ -185,26 +181,43 @@ func (m *Module) CallFunction(id uint, payload string) error {
// check if callback has already been called
if alreadyCalled {
m.logger.Error("Already called callback")
return m.vm.MakeCustomError("Callback", "Already called callback")
if context.IsFunction(1) {
context.PushString("Callback: Already called callback")
context.Call(1)
}
return 1
}
alreadyCalled = true

// check parameters
err := call.Argument(0)

if !err.IsUndefined() {
done <- errors.New(err.String())
return otto.Value{}
if !context.IsUndefined(0) {
firstParameter := context.ToString(0)
if context.IsFunction(1) {
context.PushString(firstParameter)
context.Call(1)
}
done <- errors.New(firstParameter)
return 1
}

done <- nil
return otto.Value{}
return 0

})
if err != nil {
m.logger.Error(err.Error())
}

// Push objArgs to the stack as first parameter
err = vm.PevalString(objArgs)
if err != nil {
m.logger.Error(err.Error())
}
// Push callbackCallFunction to the stack as second parameter
err = vm.PevalString(`callbackCallFunction`)
if err != nil {
m.logger.Error(err.Error())
}
// Use 2 when calling as we just pushed 2 parameters to the stack
vm.Call(2)
return <-done

}
Expand All @@ -215,43 +228,37 @@ func (m *Module) CallFunction(id uint, payload string) error {
// a registered function will be called with an object containing information
// and a callback that should be called (with an optional error) in order to
// "return"
func (m *Module) Register(vm *otto.Otto) error {
func (m *Module) Register(vm *duktape.Context) error {
m.vm = vm
err := vm.Set("registerFunction", func(call otto.FunctionCall) otto.Value {
_, err := vm.PushGlobalGoFunction("registerFunction", func(context *duktape.Context) int {
// validate function call
v := validator.New()
v.Set(0, &validator.TypeFunction)
if err := v.Validate(vm, call); err != nil {
m.logger.Error(fmt.Sprintf(`registerFunction needs a callback as it's first param %s`, err.String()))
return *err
if err := v.Validate(context); err != nil {
m.logger.Error(fmt.Sprintf(`registerFunction needs a callback as it's first param %s`, err.Error()))
return 1
}

// callback
fn := call.Argument(0)

// add function to stack
idRespChan := make(chan struct {
id uint
error error
}, 1)
m.addFunctionChan <- addFunction{
respChan: idRespChan,
fn: &fn,
fn: context,
}
// response
addResp := <-idRespChan

// exit vm on error
if addResp.error != nil {
m.logger.Error(addResp.error.Error())
return otto.Value{}
return 1
}

// convert function id to otto value
functionId, err := otto.ToValue(addResp.id)
if err != nil {
m.logger.Error(err.Error())
}
// convert function id to int
functionId := int(addResp.id)

return functionId

Expand All @@ -260,27 +267,22 @@ func (m *Module) Register(vm *otto.Otto) error {
return err
}

return vm.Set("unRegisterFunction", func(call otto.FunctionCall) otto.Value {
_, err = vm.PushGlobalGoFunction("unRegisterFunction", func(context *duktape.Context) int {

// validate function call
v := validator.New()
v.Set(0, &validator.TypeNumber)
if err := v.Validate(vm, call); err != nil {
return *err
if err := v.Validate(context); err != nil {
return 1
}

// function id
funcID := call.Argument(0)
id, err := funcID.ToInteger()
if err != nil {
m.logger.Error(err.Error())
return otto.Value{}
}
funcID := context.ToInt(0)

// delete function from channel
m.deleteFunctionChan <- uint(id)
m.deleteFunctionChan <- uint(funcID)

return otto.Value{}
return 0
})

return err
}
Loading

0 comments on commit d886554

Please sign in to comment.