This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start PoC work on WASM bridge for bus
Signed-off-by: Josh Kim <[email protected]>
- Loading branch information
Showing
3 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
//go:build js && wasm | ||
|
||
// Copyright 2021 VMware, Inc. | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
|
||
package wasm | ||
|
||
import ( | ||
"syscall/js" | ||
|
||
"github.com/google/uuid" | ||
"github.com/vmware/transport-go/bus" | ||
"github.com/vmware/transport-go/model" | ||
) | ||
|
||
type TransportWasmBridge struct { | ||
busRef bus.EventBus | ||
} | ||
|
||
func NewTransportWasmBridge(busRef bus.EventBus) *TransportWasmBridge { | ||
return &TransportWasmBridge{ | ||
busRef: busRef, | ||
} | ||
} | ||
|
||
func (t *TransportWasmBridge) sendRequestMessageWrapper() js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
var destId *uuid.UUID | ||
channel := args[0].String() | ||
payload := args[1].JSValue() | ||
if len(args) > 2 { | ||
dId, err := uuid.Parse(args[2].String()) | ||
if err != nil { | ||
errCtor := js.Global().Get("Error") | ||
js.Global().Get("console").Call("error", errCtor.New(err.Error())) | ||
return nil | ||
} | ||
destId = &dId | ||
} | ||
t.busRef.SendRequestMessage(channel, payload, destId) | ||
return nil | ||
}) | ||
} | ||
|
||
func (t *TransportWasmBridge) sendResponseMessageWrapper() js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
var destId *uuid.UUID | ||
channel := args[0].String() | ||
payload := args[1].JSValue() | ||
if len(args) > 2 { | ||
dId, err := uuid.Parse(args[2].String()) | ||
if err != nil { | ||
errCtor := js.Global().Get("Error") | ||
js.Global().Get("console").Call("error", errCtor.New(err.Error())) | ||
return nil | ||
} | ||
destId = &dId | ||
} | ||
t.busRef.SendResponseMessage(channel, payload, destId) | ||
return nil | ||
}) | ||
} | ||
|
||
func (t *TransportWasmBridge) listenStreamWrapper() js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
handler, err := t.busRef.ListenStream(args[0].String()) | ||
if err != nil { | ||
errCtor := js.Global().Get("Error") | ||
return errCtor.New(err.Error()) | ||
} | ||
|
||
return map[string]interface{}{ | ||
"handle": getResponseHandlerJsCallbackFunc(handler), | ||
"close": js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
handler.Close() | ||
return nil | ||
}), | ||
} | ||
}) | ||
} | ||
|
||
func (t *TransportWasmBridge) listenStreamWithIdWrapper() js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
if len(args) <= 1 { | ||
errCtor := js.Global().Get("Error") | ||
js.Global().Get("console").Call("error", errCtor.New("cannot listen to channel. missing destination ID")) | ||
return nil | ||
} | ||
|
||
destId, err := uuid.Parse(args[1].String()) | ||
if err != nil { | ||
errCtor := js.Global().Get("Error") | ||
return errCtor.New(err.Error()) | ||
} | ||
|
||
handler, err := t.busRef.ListenStreamForDestination(args[0].String(), &destId) | ||
if err != nil { | ||
errCtor := js.Global().Get("Error") | ||
return errCtor.New(err.Error()) | ||
} | ||
|
||
return map[string]interface{}{ | ||
"handle": getResponseHandlerJsCallbackFunc(handler), | ||
"close": js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
handler.Close() | ||
return nil | ||
}), | ||
} | ||
}) | ||
} | ||
|
||
func (t *TransportWasmBridge) browserBusWrapper() js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
b := js.Global().Get("AppEventBus") | ||
if b.Type() == js.TypeUndefined || b.Type() == js.TypeNull { | ||
errCtor := js.Global().Get("Error") | ||
return errCtor.New("bus not initialized") | ||
} | ||
return b | ||
}) | ||
} | ||
|
||
func (t *TransportWasmBridge) SetUpTransportWasmAPI() { | ||
js.Global().Set("goBusInterface", map[string]interface{}{ | ||
"sendRequestMessage": t.sendRequestMessageWrapper(), | ||
"sendRequestMessageWithId": t.sendRequestMessageWrapper(), | ||
"sendResponseMessage": t.sendResponseMessageWrapper(), | ||
"sendResponseMessageWithId": t.sendResponseMessageWrapper(), | ||
"listenStream": t.listenStreamWrapper(), | ||
"listenStreamWithId": t.listenStreamWithIdWrapper(), | ||
"getBrowserBus": t.browserBusWrapper(), | ||
}) | ||
|
||
js.Global().Get("console").Call("log", "Transport WASM bridge set up. APIs are exposed at window.goBusInterface") | ||
} | ||
|
||
func getResponseHandlerJsCallbackFunc(handler bus.MessageHandler) js.Func { | ||
return js.FuncOf(func(this js.Value, args []js.Value) interface{} { | ||
handler.Handle(func(m *model.Message) { | ||
jsCallback := args[0] | ||
if jsCallback.Type() != js.TypeFunction { | ||
errCtor := js.Global().Get("Error") | ||
js.Global().Get("console").Call("error", errCtor.New("invalid argument. not a function.")) | ||
handler.Close() | ||
return | ||
} | ||
jsCallback.Invoke(m.Payload) | ||
}, func(e error) { | ||
errCtor := js.Global().Get("Error") | ||
js.Global().Get("console").Call("error", errCtor.New(e.Error())) | ||
handler.Close() | ||
}) | ||
return nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package example | ||
|
||
//go:generate bash -c "GOARCH=wasm; GOOS=js; go build -o ${OUT_DIR}/main.wasm main.go" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
//go:build js && wasm | ||
|
||
// Copyright 2021 VMware, Inc. | ||
// SPDX-License-Identifier: BSD-2-Clause | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/vmware/transport-go/bus" | ||
"github.com/vmware/transport-go/wasm" | ||
) | ||
|
||
func init() { | ||
b := bus.GetBus() | ||
cm := b.GetChannelManager() | ||
cm.CreateChannel("goBusChan") | ||
cm.CreateChannel("broadcast") | ||
|
||
ticker := time.NewTicker(1 * time.Second) | ||
go func() { | ||
for { | ||
select { | ||
case <-ticker.C: | ||
b.SendResponseMessage("goBusChan", "sending", b.GetId()) | ||
b.SendResponseMessage("broadcast", "hello world", nil) | ||
} | ||
} | ||
}() | ||
} | ||
|
||
func main() { | ||
twa := wasm.NewTransportWasmBridge(bus.GetBus()) | ||
twa.SetUpTransportWasmAPI() | ||
|
||
fmt.Println("go bus id: ", bus.GetBus().GetId()) | ||
|
||
loop := make(chan struct{}) | ||
<-loop | ||
} |