This repository has been archived by the owner on Dec 21, 2022. It is now read-only.
/
WebSocket.ts
105 lines (91 loc) 路 2.57 KB
/
WebSocket.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { ScriptingTransport } from '../json-rpc/types'
export interface IWebSocketEventMap {
close: any
error: any
message: { data: any }
open: any
}
/**
* This interface should be compatible with the Browsers interface
* and npm ws package for servers
*/
export interface IWebSocket {
CONNECTING: number
OPEN: number
CLOSING: number
CLOSED: number
readyState: number
close(code?: number, data?: string): void
send(data: any, cb?: (err: Error) => void): void
send(data: any, options: any, cb?: (err: Error) => void): void
terminate?(): void
addEventListener<K extends keyof IWebSocketEventMap>(
type: K,
listener: (ev: IWebSocketEventMap[K]) => any,
options?: any
): void
}
export function WebSocketTransport(socket: IWebSocket): ScriptingTransport {
const queue: (string | Uint8Array | ArrayBuffer | SharedArrayBuffer)[] = []
socket.addEventListener('open', function() {
flush()
})
function flush() {
if (socket.readyState === socket.OPEN) {
queue.forEach($ => send($))
queue.length = 0
}
}
function send(msg: string | Uint8Array | ArrayBuffer | SharedArrayBuffer) {
if (typeof msg === 'string') {
socket.send(msg, { binary: false })
} else if (msg instanceof Uint8Array || msg instanceof ArrayBuffer || msg instanceof SharedArrayBuffer) {
// tslint:disable-next-line:semicolon
;(socket as any).binaryType = 'arraybuffer'
socket.send(msg, { binary: true })
}
}
const api: ScriptingTransport = {
onConnect(handler) {
if (socket.readyState === socket.OPEN) {
handler()
} else {
socket.addEventListener('open', () => handler(), { once: true })
}
},
onError(handler) {
socket.addEventListener('error', (err: ErrorEvent) => {
if (err.error) {
handler(err.error)
} else if (err.message) {
handler(
Object.assign(new Error(err.message), {
colno: err.colno,
error: err.error,
filename: err.filename,
lineno: err.lineno,
message: err.message
})
)
}
})
},
onMessage(handler) {
socket.addEventListener('message', (message: { data: any }) => {
handler(message.data)
})
},
sendMessage(message: any) {
const toSend = message instanceof Uint8Array ? message.buffer : message
if (socket.readyState === socket.OPEN) {
send(toSend)
} else {
queue.push(toSend)
}
},
close() {
socket.close()
}
}
return api
}