llonebot-dist 6.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. dist/default_config.json +68 -0
  2. dist/llonebot.js +48348 -0
  3. dist/llonebot.js.map +1 -0
  4. dist/node_modules/@borewit/text-codec/LICENSE.txt +9 -0
  5. dist/node_modules/@borewit/text-codec/README.md +76 -0
  6. dist/node_modules/@borewit/text-codec/lib/index.d.ts +8 -0
  7. dist/node_modules/@borewit/text-codec/lib/index.js +161 -0
  8. dist/node_modules/@borewit/text-codec/package.json +68 -0
  9. dist/node_modules/@minatojs/sql.js/LICENSE +44 -0
  10. dist/node_modules/@minatojs/sql.js/README.md +357 -0
  11. dist/node_modules/@minatojs/sql.js/dist/sql-wasm.d.ts +316 -0
  12. dist/node_modules/@minatojs/sql.js/dist/sql-wasm.js +225 -0
  13. dist/node_modules/@minatojs/sql.js/dist/sql-wasm.wasm +0 -0
  14. dist/node_modules/@minatojs/sql.js/package.json +58 -0
  15. dist/node_modules/@tokenizer/inflate/LICENSE +15 -0
  16. dist/node_modules/@tokenizer/inflate/README.md +114 -0
  17. dist/node_modules/@tokenizer/inflate/lib/GzipHandler.d.ts +6 -0
  18. dist/node_modules/@tokenizer/inflate/lib/GzipHandler.js +19 -0
  19. dist/node_modules/@tokenizer/inflate/lib/ZipHandler.d.ts +26 -0
  20. dist/node_modules/@tokenizer/inflate/lib/ZipHandler.js +233 -0
  21. dist/node_modules/@tokenizer/inflate/lib/ZipToken.d.ts +94 -0
  22. dist/node_modules/@tokenizer/inflate/lib/ZipToken.js +117 -0
  23. dist/node_modules/@tokenizer/inflate/lib/index.d.ts +3 -0
  24. dist/node_modules/@tokenizer/inflate/lib/index.js +2 -0
  25. dist/node_modules/@tokenizer/inflate/package.json +76 -0
  26. dist/node_modules/@tokenizer/token/README.md +19 -0
  27. dist/node_modules/@tokenizer/token/index.d.ts +30 -0
  28. dist/node_modules/@tokenizer/token/package.json +33 -0
  29. dist/node_modules/debug/LICENSE +20 -0
  30. dist/node_modules/debug/README.md +481 -0
  31. dist/node_modules/debug/package.json +64 -0
  32. dist/node_modules/debug/src/browser.js +272 -0
  33. dist/node_modules/debug/src/common.js +292 -0
  34. dist/node_modules/debug/src/index.js +10 -0
  35. dist/node_modules/debug/src/node.js +263 -0
  36. dist/node_modules/file-type/core.d.ts +253 -0
  37. dist/node_modules/file-type/core.js +1899 -0
  38. dist/node_modules/file-type/index.d.ts +98 -0
  39. dist/node_modules/file-type/index.js +86 -0
  40. dist/node_modules/file-type/license +9 -0
  41. dist/node_modules/file-type/package.json +288 -0
  42. dist/node_modules/file-type/readme.md +674 -0
  43. dist/node_modules/file-type/supported.js +356 -0
  44. dist/node_modules/file-type/util.js +60 -0
  45. dist/node_modules/ieee754/LICENSE +11 -0
  46. dist/node_modules/ieee754/README.md +51 -0
  47. dist/node_modules/ieee754/index.d.ts +10 -0
  48. dist/node_modules/ieee754/index.js +85 -0
  49. dist/node_modules/ieee754/package.json +52 -0
  50. dist/node_modules/ms/index.js +162 -0
  51. dist/node_modules/ms/license.md +21 -0
  52. dist/node_modules/ms/package.json +38 -0
  53. dist/node_modules/ms/readme.md +59 -0
  54. dist/node_modules/silk-wasm/LICENSE +21 -0
  55. dist/node_modules/silk-wasm/README.md +85 -0
  56. dist/node_modules/silk-wasm/lib/index.cjs +16 -0
  57. dist/node_modules/silk-wasm/lib/index.d.ts +70 -0
  58. dist/node_modules/silk-wasm/lib/index.mjs +16 -0
  59. dist/node_modules/silk-wasm/lib/silk.wasm +0 -0
  60. dist/node_modules/silk-wasm/lib/utils.d.ts +4 -0
  61. dist/node_modules/silk-wasm/package.json +39 -0
  62. dist/node_modules/strtok3/LICENSE.txt +21 -0
  63. dist/node_modules/strtok3/README.md +399 -0
  64. dist/node_modules/strtok3/lib/AbstractTokenizer.d.ts +76 -0
  65. dist/node_modules/strtok3/lib/AbstractTokenizer.js +108 -0
  66. dist/node_modules/strtok3/lib/BlobTokenizer.d.ts +29 -0
  67. dist/node_modules/strtok3/lib/BlobTokenizer.js +53 -0
  68. dist/node_modules/strtok3/lib/BufferTokenizer.d.ts +29 -0
  69. dist/node_modules/strtok3/lib/BufferTokenizer.js +52 -0
  70. dist/node_modules/strtok3/lib/FileTokenizer.d.ts +37 -0
  71. dist/node_modules/strtok3/lib/FileTokenizer.js +61 -0
  72. dist/node_modules/strtok3/lib/ReadStreamTokenizer.d.ts +31 -0
  73. dist/node_modules/strtok3/lib/ReadStreamTokenizer.js +102 -0
  74. dist/node_modules/strtok3/lib/core.d.ts +40 -0
  75. dist/node_modules/strtok3/lib/core.js +62 -0
  76. dist/node_modules/strtok3/lib/index.d.ts +16 -0
  77. dist/node_modules/strtok3/lib/index.js +22 -0
  78. dist/node_modules/strtok3/lib/stream/AbstractStreamReader.d.ts +54 -0
  79. dist/node_modules/strtok3/lib/stream/AbstractStreamReader.js +71 -0
  80. dist/node_modules/strtok3/lib/stream/Deferred.d.ts +6 -0
  81. dist/node_modules/strtok3/lib/stream/Deferred.js +10 -0
  82. dist/node_modules/strtok3/lib/stream/Errors.d.ts +10 -0
  83. dist/node_modules/strtok3/lib/stream/Errors.js +16 -0
  84. dist/node_modules/strtok3/lib/stream/StreamReader.d.ts +29 -0
  85. dist/node_modules/strtok3/lib/stream/StreamReader.js +83 -0
  86. dist/node_modules/strtok3/lib/stream/WebStreamByobReader.d.ts +14 -0
  87. dist/node_modules/strtok3/lib/stream/WebStreamByobReader.js +27 -0
  88. dist/node_modules/strtok3/lib/stream/WebStreamDefaultReader.d.ts +19 -0
  89. dist/node_modules/strtok3/lib/stream/WebStreamDefaultReader.js +62 -0
  90. dist/node_modules/strtok3/lib/stream/WebStreamReader.d.ts +14 -0
  91. dist/node_modules/strtok3/lib/stream/WebStreamReader.js +13 -0
  92. dist/node_modules/strtok3/lib/stream/WebStreamReaderFactory.d.ts +5 -0
  93. dist/node_modules/strtok3/lib/stream/WebStreamReaderFactory.js +19 -0
  94. dist/node_modules/strtok3/lib/stream/index.d.ts +6 -0
  95. dist/node_modules/strtok3/lib/stream/index.js +5 -0
  96. dist/node_modules/strtok3/lib/types.d.ts +139 -0
  97. dist/node_modules/strtok3/lib/types.js +1 -0
  98. dist/node_modules/strtok3/package.json +94 -0
  99. dist/node_modules/token-types/LICENSE.txt +9 -0
  100. dist/node_modules/token-types/README.md +120 -0
  101. dist/node_modules/token-types/lib/index.d.ts +135 -0
  102. dist/node_modules/token-types/lib/index.js +401 -0
  103. dist/node_modules/token-types/package.json +81 -0
  104. dist/node_modules/uint8array-extras/index.d.ts +312 -0
  105. dist/node_modules/uint8array-extras/index.js +321 -0
  106. dist/node_modules/uint8array-extras/license +9 -0
  107. dist/node_modules/uint8array-extras/package.json +54 -0
  108. dist/node_modules/uint8array-extras/readme.md +301 -0
  109. dist/node_modules/ws/LICENSE +20 -0
  110. dist/node_modules/ws/README.md +548 -0
  111. dist/node_modules/ws/browser.js +8 -0
  112. dist/node_modules/ws/index.js +13 -0
  113. dist/node_modules/ws/lib/buffer-util.js +131 -0
  114. dist/node_modules/ws/lib/constants.js +18 -0
  115. dist/node_modules/ws/lib/event-target.js +292 -0
  116. dist/node_modules/ws/lib/extension.js +203 -0
  117. dist/node_modules/ws/lib/limiter.js +55 -0
  118. dist/node_modules/ws/lib/permessage-deflate.js +528 -0
  119. dist/node_modules/ws/lib/receiver.js +706 -0
  120. dist/node_modules/ws/lib/sender.js +602 -0
  121. dist/node_modules/ws/lib/stream.js +161 -0
  122. dist/node_modules/ws/lib/subprotocol.js +62 -0
  123. dist/node_modules/ws/lib/validation.js +152 -0
  124. dist/node_modules/ws/lib/websocket-server.js +550 -0
  125. dist/node_modules/ws/lib/websocket.js +1388 -0
  126. dist/node_modules/ws/package.json +69 -0
  127. dist/node_modules/ws/wrapper.mjs +8 -0
  128. dist/package.json +1 -0
  129. dist/webui/assets/index-B9vGhdCO.js +256 -0
  130. dist/webui/assets/index-DaqFU7JR.css +1 -0
  131. dist/webui/index.html +13 -0
  132. dist/webui/logo.jpg +0 -0
  133. dist//344/275/277/347/224/250/350/257/264/346/230/216.txt +11 -0
  134. dist//346/233/264/346/226/260/346/227/245/345/277/227.txt +399 -0
@@ -0,0 +1,1388 @@
1
+ /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
2
+
3
+ 'use strict';
4
+
5
+ const EventEmitter = require('events');
6
+ const https = require('https');
7
+ const http = require('http');
8
+ const net = require('net');
9
+ const tls = require('tls');
10
+ const { randomBytes, createHash } = require('crypto');
11
+ const { Duplex, Readable } = require('stream');
12
+ const { URL } = require('url');
13
+
14
+ const PerMessageDeflate = require('./permessage-deflate');
15
+ const Receiver = require('./receiver');
16
+ const Sender = require('./sender');
17
+ const { isBlob } = require('./validation');
18
+
19
+ const {
20
+ BINARY_TYPES,
21
+ EMPTY_BUFFER,
22
+ GUID,
23
+ kForOnEventAttribute,
24
+ kListener,
25
+ kStatusCode,
26
+ kWebSocket,
27
+ NOOP
28
+ } = require('./constants');
29
+ const {
30
+ EventTarget: { addEventListener, removeEventListener }
31
+ } = require('./event-target');
32
+ const { format, parse } = require('./extension');
33
+ const { toBuffer } = require('./buffer-util');
34
+
35
+ const closeTimeout = 30 * 1000;
36
+ const kAborted = Symbol('kAborted');
37
+ const protocolVersions = [8, 13];
38
+ const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
39
+ const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
40
+
41
+ /**
42
+ * Class representing a WebSocket.
43
+ *
44
+ * @extends EventEmitter
45
+ */
46
+ class WebSocket extends EventEmitter {
47
+ /**
48
+ * Create a new `WebSocket`.
49
+ *
50
+ * @param {(String|URL)} address The URL to which to connect
51
+ * @param {(String|String[])} [protocols] The subprotocols
52
+ * @param {Object} [options] Connection options
53
+ */
54
+ constructor(address, protocols, options) {
55
+ super();
56
+
57
+ this._binaryType = BINARY_TYPES[0];
58
+ this._closeCode = 1006;
59
+ this._closeFrameReceived = false;
60
+ this._closeFrameSent = false;
61
+ this._closeMessage = EMPTY_BUFFER;
62
+ this._closeTimer = null;
63
+ this._errorEmitted = false;
64
+ this._extensions = {};
65
+ this._paused = false;
66
+ this._protocol = '';
67
+ this._readyState = WebSocket.CONNECTING;
68
+ this._receiver = null;
69
+ this._sender = null;
70
+ this._socket = null;
71
+
72
+ if (address !== null) {
73
+ this._bufferedAmount = 0;
74
+ this._isServer = false;
75
+ this._redirects = 0;
76
+
77
+ if (protocols === undefined) {
78
+ protocols = [];
79
+ } else if (!Array.isArray(protocols)) {
80
+ if (typeof protocols === 'object' && protocols !== null) {
81
+ options = protocols;
82
+ protocols = [];
83
+ } else {
84
+ protocols = [protocols];
85
+ }
86
+ }
87
+
88
+ initAsClient(this, address, protocols, options);
89
+ } else {
90
+ this._autoPong = options.autoPong;
91
+ this._isServer = true;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * For historical reasons, the custom "nodebuffer" type is used by the default
97
+ * instead of "blob".
98
+ *
99
+ * @type {String}
100
+ */
101
+ get binaryType() {
102
+ return this._binaryType;
103
+ }
104
+
105
+ set binaryType(type) {
106
+ if (!BINARY_TYPES.includes(type)) return;
107
+
108
+ this._binaryType = type;
109
+
110
+ //
111
+ // Allow to change `binaryType` on the fly.
112
+ //
113
+ if (this._receiver) this._receiver._binaryType = type;
114
+ }
115
+
116
+ /**
117
+ * @type {Number}
118
+ */
119
+ get bufferedAmount() {
120
+ if (!this._socket) return this._bufferedAmount;
121
+
122
+ return this._socket._writableState.length + this._sender._bufferedBytes;
123
+ }
124
+
125
+ /**
126
+ * @type {String}
127
+ */
128
+ get extensions() {
129
+ return Object.keys(this._extensions).join();
130
+ }
131
+
132
+ /**
133
+ * @type {Boolean}
134
+ */
135
+ get isPaused() {
136
+ return this._paused;
137
+ }
138
+
139
+ /**
140
+ * @type {Function}
141
+ */
142
+ /* istanbul ignore next */
143
+ get onclose() {
144
+ return null;
145
+ }
146
+
147
+ /**
148
+ * @type {Function}
149
+ */
150
+ /* istanbul ignore next */
151
+ get onerror() {
152
+ return null;
153
+ }
154
+
155
+ /**
156
+ * @type {Function}
157
+ */
158
+ /* istanbul ignore next */
159
+ get onopen() {
160
+ return null;
161
+ }
162
+
163
+ /**
164
+ * @type {Function}
165
+ */
166
+ /* istanbul ignore next */
167
+ get onmessage() {
168
+ return null;
169
+ }
170
+
171
+ /**
172
+ * @type {String}
173
+ */
174
+ get protocol() {
175
+ return this._protocol;
176
+ }
177
+
178
+ /**
179
+ * @type {Number}
180
+ */
181
+ get readyState() {
182
+ return this._readyState;
183
+ }
184
+
185
+ /**
186
+ * @type {String}
187
+ */
188
+ get url() {
189
+ return this._url;
190
+ }
191
+
192
+ /**
193
+ * Set up the socket and the internal resources.
194
+ *
195
+ * @param {Duplex} socket The network socket between the server and client
196
+ * @param {Buffer} head The first packet of the upgraded stream
197
+ * @param {Object} options Options object
198
+ * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
199
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
200
+ * multiple times in the same tick
201
+ * @param {Function} [options.generateMask] The function used to generate the
202
+ * masking key
203
+ * @param {Number} [options.maxPayload=0] The maximum allowed message size
204
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
205
+ * not to skip UTF-8 validation for text and close messages
206
+ * @private
207
+ */
208
+ setSocket(socket, head, options) {
209
+ const receiver = new Receiver({
210
+ allowSynchronousEvents: options.allowSynchronousEvents,
211
+ binaryType: this.binaryType,
212
+ extensions: this._extensions,
213
+ isServer: this._isServer,
214
+ maxPayload: options.maxPayload,
215
+ skipUTF8Validation: options.skipUTF8Validation
216
+ });
217
+
218
+ const sender = new Sender(socket, this._extensions, options.generateMask);
219
+
220
+ this._receiver = receiver;
221
+ this._sender = sender;
222
+ this._socket = socket;
223
+
224
+ receiver[kWebSocket] = this;
225
+ sender[kWebSocket] = this;
226
+ socket[kWebSocket] = this;
227
+
228
+ receiver.on('conclude', receiverOnConclude);
229
+ receiver.on('drain', receiverOnDrain);
230
+ receiver.on('error', receiverOnError);
231
+ receiver.on('message', receiverOnMessage);
232
+ receiver.on('ping', receiverOnPing);
233
+ receiver.on('pong', receiverOnPong);
234
+
235
+ sender.onerror = senderOnError;
236
+
237
+ //
238
+ // These methods may not be available if `socket` is just a `Duplex`.
239
+ //
240
+ if (socket.setTimeout) socket.setTimeout(0);
241
+ if (socket.setNoDelay) socket.setNoDelay();
242
+
243
+ if (head.length > 0) socket.unshift(head);
244
+
245
+ socket.on('close', socketOnClose);
246
+ socket.on('data', socketOnData);
247
+ socket.on('end', socketOnEnd);
248
+ socket.on('error', socketOnError);
249
+
250
+ this._readyState = WebSocket.OPEN;
251
+ this.emit('open');
252
+ }
253
+
254
+ /**
255
+ * Emit the `'close'` event.
256
+ *
257
+ * @private
258
+ */
259
+ emitClose() {
260
+ if (!this._socket) {
261
+ this._readyState = WebSocket.CLOSED;
262
+ this.emit('close', this._closeCode, this._closeMessage);
263
+ return;
264
+ }
265
+
266
+ if (this._extensions[PerMessageDeflate.extensionName]) {
267
+ this._extensions[PerMessageDeflate.extensionName].cleanup();
268
+ }
269
+
270
+ this._receiver.removeAllListeners();
271
+ this._readyState = WebSocket.CLOSED;
272
+ this.emit('close', this._closeCode, this._closeMessage);
273
+ }
274
+
275
+ /**
276
+ * Start a closing handshake.
277
+ *
278
+ * +----------+ +-----------+ +----------+
279
+ * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
280
+ * | +----------+ +-----------+ +----------+ |
281
+ * +----------+ +-----------+ |
282
+ * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
283
+ * +----------+ +-----------+ |
284
+ * | | | +---+ |
285
+ * +------------------------+-->|fin| - - - -
286
+ * | +---+ | +---+
287
+ * - - - - -|fin|<---------------------+
288
+ * +---+
289
+ *
290
+ * @param {Number} [code] Status code explaining why the connection is closing
291
+ * @param {(String|Buffer)} [data] The reason why the connection is
292
+ * closing
293
+ * @public
294
+ */
295
+ close(code, data) {
296
+ if (this.readyState === WebSocket.CLOSED) return;
297
+ if (this.readyState === WebSocket.CONNECTING) {
298
+ const msg = 'WebSocket was closed before the connection was established';
299
+ abortHandshake(this, this._req, msg);
300
+ return;
301
+ }
302
+
303
+ if (this.readyState === WebSocket.CLOSING) {
304
+ if (
305
+ this._closeFrameSent &&
306
+ (this._closeFrameReceived || this._receiver._writableState.errorEmitted)
307
+ ) {
308
+ this._socket.end();
309
+ }
310
+
311
+ return;
312
+ }
313
+
314
+ this._readyState = WebSocket.CLOSING;
315
+ this._sender.close(code, data, !this._isServer, (err) => {
316
+ //
317
+ // This error is handled by the `'error'` listener on the socket. We only
318
+ // want to know if the close frame has been sent here.
319
+ //
320
+ if (err) return;
321
+
322
+ this._closeFrameSent = true;
323
+
324
+ if (
325
+ this._closeFrameReceived ||
326
+ this._receiver._writableState.errorEmitted
327
+ ) {
328
+ this._socket.end();
329
+ }
330
+ });
331
+
332
+ setCloseTimer(this);
333
+ }
334
+
335
+ /**
336
+ * Pause the socket.
337
+ *
338
+ * @public
339
+ */
340
+ pause() {
341
+ if (
342
+ this.readyState === WebSocket.CONNECTING ||
343
+ this.readyState === WebSocket.CLOSED
344
+ ) {
345
+ return;
346
+ }
347
+
348
+ this._paused = true;
349
+ this._socket.pause();
350
+ }
351
+
352
+ /**
353
+ * Send a ping.
354
+ *
355
+ * @param {*} [data] The data to send
356
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
357
+ * @param {Function} [cb] Callback which is executed when the ping is sent
358
+ * @public
359
+ */
360
+ ping(data, mask, cb) {
361
+ if (this.readyState === WebSocket.CONNECTING) {
362
+ throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
363
+ }
364
+
365
+ if (typeof data === 'function') {
366
+ cb = data;
367
+ data = mask = undefined;
368
+ } else if (typeof mask === 'function') {
369
+ cb = mask;
370
+ mask = undefined;
371
+ }
372
+
373
+ if (typeof data === 'number') data = data.toString();
374
+
375
+ if (this.readyState !== WebSocket.OPEN) {
376
+ sendAfterClose(this, data, cb);
377
+ return;
378
+ }
379
+
380
+ if (mask === undefined) mask = !this._isServer;
381
+ this._sender.ping(data || EMPTY_BUFFER, mask, cb);
382
+ }
383
+
384
+ /**
385
+ * Send a pong.
386
+ *
387
+ * @param {*} [data] The data to send
388
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
389
+ * @param {Function} [cb] Callback which is executed when the pong is sent
390
+ * @public
391
+ */
392
+ pong(data, mask, cb) {
393
+ if (this.readyState === WebSocket.CONNECTING) {
394
+ throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
395
+ }
396
+
397
+ if (typeof data === 'function') {
398
+ cb = data;
399
+ data = mask = undefined;
400
+ } else if (typeof mask === 'function') {
401
+ cb = mask;
402
+ mask = undefined;
403
+ }
404
+
405
+ if (typeof data === 'number') data = data.toString();
406
+
407
+ if (this.readyState !== WebSocket.OPEN) {
408
+ sendAfterClose(this, data, cb);
409
+ return;
410
+ }
411
+
412
+ if (mask === undefined) mask = !this._isServer;
413
+ this._sender.pong(data || EMPTY_BUFFER, mask, cb);
414
+ }
415
+
416
+ /**
417
+ * Resume the socket.
418
+ *
419
+ * @public
420
+ */
421
+ resume() {
422
+ if (
423
+ this.readyState === WebSocket.CONNECTING ||
424
+ this.readyState === WebSocket.CLOSED
425
+ ) {
426
+ return;
427
+ }
428
+
429
+ this._paused = false;
430
+ if (!this._receiver._writableState.needDrain) this._socket.resume();
431
+ }
432
+
433
+ /**
434
+ * Send a data message.
435
+ *
436
+ * @param {*} data The message to send
437
+ * @param {Object} [options] Options object
438
+ * @param {Boolean} [options.binary] Specifies whether `data` is binary or
439
+ * text
440
+ * @param {Boolean} [options.compress] Specifies whether or not to compress
441
+ * `data`
442
+ * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
443
+ * last one
444
+ * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
445
+ * @param {Function} [cb] Callback which is executed when data is written out
446
+ * @public
447
+ */
448
+ send(data, options, cb) {
449
+ if (this.readyState === WebSocket.CONNECTING) {
450
+ throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
451
+ }
452
+
453
+ if (typeof options === 'function') {
454
+ cb = options;
455
+ options = {};
456
+ }
457
+
458
+ if (typeof data === 'number') data = data.toString();
459
+
460
+ if (this.readyState !== WebSocket.OPEN) {
461
+ sendAfterClose(this, data, cb);
462
+ return;
463
+ }
464
+
465
+ const opts = {
466
+ binary: typeof data !== 'string',
467
+ mask: !this._isServer,
468
+ compress: true,
469
+ fin: true,
470
+ ...options
471
+ };
472
+
473
+ if (!this._extensions[PerMessageDeflate.extensionName]) {
474
+ opts.compress = false;
475
+ }
476
+
477
+ this._sender.send(data || EMPTY_BUFFER, opts, cb);
478
+ }
479
+
480
+ /**
481
+ * Forcibly close the connection.
482
+ *
483
+ * @public
484
+ */
485
+ terminate() {
486
+ if (this.readyState === WebSocket.CLOSED) return;
487
+ if (this.readyState === WebSocket.CONNECTING) {
488
+ const msg = 'WebSocket was closed before the connection was established';
489
+ abortHandshake(this, this._req, msg);
490
+ return;
491
+ }
492
+
493
+ if (this._socket) {
494
+ this._readyState = WebSocket.CLOSING;
495
+ this._socket.destroy();
496
+ }
497
+ }
498
+ }
499
+
500
+ /**
501
+ * @constant {Number} CONNECTING
502
+ * @memberof WebSocket
503
+ */
504
+ Object.defineProperty(WebSocket, 'CONNECTING', {
505
+ enumerable: true,
506
+ value: readyStates.indexOf('CONNECTING')
507
+ });
508
+
509
+ /**
510
+ * @constant {Number} CONNECTING
511
+ * @memberof WebSocket.prototype
512
+ */
513
+ Object.defineProperty(WebSocket.prototype, 'CONNECTING', {
514
+ enumerable: true,
515
+ value: readyStates.indexOf('CONNECTING')
516
+ });
517
+
518
+ /**
519
+ * @constant {Number} OPEN
520
+ * @memberof WebSocket
521
+ */
522
+ Object.defineProperty(WebSocket, 'OPEN', {
523
+ enumerable: true,
524
+ value: readyStates.indexOf('OPEN')
525
+ });
526
+
527
+ /**
528
+ * @constant {Number} OPEN
529
+ * @memberof WebSocket.prototype
530
+ */
531
+ Object.defineProperty(WebSocket.prototype, 'OPEN', {
532
+ enumerable: true,
533
+ value: readyStates.indexOf('OPEN')
534
+ });
535
+
536
+ /**
537
+ * @constant {Number} CLOSING
538
+ * @memberof WebSocket
539
+ */
540
+ Object.defineProperty(WebSocket, 'CLOSING', {
541
+ enumerable: true,
542
+ value: readyStates.indexOf('CLOSING')
543
+ });
544
+
545
+ /**
546
+ * @constant {Number} CLOSING
547
+ * @memberof WebSocket.prototype
548
+ */
549
+ Object.defineProperty(WebSocket.prototype, 'CLOSING', {
550
+ enumerable: true,
551
+ value: readyStates.indexOf('CLOSING')
552
+ });
553
+
554
+ /**
555
+ * @constant {Number} CLOSED
556
+ * @memberof WebSocket
557
+ */
558
+ Object.defineProperty(WebSocket, 'CLOSED', {
559
+ enumerable: true,
560
+ value: readyStates.indexOf('CLOSED')
561
+ });
562
+
563
+ /**
564
+ * @constant {Number} CLOSED
565
+ * @memberof WebSocket.prototype
566
+ */
567
+ Object.defineProperty(WebSocket.prototype, 'CLOSED', {
568
+ enumerable: true,
569
+ value: readyStates.indexOf('CLOSED')
570
+ });
571
+
572
+ [
573
+ 'binaryType',
574
+ 'bufferedAmount',
575
+ 'extensions',
576
+ 'isPaused',
577
+ 'protocol',
578
+ 'readyState',
579
+ 'url'
580
+ ].forEach((property) => {
581
+ Object.defineProperty(WebSocket.prototype, property, { enumerable: true });
582
+ });
583
+
584
+ //
585
+ // Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.
586
+ // See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
587
+ //
588
+ ['open', 'error', 'close', 'message'].forEach((method) => {
589
+ Object.defineProperty(WebSocket.prototype, `on${method}`, {
590
+ enumerable: true,
591
+ get() {
592
+ for (const listener of this.listeners(method)) {
593
+ if (listener[kForOnEventAttribute]) return listener[kListener];
594
+ }
595
+
596
+ return null;
597
+ },
598
+ set(handler) {
599
+ for (const listener of this.listeners(method)) {
600
+ if (listener[kForOnEventAttribute]) {
601
+ this.removeListener(method, listener);
602
+ break;
603
+ }
604
+ }
605
+
606
+ if (typeof handler !== 'function') return;
607
+
608
+ this.addEventListener(method, handler, {
609
+ [kForOnEventAttribute]: true
610
+ });
611
+ }
612
+ });
613
+ });
614
+
615
+ WebSocket.prototype.addEventListener = addEventListener;
616
+ WebSocket.prototype.removeEventListener = removeEventListener;
617
+
618
+ module.exports = WebSocket;
619
+
620
+ /**
621
+ * Initialize a WebSocket client.
622
+ *
623
+ * @param {WebSocket} websocket The client to initialize
624
+ * @param {(String|URL)} address The URL to which to connect
625
+ * @param {Array} protocols The subprotocols
626
+ * @param {Object} [options] Connection options
627
+ * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
628
+ * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
629
+ * times in the same tick
630
+ * @param {Boolean} [options.autoPong=true] Specifies whether or not to
631
+ * automatically send a pong in response to a ping
632
+ * @param {Function} [options.finishRequest] A function which can be used to
633
+ * customize the headers of each http request before it is sent
634
+ * @param {Boolean} [options.followRedirects=false] Whether or not to follow
635
+ * redirects
636
+ * @param {Function} [options.generateMask] The function used to generate the
637
+ * masking key
638
+ * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
639
+ * handshake request
640
+ * @param {Number} [options.maxPayload=104857600] The maximum allowed message
641
+ * size
642
+ * @param {Number} [options.maxRedirects=10] The maximum number of redirects
643
+ * allowed
644
+ * @param {String} [options.origin] Value of the `Origin` or
645
+ * `Sec-WebSocket-Origin` header
646
+ * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
647
+ * permessage-deflate
648
+ * @param {Number} [options.protocolVersion=13] Value of the
649
+ * `Sec-WebSocket-Version` header
650
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
651
+ * not to skip UTF-8 validation for text and close messages
652
+ * @private
653
+ */
654
+ function initAsClient(websocket, address, protocols, options) {
655
+ const opts = {
656
+ allowSynchronousEvents: true,
657
+ autoPong: true,
658
+ protocolVersion: protocolVersions[1],
659
+ maxPayload: 100 * 1024 * 1024,
660
+ skipUTF8Validation: false,
661
+ perMessageDeflate: true,
662
+ followRedirects: false,
663
+ maxRedirects: 10,
664
+ ...options,
665
+ socketPath: undefined,
666
+ hostname: undefined,
667
+ protocol: undefined,
668
+ timeout: undefined,
669
+ method: 'GET',
670
+ host: undefined,
671
+ path: undefined,
672
+ port: undefined
673
+ };
674
+
675
+ websocket._autoPong = opts.autoPong;
676
+
677
+ if (!protocolVersions.includes(opts.protocolVersion)) {
678
+ throw new RangeError(
679
+ `Unsupported protocol version: ${opts.protocolVersion} ` +
680
+ `(supported versions: ${protocolVersions.join(', ')})`
681
+ );
682
+ }
683
+
684
+ let parsedUrl;
685
+
686
+ if (address instanceof URL) {
687
+ parsedUrl = address;
688
+ } else {
689
+ try {
690
+ parsedUrl = new URL(address);
691
+ } catch (e) {
692
+ throw new SyntaxError(`Invalid URL: ${address}`);
693
+ }
694
+ }
695
+
696
+ if (parsedUrl.protocol === 'http:') {
697
+ parsedUrl.protocol = 'ws:';
698
+ } else if (parsedUrl.protocol === 'https:') {
699
+ parsedUrl.protocol = 'wss:';
700
+ }
701
+
702
+ websocket._url = parsedUrl.href;
703
+
704
+ const isSecure = parsedUrl.protocol === 'wss:';
705
+ const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
706
+ let invalidUrlMessage;
707
+
708
+ if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
709
+ invalidUrlMessage =
710
+ 'The URL\'s protocol must be one of "ws:", "wss:", ' +
711
+ '"http:", "https:", or "ws+unix:"';
712
+ } else if (isIpcUrl && !parsedUrl.pathname) {
713
+ invalidUrlMessage = "The URL's pathname is empty";
714
+ } else if (parsedUrl.hash) {
715
+ invalidUrlMessage = 'The URL contains a fragment identifier';
716
+ }
717
+
718
+ if (invalidUrlMessage) {
719
+ const err = new SyntaxError(invalidUrlMessage);
720
+
721
+ if (websocket._redirects === 0) {
722
+ throw err;
723
+ } else {
724
+ emitErrorAndClose(websocket, err);
725
+ return;
726
+ }
727
+ }
728
+
729
+ const defaultPort = isSecure ? 443 : 80;
730
+ const key = randomBytes(16).toString('base64');
731
+ const request = isSecure ? https.request : http.request;
732
+ const protocolSet = new Set();
733
+ let perMessageDeflate;
734
+
735
+ opts.createConnection =
736
+ opts.createConnection || (isSecure ? tlsConnect : netConnect);
737
+ opts.defaultPort = opts.defaultPort || defaultPort;
738
+ opts.port = parsedUrl.port || defaultPort;
739
+ opts.host = parsedUrl.hostname.startsWith('[')
740
+ ? parsedUrl.hostname.slice(1, -1)
741
+ : parsedUrl.hostname;
742
+ opts.headers = {
743
+ ...opts.headers,
744
+ 'Sec-WebSocket-Version': opts.protocolVersion,
745
+ 'Sec-WebSocket-Key': key,
746
+ Connection: 'Upgrade',
747
+ Upgrade: 'websocket'
748
+ };
749
+ opts.path = parsedUrl.pathname + parsedUrl.search;
750
+ opts.timeout = opts.handshakeTimeout;
751
+
752
+ if (opts.perMessageDeflate) {
753
+ perMessageDeflate = new PerMessageDeflate(
754
+ opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
755
+ false,
756
+ opts.maxPayload
757
+ );
758
+ opts.headers['Sec-WebSocket-Extensions'] = format({
759
+ [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
760
+ });
761
+ }
762
+ if (protocols.length) {
763
+ for (const protocol of protocols) {
764
+ if (
765
+ typeof protocol !== 'string' ||
766
+ !subprotocolRegex.test(protocol) ||
767
+ protocolSet.has(protocol)
768
+ ) {
769
+ throw new SyntaxError(
770
+ 'An invalid or duplicated subprotocol was specified'
771
+ );
772
+ }
773
+
774
+ protocolSet.add(protocol);
775
+ }
776
+
777
+ opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');
778
+ }
779
+ if (opts.origin) {
780
+ if (opts.protocolVersion < 13) {
781
+ opts.headers['Sec-WebSocket-Origin'] = opts.origin;
782
+ } else {
783
+ opts.headers.Origin = opts.origin;
784
+ }
785
+ }
786
+ if (parsedUrl.username || parsedUrl.password) {
787
+ opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
788
+ }
789
+
790
+ if (isIpcUrl) {
791
+ const parts = opts.path.split(':');
792
+
793
+ opts.socketPath = parts[0];
794
+ opts.path = parts[1];
795
+ }
796
+
797
+ let req;
798
+
799
+ if (opts.followRedirects) {
800
+ if (websocket._redirects === 0) {
801
+ websocket._originalIpc = isIpcUrl;
802
+ websocket._originalSecure = isSecure;
803
+ websocket._originalHostOrSocketPath = isIpcUrl
804
+ ? opts.socketPath
805
+ : parsedUrl.host;
806
+
807
+ const headers = options && options.headers;
808
+
809
+ //
810
+ // Shallow copy the user provided options so that headers can be changed
811
+ // without mutating the original object.
812
+ //
813
+ options = { ...options, headers: {} };
814
+
815
+ if (headers) {
816
+ for (const [key, value] of Object.entries(headers)) {
817
+ options.headers[key.toLowerCase()] = value;
818
+ }
819
+ }
820
+ } else if (websocket.listenerCount('redirect') === 0) {
821
+ const isSameHost = isIpcUrl
822
+ ? websocket._originalIpc
823
+ ? opts.socketPath === websocket._originalHostOrSocketPath
824
+ : false
825
+ : websocket._originalIpc
826
+ ? false
827
+ : parsedUrl.host === websocket._originalHostOrSocketPath;
828
+
829
+ if (!isSameHost || (websocket._originalSecure && !isSecure)) {
830
+ //
831
+ // Match curl 7.77.0 behavior and drop the following headers. These
832
+ // headers are also dropped when following a redirect to a subdomain.
833
+ //
834
+ delete opts.headers.authorization;
835
+ delete opts.headers.cookie;
836
+
837
+ if (!isSameHost) delete opts.headers.host;
838
+
839
+ opts.auth = undefined;
840
+ }
841
+ }
842
+
843
+ //
844
+ // Match curl 7.77.0 behavior and make the first `Authorization` header win.
845
+ // If the `Authorization` header is set, then there is nothing to do as it
846
+ // will take precedence.
847
+ //
848
+ if (opts.auth && !options.headers.authorization) {
849
+ options.headers.authorization =
850
+ 'Basic ' + Buffer.from(opts.auth).toString('base64');
851
+ }
852
+
853
+ req = websocket._req = request(opts);
854
+
855
+ if (websocket._redirects) {
856
+ //
857
+ // Unlike what is done for the `'upgrade'` event, no early exit is
858
+ // triggered here if the user calls `websocket.close()` or
859
+ // `websocket.terminate()` from a listener of the `'redirect'` event. This
860
+ // is because the user can also call `request.destroy()` with an error
861
+ // before calling `websocket.close()` or `websocket.terminate()` and this
862
+ // would result in an error being emitted on the `request` object with no
863
+ // `'error'` event listeners attached.
864
+ //
865
+ websocket.emit('redirect', websocket.url, req);
866
+ }
867
+ } else {
868
+ req = websocket._req = request(opts);
869
+ }
870
+
871
+ if (opts.timeout) {
872
+ req.on('timeout', () => {
873
+ abortHandshake(websocket, req, 'Opening handshake has timed out');
874
+ });
875
+ }
876
+
877
+ req.on('error', (err) => {
878
+ if (req === null || req[kAborted]) return;
879
+
880
+ req = websocket._req = null;
881
+ emitErrorAndClose(websocket, err);
882
+ });
883
+
884
+ req.on('response', (res) => {
885
+ const location = res.headers.location;
886
+ const statusCode = res.statusCode;
887
+
888
+ if (
889
+ location &&
890
+ opts.followRedirects &&
891
+ statusCode >= 300 &&
892
+ statusCode < 400
893
+ ) {
894
+ if (++websocket._redirects > opts.maxRedirects) {
895
+ abortHandshake(websocket, req, 'Maximum redirects exceeded');
896
+ return;
897
+ }
898
+
899
+ req.abort();
900
+
901
+ let addr;
902
+
903
+ try {
904
+ addr = new URL(location, address);
905
+ } catch (e) {
906
+ const err = new SyntaxError(`Invalid URL: ${location}`);
907
+ emitErrorAndClose(websocket, err);
908
+ return;
909
+ }
910
+
911
+ initAsClient(websocket, addr, protocols, options);
912
+ } else if (!websocket.emit('unexpected-response', req, res)) {
913
+ abortHandshake(
914
+ websocket,
915
+ req,
916
+ `Unexpected server response: ${res.statusCode}`
917
+ );
918
+ }
919
+ });
920
+
921
+ req.on('upgrade', (res, socket, head) => {
922
+ websocket.emit('upgrade', res);
923
+
924
+ //
925
+ // The user may have closed the connection from a listener of the
926
+ // `'upgrade'` event.
927
+ //
928
+ if (websocket.readyState !== WebSocket.CONNECTING) return;
929
+
930
+ req = websocket._req = null;
931
+
932
+ const upgrade = res.headers.upgrade;
933
+
934
+ if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
935
+ abortHandshake(websocket, socket, 'Invalid Upgrade header');
936
+ return;
937
+ }
938
+
939
+ const digest = createHash('sha1')
940
+ .update(key + GUID)
941
+ .digest('base64');
942
+
943
+ if (res.headers['sec-websocket-accept'] !== digest) {
944
+ abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');
945
+ return;
946
+ }
947
+
948
+ const serverProt = res.headers['sec-websocket-protocol'];
949
+ let protError;
950
+
951
+ if (serverProt !== undefined) {
952
+ if (!protocolSet.size) {
953
+ protError = 'Server sent a subprotocol but none was requested';
954
+ } else if (!protocolSet.has(serverProt)) {
955
+ protError = 'Server sent an invalid subprotocol';
956
+ }
957
+ } else if (protocolSet.size) {
958
+ protError = 'Server sent no subprotocol';
959
+ }
960
+
961
+ if (protError) {
962
+ abortHandshake(websocket, socket, protError);
963
+ return;
964
+ }
965
+
966
+ if (serverProt) websocket._protocol = serverProt;
967
+
968
+ const secWebSocketExtensions = res.headers['sec-websocket-extensions'];
969
+
970
+ if (secWebSocketExtensions !== undefined) {
971
+ if (!perMessageDeflate) {
972
+ const message =
973
+ 'Server sent a Sec-WebSocket-Extensions header but no extension ' +
974
+ 'was requested';
975
+ abortHandshake(websocket, socket, message);
976
+ return;
977
+ }
978
+
979
+ let extensions;
980
+
981
+ try {
982
+ extensions = parse(secWebSocketExtensions);
983
+ } catch (err) {
984
+ const message = 'Invalid Sec-WebSocket-Extensions header';
985
+ abortHandshake(websocket, socket, message);
986
+ return;
987
+ }
988
+
989
+ const extensionNames = Object.keys(extensions);
990
+
991
+ if (
992
+ extensionNames.length !== 1 ||
993
+ extensionNames[0] !== PerMessageDeflate.extensionName
994
+ ) {
995
+ const message = 'Server indicated an extension that was not requested';
996
+ abortHandshake(websocket, socket, message);
997
+ return;
998
+ }
999
+
1000
+ try {
1001
+ perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
1002
+ } catch (err) {
1003
+ const message = 'Invalid Sec-WebSocket-Extensions header';
1004
+ abortHandshake(websocket, socket, message);
1005
+ return;
1006
+ }
1007
+
1008
+ websocket._extensions[PerMessageDeflate.extensionName] =
1009
+ perMessageDeflate;
1010
+ }
1011
+
1012
+ websocket.setSocket(socket, head, {
1013
+ allowSynchronousEvents: opts.allowSynchronousEvents,
1014
+ generateMask: opts.generateMask,
1015
+ maxPayload: opts.maxPayload,
1016
+ skipUTF8Validation: opts.skipUTF8Validation
1017
+ });
1018
+ });
1019
+
1020
+ if (opts.finishRequest) {
1021
+ opts.finishRequest(req, websocket);
1022
+ } else {
1023
+ req.end();
1024
+ }
1025
+ }
1026
+
1027
+ /**
1028
+ * Emit the `'error'` and `'close'` events.
1029
+ *
1030
+ * @param {WebSocket} websocket The WebSocket instance
1031
+ * @param {Error} The error to emit
1032
+ * @private
1033
+ */
1034
+ function emitErrorAndClose(websocket, err) {
1035
+ websocket._readyState = WebSocket.CLOSING;
1036
+ //
1037
+ // The following assignment is practically useless and is done only for
1038
+ // consistency.
1039
+ //
1040
+ websocket._errorEmitted = true;
1041
+ websocket.emit('error', err);
1042
+ websocket.emitClose();
1043
+ }
1044
+
1045
+ /**
1046
+ * Create a `net.Socket` and initiate a connection.
1047
+ *
1048
+ * @param {Object} options Connection options
1049
+ * @return {net.Socket} The newly created socket used to start the connection
1050
+ * @private
1051
+ */
1052
+ function netConnect(options) {
1053
+ options.path = options.socketPath;
1054
+ return net.connect(options);
1055
+ }
1056
+
1057
+ /**
1058
+ * Create a `tls.TLSSocket` and initiate a connection.
1059
+ *
1060
+ * @param {Object} options Connection options
1061
+ * @return {tls.TLSSocket} The newly created socket used to start the connection
1062
+ * @private
1063
+ */
1064
+ function tlsConnect(options) {
1065
+ options.path = undefined;
1066
+
1067
+ if (!options.servername && options.servername !== '') {
1068
+ options.servername = net.isIP(options.host) ? '' : options.host;
1069
+ }
1070
+
1071
+ return tls.connect(options);
1072
+ }
1073
+
1074
+ /**
1075
+ * Abort the handshake and emit an error.
1076
+ *
1077
+ * @param {WebSocket} websocket The WebSocket instance
1078
+ * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to
1079
+ * abort or the socket to destroy
1080
+ * @param {String} message The error message
1081
+ * @private
1082
+ */
1083
+ function abortHandshake(websocket, stream, message) {
1084
+ websocket._readyState = WebSocket.CLOSING;
1085
+
1086
+ const err = new Error(message);
1087
+ Error.captureStackTrace(err, abortHandshake);
1088
+
1089
+ if (stream.setHeader) {
1090
+ stream[kAborted] = true;
1091
+ stream.abort();
1092
+
1093
+ if (stream.socket && !stream.socket.destroyed) {
1094
+ //
1095
+ // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if
1096
+ // called after the request completed. See
1097
+ // https://github.com/websockets/ws/issues/1869.
1098
+ //
1099
+ stream.socket.destroy();
1100
+ }
1101
+
1102
+ process.nextTick(emitErrorAndClose, websocket, err);
1103
+ } else {
1104
+ stream.destroy(err);
1105
+ stream.once('error', websocket.emit.bind(websocket, 'error'));
1106
+ stream.once('close', websocket.emitClose.bind(websocket));
1107
+ }
1108
+ }
1109
+
1110
+ /**
1111
+ * Handle cases where the `ping()`, `pong()`, or `send()` methods are called
1112
+ * when the `readyState` attribute is `CLOSING` or `CLOSED`.
1113
+ *
1114
+ * @param {WebSocket} websocket The WebSocket instance
1115
+ * @param {*} [data] The data to send
1116
+ * @param {Function} [cb] Callback
1117
+ * @private
1118
+ */
1119
+ function sendAfterClose(websocket, data, cb) {
1120
+ if (data) {
1121
+ const length = isBlob(data) ? data.size : toBuffer(data).length;
1122
+
1123
+ //
1124
+ // The `_bufferedAmount` property is used only when the peer is a client and
1125
+ // the opening handshake fails. Under these circumstances, in fact, the
1126
+ // `setSocket()` method is not called, so the `_socket` and `_sender`
1127
+ // properties are set to `null`.
1128
+ //
1129
+ if (websocket._socket) websocket._sender._bufferedBytes += length;
1130
+ else websocket._bufferedAmount += length;
1131
+ }
1132
+
1133
+ if (cb) {
1134
+ const err = new Error(
1135
+ `WebSocket is not open: readyState ${websocket.readyState} ` +
1136
+ `(${readyStates[websocket.readyState]})`
1137
+ );
1138
+ process.nextTick(cb, err);
1139
+ }
1140
+ }
1141
+
1142
+ /**
1143
+ * The listener of the `Receiver` `'conclude'` event.
1144
+ *
1145
+ * @param {Number} code The status code
1146
+ * @param {Buffer} reason The reason for closing
1147
+ * @private
1148
+ */
1149
+ function receiverOnConclude(code, reason) {
1150
+ const websocket = this[kWebSocket];
1151
+
1152
+ websocket._closeFrameReceived = true;
1153
+ websocket._closeMessage = reason;
1154
+ websocket._closeCode = code;
1155
+
1156
+ if (websocket._socket[kWebSocket] === undefined) return;
1157
+
1158
+ websocket._socket.removeListener('data', socketOnData);
1159
+ process.nextTick(resume, websocket._socket);
1160
+
1161
+ if (code === 1005) websocket.close();
1162
+ else websocket.close(code, reason);
1163
+ }
1164
+
1165
+ /**
1166
+ * The listener of the `Receiver` `'drain'` event.
1167
+ *
1168
+ * @private
1169
+ */
1170
+ function receiverOnDrain() {
1171
+ const websocket = this[kWebSocket];
1172
+
1173
+ if (!websocket.isPaused) websocket._socket.resume();
1174
+ }
1175
+
1176
+ /**
1177
+ * The listener of the `Receiver` `'error'` event.
1178
+ *
1179
+ * @param {(RangeError|Error)} err The emitted error
1180
+ * @private
1181
+ */
1182
+ function receiverOnError(err) {
1183
+ const websocket = this[kWebSocket];
1184
+
1185
+ if (websocket._socket[kWebSocket] !== undefined) {
1186
+ websocket._socket.removeListener('data', socketOnData);
1187
+
1188
+ //
1189
+ // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See
1190
+ // https://github.com/websockets/ws/issues/1940.
1191
+ //
1192
+ process.nextTick(resume, websocket._socket);
1193
+
1194
+ websocket.close(err[kStatusCode]);
1195
+ }
1196
+
1197
+ if (!websocket._errorEmitted) {
1198
+ websocket._errorEmitted = true;
1199
+ websocket.emit('error', err);
1200
+ }
1201
+ }
1202
+
1203
+ /**
1204
+ * The listener of the `Receiver` `'finish'` event.
1205
+ *
1206
+ * @private
1207
+ */
1208
+ function receiverOnFinish() {
1209
+ this[kWebSocket].emitClose();
1210
+ }
1211
+
1212
+ /**
1213
+ * The listener of the `Receiver` `'message'` event.
1214
+ *
1215
+ * @param {Buffer|ArrayBuffer|Buffer[])} data The message
1216
+ * @param {Boolean} isBinary Specifies whether the message is binary or not
1217
+ * @private
1218
+ */
1219
+ function receiverOnMessage(data, isBinary) {
1220
+ this[kWebSocket].emit('message', data, isBinary);
1221
+ }
1222
+
1223
+ /**
1224
+ * The listener of the `Receiver` `'ping'` event.
1225
+ *
1226
+ * @param {Buffer} data The data included in the ping frame
1227
+ * @private
1228
+ */
1229
+ function receiverOnPing(data) {
1230
+ const websocket = this[kWebSocket];
1231
+
1232
+ if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
1233
+ websocket.emit('ping', data);
1234
+ }
1235
+
1236
+ /**
1237
+ * The listener of the `Receiver` `'pong'` event.
1238
+ *
1239
+ * @param {Buffer} data The data included in the pong frame
1240
+ * @private
1241
+ */
1242
+ function receiverOnPong(data) {
1243
+ this[kWebSocket].emit('pong', data);
1244
+ }
1245
+
1246
+ /**
1247
+ * Resume a readable stream
1248
+ *
1249
+ * @param {Readable} stream The readable stream
1250
+ * @private
1251
+ */
1252
+ function resume(stream) {
1253
+ stream.resume();
1254
+ }
1255
+
1256
+ /**
1257
+ * The `Sender` error event handler.
1258
+ *
1259
+ * @param {Error} The error
1260
+ * @private
1261
+ */
1262
+ function senderOnError(err) {
1263
+ const websocket = this[kWebSocket];
1264
+
1265
+ if (websocket.readyState === WebSocket.CLOSED) return;
1266
+ if (websocket.readyState === WebSocket.OPEN) {
1267
+ websocket._readyState = WebSocket.CLOSING;
1268
+ setCloseTimer(websocket);
1269
+ }
1270
+
1271
+ //
1272
+ // `socket.end()` is used instead of `socket.destroy()` to allow the other
1273
+ // peer to finish sending queued data. There is no need to set a timer here
1274
+ // because `CLOSING` means that it is already set or not needed.
1275
+ //
1276
+ this._socket.end();
1277
+
1278
+ if (!websocket._errorEmitted) {
1279
+ websocket._errorEmitted = true;
1280
+ websocket.emit('error', err);
1281
+ }
1282
+ }
1283
+
1284
+ /**
1285
+ * Set a timer to destroy the underlying raw socket of a WebSocket.
1286
+ *
1287
+ * @param {WebSocket} websocket The WebSocket instance
1288
+ * @private
1289
+ */
1290
+ function setCloseTimer(websocket) {
1291
+ websocket._closeTimer = setTimeout(
1292
+ websocket._socket.destroy.bind(websocket._socket),
1293
+ closeTimeout
1294
+ );
1295
+ }
1296
+
1297
+ /**
1298
+ * The listener of the socket `'close'` event.
1299
+ *
1300
+ * @private
1301
+ */
1302
+ function socketOnClose() {
1303
+ const websocket = this[kWebSocket];
1304
+
1305
+ this.removeListener('close', socketOnClose);
1306
+ this.removeListener('data', socketOnData);
1307
+ this.removeListener('end', socketOnEnd);
1308
+
1309
+ websocket._readyState = WebSocket.CLOSING;
1310
+
1311
+ let chunk;
1312
+
1313
+ //
1314
+ // The close frame might not have been received or the `'end'` event emitted,
1315
+ // for example, if the socket was destroyed due to an error. Ensure that the
1316
+ // `receiver` stream is closed after writing any remaining buffered data to
1317
+ // it. If the readable side of the socket is in flowing mode then there is no
1318
+ // buffered data as everything has been already written and `readable.read()`
1319
+ // will return `null`. If instead, the socket is paused, any possible buffered
1320
+ // data will be read as a single chunk.
1321
+ //
1322
+ if (
1323
+ !this._readableState.endEmitted &&
1324
+ !websocket._closeFrameReceived &&
1325
+ !websocket._receiver._writableState.errorEmitted &&
1326
+ (chunk = websocket._socket.read()) !== null
1327
+ ) {
1328
+ websocket._receiver.write(chunk);
1329
+ }
1330
+
1331
+ websocket._receiver.end();
1332
+
1333
+ this[kWebSocket] = undefined;
1334
+
1335
+ clearTimeout(websocket._closeTimer);
1336
+
1337
+ if (
1338
+ websocket._receiver._writableState.finished ||
1339
+ websocket._receiver._writableState.errorEmitted
1340
+ ) {
1341
+ websocket.emitClose();
1342
+ } else {
1343
+ websocket._receiver.on('error', receiverOnFinish);
1344
+ websocket._receiver.on('finish', receiverOnFinish);
1345
+ }
1346
+ }
1347
+
1348
+ /**
1349
+ * The listener of the socket `'data'` event.
1350
+ *
1351
+ * @param {Buffer} chunk A chunk of data
1352
+ * @private
1353
+ */
1354
+ function socketOnData(chunk) {
1355
+ if (!this[kWebSocket]._receiver.write(chunk)) {
1356
+ this.pause();
1357
+ }
1358
+ }
1359
+
1360
+ /**
1361
+ * The listener of the socket `'end'` event.
1362
+ *
1363
+ * @private
1364
+ */
1365
+ function socketOnEnd() {
1366
+ const websocket = this[kWebSocket];
1367
+
1368
+ websocket._readyState = WebSocket.CLOSING;
1369
+ websocket._receiver.end();
1370
+ this.end();
1371
+ }
1372
+
1373
+ /**
1374
+ * The listener of the socket `'error'` event.
1375
+ *
1376
+ * @private
1377
+ */
1378
+ function socketOnError() {
1379
+ const websocket = this[kWebSocket];
1380
+
1381
+ this.removeListener('error', socketOnError);
1382
+ this.on('error', NOOP);
1383
+
1384
+ if (websocket) {
1385
+ websocket._readyState = WebSocket.CLOSING;
1386
+ this.destroy();
1387
+ }
1388
+ }