MCPcopy
hub / github.com/netbirdio/netbird / NewJSInterface

Function NewJSInterface

client/wasm/internal/websocket/websocket.go:160–215  ·  view source on GitHub ↗

NewJSInterface creates a JavaScript object wrapping the WebSocket connection. It exposes: send(string|Uint8Array), close(), and callback properties onmessage, onclose, onerror. Callback properties may be set from the JS thread while the read loop goroutine reads them. In WASM this is safe because G

(conn *Conn)

Source from the content-addressed store, hash-verified

158// single thread, but the design would need synchronization on
159// multi-threaded runtimes.
160func NewJSInterface(conn *Conn) js.Value {
161 obj := js.Global().Get("Object").Call("create", js.Null())
162
163 sendFunc := js.FuncOf(func(_ js.Value, args []js.Value) any {
164 if len(args) < 1 {
165 log.Errorf("websocket send requires a data argument")
166 return js.ValueOf(false)
167 }
168
169 data := args[0]
170 switch data.Type() {
171 case js.TypeString:
172 if err := conn.WriteText([]byte(data.String())); err != nil {
173 log.Errorf("failed to send websocket text: %v", err)
174 return js.ValueOf(false)
175 }
176 default:
177 buf, err := jsToBytes(data)
178 if err != nil {
179 log.Errorf("failed to convert js value to bytes: %v", err)
180 return js.ValueOf(false)
181 }
182 if err := conn.WriteBinary(buf); err != nil {
183 log.Errorf("failed to send websocket binary: %v", err)
184 return js.ValueOf(false)
185 }
186 }
187 return js.ValueOf(true)
188 })
189 obj.Set("send", sendFunc)
190
191 closeFunc := js.FuncOf(func(_ js.Value, _ []js.Value) any {
192 if err := conn.Close(); err != nil {
193 log.Debugf("failed to close websocket: %v", err)
194 }
195 return js.Undefined()
196 })
197 obj.Set("close", closeFunc)
198
199 go func() {
200 defer func() {
201 if err := conn.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
202 log.Debugf("close websocket on readLoop exit: %v", err)
203 }
204 }()
205 readLoop(conn, obj)
206 // Undefining before Release turns post-close JS calls into TypeError
207 // instead of a silent "call to released function".
208 obj.Set("send", js.Undefined())
209 obj.Set("close", js.Undefined())
210 sendFunc.Release()
211 closeFunc.Release()
212 }()
213
214 return obj
215}
216
217func jsToBytes(data js.Value) ([]byte, error) {

Callers

nothing calls this directly

Calls 13

jsToBytesFunction · 0.85
ErrorfMethod · 0.80
WriteTextMethod · 0.80
WriteBinaryMethod · 0.80
readLoopFunction · 0.70
GetMethod · 0.65
TypeMethod · 0.65
StringMethod · 0.65
SetMethod · 0.65
CloseMethod · 0.65
DebugfMethod · 0.65
ReleaseMethod · 0.65

Tested by

no test coverage detected