source: code/trunk/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 4.0 KB
Line 
1// +build js
2
3// Package wsjs implements typed access to the browser javascript WebSocket API.
4//
5// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
6package wsjs
7
8import (
9 "syscall/js"
10)
11
12func handleJSError(err *error, onErr func()) {
13 r := recover()
14
15 if jsErr, ok := r.(js.Error); ok {
16 *err = jsErr
17
18 if onErr != nil {
19 onErr()
20 }
21 return
22 }
23
24 if r != nil {
25 panic(r)
26 }
27}
28
29// New is a wrapper around the javascript WebSocket constructor.
30func New(url string, protocols []string) (c WebSocket, err error) {
31 defer handleJSError(&err, func() {
32 c = WebSocket{}
33 })
34
35 jsProtocols := make([]interface{}, len(protocols))
36 for i, p := range protocols {
37 jsProtocols[i] = p
38 }
39
40 c = WebSocket{
41 v: js.Global().Get("WebSocket").New(url, jsProtocols),
42 }
43
44 c.setBinaryType("arraybuffer")
45
46 return c, nil
47}
48
49// WebSocket is a wrapper around a javascript WebSocket object.
50type WebSocket struct {
51 v js.Value
52}
53
54func (c WebSocket) setBinaryType(typ string) {
55 c.v.Set("binaryType", string(typ))
56}
57
58func (c WebSocket) addEventListener(eventType string, fn func(e js.Value)) func() {
59 f := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
60 fn(args[0])
61 return nil
62 })
63 c.v.Call("addEventListener", eventType, f)
64
65 return func() {
66 c.v.Call("removeEventListener", eventType, f)
67 f.Release()
68 }
69}
70
71// CloseEvent is the type passed to a WebSocket close handler.
72type CloseEvent struct {
73 Code uint16
74 Reason string
75 WasClean bool
76}
77
78// OnClose registers a function to be called when the WebSocket is closed.
79func (c WebSocket) OnClose(fn func(CloseEvent)) (remove func()) {
80 return c.addEventListener("close", func(e js.Value) {
81 ce := CloseEvent{
82 Code: uint16(e.Get("code").Int()),
83 Reason: e.Get("reason").String(),
84 WasClean: e.Get("wasClean").Bool(),
85 }
86 fn(ce)
87 })
88}
89
90// OnError registers a function to be called when there is an error
91// with the WebSocket.
92func (c WebSocket) OnError(fn func(e js.Value)) (remove func()) {
93 return c.addEventListener("error", fn)
94}
95
96// MessageEvent is the type passed to a message handler.
97type MessageEvent struct {
98 // string or []byte.
99 Data interface{}
100
101 // There are more fields to the interface but we don't use them.
102 // See https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
103}
104
105// OnMessage registers a function to be called when the WebSocket receives a message.
106func (c WebSocket) OnMessage(fn func(m MessageEvent)) (remove func()) {
107 return c.addEventListener("message", func(e js.Value) {
108 var data interface{}
109
110 arrayBuffer := e.Get("data")
111 if arrayBuffer.Type() == js.TypeString {
112 data = arrayBuffer.String()
113 } else {
114 data = extractArrayBuffer(arrayBuffer)
115 }
116
117 me := MessageEvent{
118 Data: data,
119 }
120 fn(me)
121
122 return
123 })
124}
125
126// Subprotocol returns the WebSocket subprotocol in use.
127func (c WebSocket) Subprotocol() string {
128 return c.v.Get("protocol").String()
129}
130
131// OnOpen registers a function to be called when the WebSocket is opened.
132func (c WebSocket) OnOpen(fn func(e js.Value)) (remove func()) {
133 return c.addEventListener("open", fn)
134}
135
136// Close closes the WebSocket with the given code and reason.
137func (c WebSocket) Close(code int, reason string) (err error) {
138 defer handleJSError(&err, nil)
139 c.v.Call("close", code, reason)
140 return err
141}
142
143// SendText sends the given string as a text message
144// on the WebSocket.
145func (c WebSocket) SendText(v string) (err error) {
146 defer handleJSError(&err, nil)
147 c.v.Call("send", v)
148 return err
149}
150
151// SendBytes sends the given message as a binary message
152// on the WebSocket.
153func (c WebSocket) SendBytes(v []byte) (err error) {
154 defer handleJSError(&err, nil)
155 c.v.Call("send", uint8Array(v))
156 return err
157}
158
159func extractArrayBuffer(arrayBuffer js.Value) []byte {
160 uint8Array := js.Global().Get("Uint8Array").New(arrayBuffer)
161 dst := make([]byte, uint8Array.Length())
162 js.CopyBytesToGo(dst, uint8Array)
163 return dst
164}
165
166func uint8Array(src []byte) js.Value {
167 uint8Array := js.Global().Get("Uint8Array").New(len(src))
168 js.CopyBytesToJS(uint8Array, src)
169 return uint8Array
170}
Note: See TracBrowser for help on using the repository browser.