diff --git a/bridge.go b/bridge.go index d090e21..f114212 100644 --- a/bridge.go +++ b/bridge.go @@ -78,7 +78,7 @@ func BridgeFromFile(name, file string, imports *wasmer.Imports) (*Bridge, error) func (b *Bridge) addValues() { var goObj *object goObj = propObject("jsGo", map[string]interface{}{ - "_makeFuncWrapper": wasmFunc(func(args []interface{}) (interface{}, error) { + "_makeFuncWrapper": Func(func(args []interface{}) (interface{}, error) { return &funcWrapper{id: args[0]}, nil }), "_pendingEvent": nil, @@ -112,7 +112,7 @@ func (b *Bridge) addValues() { "O_EXCL": syscall.O_EXCL, }), - "write": wasmFunc(func(args []interface{}) (interface{}, error) { + "write": Func(func(args []interface{}) (interface{}, error) { fd := int(args[0].(float64)) offset := int(args[2].(float64)) length := int(args[3].(float64)) @@ -311,6 +311,11 @@ func (b *Bridge) storeValue(addr int32, v interface{}) { return } + rv := reflect.TypeOf(v) + if rv.Kind() == reflect.Ptr { + rv = rv.Elem() + } + ref, ok := b.refs[v] if !ok { ref = len(b.values) @@ -319,18 +324,15 @@ func (b *Bridge) storeValue(addr int32, v interface{}) { } typeFlag := 0 - rv := reflect.TypeOf(v) - if rv.Kind() == reflect.Ptr { - rv = rv.Elem() - } switch rv.Kind() { case reflect.String: typeFlag = 1 - case reflect.Struct, reflect.Slice: //TODO symbol maybe? + case reflect.Struct, reflect.Slice: typeFlag = 2 + case reflect.Func: + typeFlag = 3 default: panic(fmt.Sprintf("unknown type: %T", v)) - // TODO function } b.setUint32(addr+4, uint32(nanHead|typeFlag)) b.setUint32(addr, uint32(ref)) @@ -372,7 +374,7 @@ type buffer struct { data []byte } -type wasmFunc func(args []interface{}) (interface{}, error) +type Func func(args []interface{}) (interface{}, error) func (b *Bridge) resume() error { res := b.instance.Exports["resume"] @@ -402,11 +404,17 @@ func (b *Bridge) makeFuncWrapper(id, this interface{}, args *[]interface{}) (int } // TODO cheeck if the wasm is still running -func (b *Bridge) CallFunc(fn string, args *[]interface{}) (interface{}, error) { +func (b *Bridge) CallFunc(fn string, args []interface{}) (interface{}, error) { fw, ok := b.values[5].(*object).props[fn] if !ok { return nil, fmt.Errorf("missing function: %v", fn) } - return b.makeFuncWrapper(fw.(*funcWrapper).id, b.values[7], args) + return b.makeFuncWrapper(fw.(*funcWrapper).id, b.values[7], &args) +} + +// TODO check if wasm is still running +func (b *Bridge) SetFunc(fname string, fn Func) error { + b.values[5].(*object).props[fname] = &fn + return nil } diff --git a/imports.go b/imports.go index 81ace52..fae6ea1 100644 --- a/imports.go +++ b/imports.go @@ -157,7 +157,7 @@ func valueCall(ctx unsafe.Pointer, sp int32) { v := b.loadValue(sp + 8) str := b.loadString(sp + 16) args := b.loadSliceOfValues(sp + 32) - f, ok := v.(*object).props[str].(wasmFunc) + f, ok := v.(*object).props[str].(Func) if !ok { panic(fmt.Sprintln("valueCall: prop not found in ", v, str)) } @@ -176,7 +176,19 @@ func valueCall(ctx unsafe.Pointer, sp int32) { //export valueInvoke func valueInvoke(ctx unsafe.Pointer, sp int32) { - panic("valueInvoke") + b := getBridge(ctx) + val := *(b.loadValue(sp + 8).(*Func)) + args := b.loadSliceOfValues(sp + 16) + res, err := val(args) + sp = b.getSP() + if err != nil { + b.storeValue(sp+40, err) + b.setUint8(sp+48, 0) + return + } + + b.storeValue(sp+40, res) + b.setUint8(sp+48, 1) } //export valueNew diff --git a/simple/caller/main.go b/simple/caller/main.go index ef5c902..a785dcc 100644 --- a/simple/caller/main.go +++ b/simple/caller/main.go @@ -7,12 +7,24 @@ import ( wasmgo "github.com/vedhavyas/wasm" ) +func proxy(b *wasmgo.Bridge) wasmgo.Func { + return func(args []interface{}) (i interface{}, e error) { + fmt.Println("In Go", args) + return b.CallFunc("addition", args) + } +} + func main() { b, err := wasmgo.BridgeFromFile("test", "./simple/prog/main.wasm", nil) if err != nil { log.Fatal(err) } + err = b.SetFunc("proxy", proxy(b)) + if err != nil { + panic(err) + } + init, done := make(chan error), make(chan bool) go b.Run(init, done) err = <-init @@ -20,8 +32,6 @@ func main() { panic(err) } - res, err := b.CallFunc("printWasm", &[]interface{}{"Hello from Go"}) - fmt.Println(res, err) <-done fmt.Println("wasm exited", err) } diff --git a/simple/prog/main.go b/simple/prog/main.go index 04fba53..1aa46cd 100644 --- a/simple/prog/main.go +++ b/simple/prog/main.go @@ -8,17 +8,22 @@ import ( ) // TODO: log seems to cause an issue -func printWasm(this js.Value, v []js.Value) interface{} { - fmt.Println(v[0].String()) - return "Hello from WASM" +func addition(this js.Value, args []js.Value) interface{} { + fmt.Println("In WASM", args) + this.Set() + this.SetIndex() + a, b := args[0].Int(), args[1].Int() + return a + b } func main() { ch := make(chan bool) - fmt.Println("WASM-Go Initialized") // register functions - fun := js.FuncOf(printWasm) - js.Global().Set("printWasm", fun) + fun := js.FuncOf(addition) + js.Global().Set("addition", fun) + + res := js.Global().Get("proxy").Invoke(1, 2) + fmt.Printf("1 + 2 = %d\n", res.Int()) <-ch } diff --git a/simple/prog/main.wasm b/simple/prog/main.wasm index e244d4b..e04124f 100755 Binary files a/simple/prog/main.wasm and b/simple/prog/main.wasm differ