Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit afb088a

Browse files
committed
Start PoC work on WASM bridge for bus
Signed-off-by: Josh Kim <[email protected]>
1 parent 3c1a8f0 commit afb088a

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed

wasm/bus_bridge.go

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//go:build js && wasm
2+
3+
// Copyright 2021 VMware, Inc.
4+
// SPDX-License-Identifier: BSD-2-Clause
5+
6+
package wasm
7+
8+
import (
9+
"syscall/js"
10+
11+
"github.com/google/uuid"
12+
"github.com/vmware/transport-go/bus"
13+
"github.com/vmware/transport-go/model"
14+
)
15+
16+
type TransportWasmBridge struct {
17+
busRef bus.EventBus
18+
}
19+
20+
func NewTransportWasmBridge(busRef bus.EventBus) *TransportWasmBridge {
21+
return &TransportWasmBridge{
22+
busRef: busRef,
23+
}
24+
}
25+
26+
func (t *TransportWasmBridge) sendRequestMessageWrapper() js.Func {
27+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
28+
var destId *uuid.UUID
29+
channel := args[0].String()
30+
payload := args[1].JSValue()
31+
if len(args) > 2 {
32+
dId, err := uuid.Parse(args[2].String())
33+
if err != nil {
34+
errCtor := js.Global().Get("Error")
35+
js.Global().Get("console").Call("error", errCtor.New(err.Error()))
36+
return nil
37+
}
38+
destId = &dId
39+
}
40+
t.busRef.SendRequestMessage(channel, payload, destId)
41+
return nil
42+
})
43+
}
44+
45+
func (t *TransportWasmBridge) sendResponseMessageWrapper() js.Func {
46+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
47+
var destId *uuid.UUID
48+
channel := args[0].String()
49+
payload := args[1].JSValue()
50+
if len(args) > 2 {
51+
dId, err := uuid.Parse(args[2].String())
52+
if err != nil {
53+
errCtor := js.Global().Get("Error")
54+
js.Global().Get("console").Call("error", errCtor.New(err.Error()))
55+
return nil
56+
}
57+
destId = &dId
58+
}
59+
t.busRef.SendResponseMessage(channel, payload, destId)
60+
return nil
61+
})
62+
}
63+
64+
func (t *TransportWasmBridge) listenStreamWrapper() js.Func {
65+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
66+
handler, err := t.busRef.ListenStream(args[0].String())
67+
if err != nil {
68+
errCtor := js.Global().Get("Error")
69+
return errCtor.New(err.Error())
70+
}
71+
72+
return map[string]interface{}{
73+
"handle": getResponseHandlerJsCallbackFunc(handler),
74+
"close": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
75+
handler.Close()
76+
return nil
77+
}),
78+
}
79+
})
80+
}
81+
82+
func (t *TransportWasmBridge) listenStreamWithIdWrapper() js.Func {
83+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
84+
if len(args) <= 1 {
85+
errCtor := js.Global().Get("Error")
86+
js.Global().Get("console").Call("error", errCtor.New("cannot listen to channel. missing destination ID"))
87+
return nil
88+
}
89+
90+
destId, err := uuid.Parse(args[1].String())
91+
if err != nil {
92+
errCtor := js.Global().Get("Error")
93+
return errCtor.New(err.Error())
94+
}
95+
96+
handler, err := t.busRef.ListenStreamForDestination(args[0].String(), &destId)
97+
if err != nil {
98+
errCtor := js.Global().Get("Error")
99+
return errCtor.New(err.Error())
100+
}
101+
102+
return map[string]interface{}{
103+
"handle": getResponseHandlerJsCallbackFunc(handler),
104+
"close": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
105+
handler.Close()
106+
return nil
107+
}),
108+
}
109+
})
110+
}
111+
112+
func (t *TransportWasmBridge) browserBusWrapper() js.Func {
113+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
114+
b := js.Global().Get("AppEventBus")
115+
if b.Type() == js.TypeUndefined || b.Type() == js.TypeNull {
116+
errCtor := js.Global().Get("Error")
117+
return errCtor.New("bus not initialized")
118+
}
119+
return b
120+
})
121+
}
122+
123+
func (t *TransportWasmBridge) SetUpTransportWasmAPI() {
124+
js.Global().Set("goBusInterface", map[string]interface{}{
125+
"sendRequestMessage": t.sendRequestMessageWrapper(),
126+
"sendRequestMessageWithId": t.sendRequestMessageWrapper(),
127+
"sendResponseMessage": t.sendResponseMessageWrapper(),
128+
"sendResponseMessageWithId": t.sendResponseMessageWrapper(),
129+
"listenStream": t.listenStreamWrapper(),
130+
"listenStreamWithId": t.listenStreamWithIdWrapper(),
131+
"getBrowserBus": t.browserBusWrapper(),
132+
})
133+
134+
js.Global().Get("console").Call("log", "Transport WASM bridge set up. APIs are exposed at window.goBusInterface")
135+
}
136+
137+
func getResponseHandlerJsCallbackFunc(handler bus.MessageHandler) js.Func {
138+
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
139+
handler.Handle(func(m *model.Message) {
140+
jsCallback := args[0]
141+
if jsCallback.Type() != js.TypeFunction {
142+
errCtor := js.Global().Get("Error")
143+
js.Global().Get("console").Call("error", errCtor.New("invalid argument. not a function."))
144+
handler.Close()
145+
return
146+
}
147+
jsCallback.Invoke(m.Payload)
148+
}, func(e error) {
149+
errCtor := js.Global().Get("Error")
150+
js.Global().Get("console").Call("error", errCtor.New(e.Error()))
151+
handler.Close()
152+
})
153+
return nil
154+
})
155+
}

wasm/example/build.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package example
2+
3+
//go:generate bash -c "GOARCH=wasm; GOOS=js; go build -o ${OUT_DIR}main.wasm main.go"

wasm/example/main.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//go:build js && wasm
2+
3+
// Copyright 2021 VMware, Inc.
4+
// SPDX-License-Identifier: BSD-2-Clause
5+
6+
package main
7+
8+
import (
9+
"fmt"
10+
"time"
11+
12+
"github.com/vmware/transport-go/bus"
13+
"github.com/vmware/transport-go/wasm"
14+
)
15+
16+
func init() {
17+
b := bus.GetBus()
18+
cm := b.GetChannelManager()
19+
cm.CreateChannel("goBusChan")
20+
cm.CreateChannel("broadcast")
21+
22+
ticker := time.NewTicker(1 * time.Second)
23+
go func() {
24+
for {
25+
select {
26+
case <-ticker.C:
27+
b.SendResponseMessage("goBusChan", "sending", b.GetId())
28+
b.SendResponseMessage("broadcast", "hello world", nil)
29+
}
30+
}
31+
}()
32+
}
33+
34+
func main() {
35+
twa := wasm.NewTransportWasmBridge(bus.GetBus())
36+
twa.SetUpTransportWasmAPI()
37+
38+
fmt.Println("go bus id: ", bus.GetBus().GetId())
39+
40+
loop := make(chan struct{})
41+
<-loop
42+
}

0 commit comments

Comments
 (0)