@babylonjs/inspector 9.5.0 → 9.5.1

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.
@@ -5,15 +5,16 @@ import require$$1, { join, dirname, resolve } from 'path';
5
5
  import require$$0, { readFileSync, existsSync } from 'fs';
6
6
  import require$$7, { fileURLToPath } from 'url';
7
7
  import { parseArgs } from 'util';
8
- import require$$0$3 from 'events';
9
- import require$$1$1 from 'https';
8
+ import require$$0$4 from 'events';
9
+ import require$$1$2 from 'https';
10
10
  import require$$2$1 from 'http';
11
11
  import require$$3 from 'net';
12
12
  import require$$4 from 'tls';
13
- import require$$5 from 'crypto';
14
- import require$$0$2 from 'stream';
13
+ import require$$1$1 from 'crypto';
14
+ import require$$0$3 from 'stream';
15
15
  import require$$0$1 from 'zlib';
16
16
  import require$$2 from 'os';
17
+ import require$$0$2 from 'buffer';
17
18
 
18
19
  function getDefaultExportFromCjs (x) {
19
20
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -21,12 +22,21 @@ function getDefaultExportFromCjs (x) {
21
22
 
22
23
  var bufferUtil$1 = {exports: {}};
23
24
 
25
+ const BINARY_TYPES$2 = ['nodebuffer', 'arraybuffer', 'fragments'];
26
+ const hasBlob$1 = typeof Blob !== 'undefined';
27
+
28
+ if (hasBlob$1) BINARY_TYPES$2.push('blob');
29
+
24
30
  var constants = {
25
- BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'],
31
+ BINARY_TYPES: BINARY_TYPES$2,
32
+ CLOSE_TIMEOUT: 30000,
33
+ EMPTY_BUFFER: Buffer.alloc(0),
26
34
  GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
35
+ hasBlob: hasBlob$1,
36
+ kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),
37
+ kListener: Symbol('kListener'),
27
38
  kStatusCode: Symbol('status-code'),
28
39
  kWebSocket: Symbol('websocket'),
29
- EMPTY_BUFFER: Buffer.alloc(0),
30
40
  NOOP: () => {}
31
41
  };
32
42
 
@@ -324,8 +334,13 @@ function requireBufferutil () {
324
334
  return bufferutil.exports;
325
335
  }
326
336
 
337
+ var unmask$1;
338
+ var mask;
339
+
327
340
  const { EMPTY_BUFFER: EMPTY_BUFFER$3 } = constants;
328
341
 
342
+ const FastBuffer$2 = Buffer[Symbol.species];
343
+
329
344
  /**
330
345
  * Merges an array of buffers into a new buffer.
331
346
  *
@@ -347,7 +362,9 @@ function concat$1(list, totalLength) {
347
362
  offset += buf.length;
348
363
  }
349
364
 
350
- if (offset < totalLength) return target.slice(0, offset);
365
+ if (offset < totalLength) {
366
+ return new FastBuffer$2(target.buffer, target.byteOffset, offset);
367
+ }
351
368
 
352
369
  return target;
353
370
  }
@@ -376,9 +393,7 @@ function _mask(source, mask, output, offset, length) {
376
393
  * @public
377
394
  */
378
395
  function _unmask(buffer, mask) {
379
- // Required until https://github.com/nodejs/node/issues/9006 is resolved.
380
- const length = buffer.length;
381
- for (let i = 0; i < length; i++) {
396
+ for (let i = 0; i < buffer.length; i++) {
382
397
  buffer[i] ^= mask[i & 3];
383
398
  }
384
399
  }
@@ -391,11 +406,11 @@ function _unmask(buffer, mask) {
391
406
  * @public
392
407
  */
393
408
  function toArrayBuffer$1(buf) {
394
- if (buf.byteLength === buf.buffer.byteLength) {
409
+ if (buf.length === buf.buffer.byteLength) {
395
410
  return buf.buffer;
396
411
  }
397
412
 
398
- return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
413
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
399
414
  }
400
415
 
401
416
  /**
@@ -414,9 +429,9 @@ function toBuffer$2(data) {
414
429
  let buf;
415
430
 
416
431
  if (data instanceof ArrayBuffer) {
417
- buf = Buffer.from(data);
432
+ buf = new FastBuffer$2(data);
418
433
  } else if (ArrayBuffer.isView(data)) {
419
- buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
434
+ buf = new FastBuffer$2(data.buffer, data.byteOffset, data.byteLength);
420
435
  } else {
421
436
  buf = Buffer.from(data);
422
437
  toBuffer$2.readOnly = false;
@@ -425,31 +440,31 @@ function toBuffer$2(data) {
425
440
  return buf;
426
441
  }
427
442
 
428
- try {
429
- const bufferUtil = requireBufferutil();
430
- const bu = bufferUtil.BufferUtil || bufferUtil;
443
+ bufferUtil$1.exports = {
444
+ concat: concat$1,
445
+ mask: _mask,
446
+ toArrayBuffer: toArrayBuffer$1,
447
+ toBuffer: toBuffer$2,
448
+ unmask: _unmask
449
+ };
450
+
451
+ /* istanbul ignore else */
452
+ if (!process.env.WS_NO_BUFFER_UTIL) {
453
+ try {
454
+ const bufferUtil = requireBufferutil();
431
455
 
432
- bufferUtil$1.exports = {
433
- concat: concat$1,
434
- mask(source, mask, output, offset, length) {
456
+ mask = bufferUtil$1.exports.mask = function (source, mask, output, offset, length) {
435
457
  if (length < 48) _mask(source, mask, output, offset, length);
436
- else bu.mask(source, mask, output, offset, length);
437
- },
438
- toArrayBuffer: toArrayBuffer$1,
439
- toBuffer: toBuffer$2,
440
- unmask(buffer, mask) {
458
+ else bufferUtil.mask(source, mask, output, offset, length);
459
+ };
460
+
461
+ unmask$1 = bufferUtil$1.exports.unmask = function (buffer, mask) {
441
462
  if (buffer.length < 32) _unmask(buffer, mask);
442
- else bu.unmask(buffer, mask);
443
- }
444
- };
445
- } catch (e) /* istanbul ignore next */ {
446
- bufferUtil$1.exports = {
447
- concat: concat$1,
448
- mask: _mask,
449
- toArrayBuffer: toArrayBuffer$1,
450
- toBuffer: toBuffer$2,
451
- unmask: _unmask
452
- };
463
+ else bufferUtil.unmask(buffer, mask);
464
+ };
465
+ } catch (e) {
466
+ // Continue regardless of the error.
467
+ }
453
468
  }
454
469
 
455
470
  var bufferUtilExports = bufferUtil$1.exports;
@@ -512,14 +527,15 @@ const zlib = require$$0$1;
512
527
 
513
528
  const bufferUtil = bufferUtilExports;
514
529
  const Limiter = limiter;
515
- const { kStatusCode: kStatusCode$2, NOOP: NOOP$1 } = constants;
530
+ const { kStatusCode: kStatusCode$2 } = constants;
516
531
 
532
+ const FastBuffer$1 = Buffer[Symbol.species];
517
533
  const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
518
534
  const kPerMessageDeflate = Symbol('permessage-deflate');
519
535
  const kTotalLength = Symbol('total-length');
520
536
  const kCallback = Symbol('callback');
521
537
  const kBuffers = Symbol('buffers');
522
- const kError = Symbol('error');
538
+ const kError$1 = Symbol('error');
523
539
 
524
540
  //
525
541
  // We limit zlib concurrency, which prevents severe memory fragmentation
@@ -533,37 +549,37 @@ let zlibLimiter;
533
549
  /**
534
550
  * permessage-deflate implementation.
535
551
  */
536
- let PerMessageDeflate$4 = class PerMessageDeflate {
552
+ let PerMessageDeflate$3 = class PerMessageDeflate {
537
553
  /**
538
554
  * Creates a PerMessageDeflate instance.
539
555
  *
540
556
  * @param {Object} [options] Configuration options
541
- * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
542
- * disabling of server context takeover
557
+ * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
558
+ * for, or request, a custom client window size
543
559
  * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
544
560
  * acknowledge disabling of client context takeover
561
+ * @param {Number} [options.concurrencyLimit=10] The number of concurrent
562
+ * calls to zlib
563
+ * @param {Boolean} [options.isServer=false] Create the instance in either
564
+ * server or client mode
565
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
545
566
  * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
546
567
  * use of a custom server window size
547
- * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
548
- * for, or request, a custom client window size
568
+ * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
569
+ * disabling of server context takeover
570
+ * @param {Number} [options.threshold=1024] Size (in bytes) below which
571
+ * messages should not be compressed if context takeover is disabled
549
572
  * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
550
573
  * deflate
551
574
  * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
552
575
  * inflate
553
- * @param {Number} [options.threshold=1024] Size (in bytes) below which
554
- * messages should not be compressed
555
- * @param {Number} [options.concurrencyLimit=10] The number of concurrent
556
- * calls to zlib
557
- * @param {Boolean} [isServer=false] Create the instance in either server or
558
- * client mode
559
- * @param {Number} [maxPayload=0] The maximum allowed message length
560
576
  */
561
- constructor(options, isServer, maxPayload) {
562
- this._maxPayload = maxPayload | 0;
577
+ constructor(options) {
563
578
  this._options = options || {};
564
579
  this._threshold =
565
580
  this._options.threshold !== undefined ? this._options.threshold : 1024;
566
- this._isServer = !!isServer;
581
+ this._maxPayload = this._options.maxPayload | 0;
582
+ this._isServer = !!this._options.isServer;
567
583
  this._deflate = null;
568
584
  this._inflate = null;
569
585
 
@@ -821,7 +837,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
821
837
  /**
822
838
  * Compress data. Concurrency limited.
823
839
  *
824
- * @param {Buffer} data Data to compress
840
+ * @param {(Buffer|String)} data Data to compress
825
841
  * @param {Boolean} fin Specifies whether or not this is the last fragment
826
842
  * @param {Function} callback Callback
827
843
  * @public
@@ -870,7 +886,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
870
886
  if (fin) this._inflate.write(TRAILER);
871
887
 
872
888
  this._inflate.flush(() => {
873
- const err = this._inflate[kError];
889
+ const err = this._inflate[kError$1];
874
890
 
875
891
  if (err) {
876
892
  this._inflate.close();
@@ -903,7 +919,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
903
919
  /**
904
920
  * Compress data.
905
921
  *
906
- * @param {Buffer} data Data to compress
922
+ * @param {(Buffer|String)} data Data to compress
907
923
  * @param {Boolean} fin Specifies whether or not this is the last fragment
908
924
  * @param {Function} callback Callback
909
925
  * @private
@@ -926,13 +942,6 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
926
942
  this._deflate[kTotalLength] = 0;
927
943
  this._deflate[kBuffers] = [];
928
944
 
929
- //
930
- // An `'error'` event is emitted, only on Node.js < 10.0.0, if the
931
- // `zlib.DeflateRaw` instance is closed while data is being processed.
932
- // This can happen if `PerMessageDeflate#cleanup()` is called at the wrong
933
- // time due to an abnormal WebSocket closure.
934
- //
935
- this._deflate.on('error', NOOP$1);
936
945
  this._deflate.on('data', deflateOnData);
937
946
  }
938
947
 
@@ -952,7 +961,9 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
952
961
  this._deflate[kTotalLength]
953
962
  );
954
963
 
955
- if (fin) data = data.slice(0, data.length - 4);
964
+ if (fin) {
965
+ data = new FastBuffer$1(data.buffer, data.byteOffset, data.length - 4);
966
+ }
956
967
 
957
968
  //
958
969
  // Ensure that the callback will not be called again in
@@ -972,7 +983,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
972
983
  }
973
984
  };
974
985
 
975
- var permessageDeflate = PerMessageDeflate$4;
986
+ var permessageDeflate = PerMessageDeflate$3;
976
987
 
977
988
  /**
978
989
  * The listener of the `zlib.DeflateRaw` stream `'data'` event.
@@ -1002,10 +1013,18 @@ function inflateOnData(chunk) {
1002
1013
  return;
1003
1014
  }
1004
1015
 
1005
- this[kError] = new RangeError('Max payload size exceeded');
1006
- this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
1007
- this[kError][kStatusCode$2] = 1009;
1016
+ this[kError$1] = new RangeError('Max payload size exceeded');
1017
+ this[kError$1].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
1018
+ this[kError$1][kStatusCode$2] = 1009;
1008
1019
  this.removeListener('data', inflateOnData);
1020
+
1021
+ //
1022
+ // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the
1023
+ // fact that in Node.js versions prior to 13.10.0, the callback for
1024
+ // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing
1025
+ // `zlib.reset()` ensures that either the callback is invoked or an error is
1026
+ // emitted.
1027
+ //
1009
1028
  this.reset();
1010
1029
  }
1011
1030
 
@@ -1021,6 +1040,12 @@ function inflateOnError(err) {
1021
1040
  // closed when an error is emitted.
1022
1041
  //
1023
1042
  this[kPerMessageDeflate]._inflate = null;
1043
+
1044
+ if (this[kError$1]) {
1045
+ this[kCallback](this[kError$1]);
1046
+ return;
1047
+ }
1048
+
1024
1049
  err[kStatusCode$2] = 1007;
1025
1050
  this[kCallback](err);
1026
1051
  }
@@ -1113,6 +1138,35 @@ function requireUtf8Validate () {
1113
1138
  return utf8Validate.exports;
1114
1139
  }
1115
1140
 
1141
+ var isValidUTF8_1;
1142
+
1143
+ const { isUtf8 } = require$$0$2;
1144
+
1145
+ const { hasBlob } = constants;
1146
+
1147
+ //
1148
+ // Allowed token characters:
1149
+ //
1150
+ // '!', '#', '$', '%', '&', ''', '*', '+', '-',
1151
+ // '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
1152
+ //
1153
+ // tokenChars[32] === 0 // ' '
1154
+ // tokenChars[33] === 1 // '!'
1155
+ // tokenChars[34] === 0 // '"'
1156
+ // ...
1157
+ //
1158
+ // prettier-ignore
1159
+ const tokenChars$2 = [
1160
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
1161
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
1162
+ 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
1163
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
1164
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
1165
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
1166
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
1167
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
1168
+ ];
1169
+
1116
1170
  /**
1117
1171
  * Checks if a status code is allowed in a close frame.
1118
1172
  *
@@ -1195,47 +1249,71 @@ function _isValidUTF8(buf) {
1195
1249
  return true;
1196
1250
  }
1197
1251
 
1198
- try {
1199
- let isValidUTF8 = requireUtf8Validate();
1252
+ /**
1253
+ * Determines whether a value is a `Blob`.
1254
+ *
1255
+ * @param {*} value The value to be tested
1256
+ * @return {Boolean} `true` if `value` is a `Blob`, else `false`
1257
+ * @private
1258
+ */
1259
+ function isBlob$2(value) {
1260
+ return (
1261
+ hasBlob &&
1262
+ typeof value === 'object' &&
1263
+ typeof value.arrayBuffer === 'function' &&
1264
+ typeof value.type === 'string' &&
1265
+ typeof value.stream === 'function' &&
1266
+ (value[Symbol.toStringTag] === 'Blob' ||
1267
+ value[Symbol.toStringTag] === 'File')
1268
+ );
1269
+ }
1200
1270
 
1201
- /* istanbul ignore if */
1202
- if (typeof isValidUTF8 === 'object') {
1203
- isValidUTF8 = isValidUTF8.Validation.isValidUTF8; // utf-8-validate@<3.0.0
1204
- }
1271
+ validation.exports = {
1272
+ isBlob: isBlob$2,
1273
+ isValidStatusCode: isValidStatusCode$2,
1274
+ isValidUTF8: _isValidUTF8,
1275
+ tokenChars: tokenChars$2
1276
+ };
1205
1277
 
1206
- validation.exports = {
1207
- isValidStatusCode: isValidStatusCode$2,
1208
- isValidUTF8(buf) {
1209
- return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
1210
- }
1211
- };
1212
- } catch (e) /* istanbul ignore next */ {
1213
- validation.exports = {
1214
- isValidStatusCode: isValidStatusCode$2,
1215
- isValidUTF8: _isValidUTF8
1278
+ if (isUtf8) {
1279
+ isValidUTF8_1 = validation.exports.isValidUTF8 = function (buf) {
1280
+ return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
1216
1281
  };
1282
+ } /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
1283
+ try {
1284
+ const isValidUTF8 = requireUtf8Validate();
1285
+
1286
+ isValidUTF8_1 = validation.exports.isValidUTF8 = function (buf) {
1287
+ return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
1288
+ };
1289
+ } catch (e) {
1290
+ // Continue regardless of the error.
1291
+ }
1217
1292
  }
1218
1293
 
1219
1294
  var validationExports = validation.exports;
1220
1295
 
1221
- const { Writable } = require$$0$2;
1296
+ const { Writable } = require$$0$3;
1222
1297
 
1223
- const PerMessageDeflate$3 = permessageDeflate;
1298
+ const PerMessageDeflate$2 = permessageDeflate;
1224
1299
  const {
1225
1300
  BINARY_TYPES: BINARY_TYPES$1,
1226
1301
  EMPTY_BUFFER: EMPTY_BUFFER$2,
1227
1302
  kStatusCode: kStatusCode$1,
1228
- kWebSocket: kWebSocket$2
1303
+ kWebSocket: kWebSocket$3
1229
1304
  } = constants;
1230
1305
  const { concat, toArrayBuffer, unmask } = bufferUtilExports;
1231
1306
  const { isValidStatusCode: isValidStatusCode$1, isValidUTF8 } = validationExports;
1232
1307
 
1308
+ const FastBuffer = Buffer[Symbol.species];
1309
+
1233
1310
  const GET_INFO = 0;
1234
1311
  const GET_PAYLOAD_LENGTH_16 = 1;
1235
1312
  const GET_PAYLOAD_LENGTH_64 = 2;
1236
1313
  const GET_MASK = 3;
1237
1314
  const GET_DATA = 4;
1238
1315
  const INFLATING = 5;
1316
+ const DEFER_EVENT = 6;
1239
1317
 
1240
1318
  /**
1241
1319
  * HyBi Receiver implementation.
@@ -1246,20 +1324,32 @@ let Receiver$1 = class Receiver extends Writable {
1246
1324
  /**
1247
1325
  * Creates a Receiver instance.
1248
1326
  *
1249
- * @param {String} [binaryType=nodebuffer] The type for binary data
1250
- * @param {Object} [extensions] An object containing the negotiated extensions
1251
- * @param {Boolean} [isServer=false] Specifies whether to operate in client or
1252
- * server mode
1253
- * @param {Number} [maxPayload=0] The maximum allowed message length
1327
+ * @param {Object} [options] Options object
1328
+ * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
1329
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
1330
+ * multiple times in the same tick
1331
+ * @param {String} [options.binaryType=nodebuffer] The type for binary data
1332
+ * @param {Object} [options.extensions] An object containing the negotiated
1333
+ * extensions
1334
+ * @param {Boolean} [options.isServer=false] Specifies whether to operate in
1335
+ * client or server mode
1336
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
1337
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
1338
+ * not to skip UTF-8 validation for text and close messages
1254
1339
  */
1255
- constructor(binaryType, extensions, isServer, maxPayload) {
1340
+ constructor(options = {}) {
1256
1341
  super();
1257
1342
 
1258
- this._binaryType = binaryType || BINARY_TYPES$1[0];
1259
- this[kWebSocket$2] = undefined;
1260
- this._extensions = extensions || {};
1261
- this._isServer = !!isServer;
1262
- this._maxPayload = maxPayload | 0;
1343
+ this._allowSynchronousEvents =
1344
+ options.allowSynchronousEvents !== undefined
1345
+ ? options.allowSynchronousEvents
1346
+ : true;
1347
+ this._binaryType = options.binaryType || BINARY_TYPES$1[0];
1348
+ this._extensions = options.extensions || {};
1349
+ this._isServer = !!options.isServer;
1350
+ this._maxPayload = options.maxPayload | 0;
1351
+ this._skipUTF8Validation = !!options.skipUTF8Validation;
1352
+ this[kWebSocket$3] = undefined;
1263
1353
 
1264
1354
  this._bufferedBytes = 0;
1265
1355
  this._buffers = [];
@@ -1276,8 +1366,9 @@ let Receiver$1 = class Receiver extends Writable {
1276
1366
  this._messageLength = 0;
1277
1367
  this._fragments = [];
1278
1368
 
1279
- this._state = GET_INFO;
1369
+ this._errored = false;
1280
1370
  this._loop = false;
1371
+ this._state = GET_INFO;
1281
1372
  }
1282
1373
 
1283
1374
  /**
@@ -1310,8 +1401,13 @@ let Receiver$1 = class Receiver extends Writable {
1310
1401
 
1311
1402
  if (n < this._buffers[0].length) {
1312
1403
  const buf = this._buffers[0];
1313
- this._buffers[0] = buf.slice(n);
1314
- return buf.slice(0, n);
1404
+ this._buffers[0] = new FastBuffer(
1405
+ buf.buffer,
1406
+ buf.byteOffset + n,
1407
+ buf.length - n
1408
+ );
1409
+
1410
+ return new FastBuffer(buf.buffer, buf.byteOffset, n);
1315
1411
  }
1316
1412
 
1317
1413
  const dst = Buffer.allocUnsafe(n);
@@ -1324,7 +1420,11 @@ let Receiver$1 = class Receiver extends Writable {
1324
1420
  dst.set(this._buffers.shift(), offset);
1325
1421
  } else {
1326
1422
  dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
1327
- this._buffers[0] = buf.slice(n);
1423
+ this._buffers[0] = new FastBuffer(
1424
+ buf.buffer,
1425
+ buf.byteOffset + n,
1426
+ buf.length - n
1427
+ );
1328
1428
  }
1329
1429
 
1330
1430
  n -= buf.length;
@@ -1340,43 +1440,42 @@ let Receiver$1 = class Receiver extends Writable {
1340
1440
  * @private
1341
1441
  */
1342
1442
  startLoop(cb) {
1343
- let err;
1344
1443
  this._loop = true;
1345
1444
 
1346
1445
  do {
1347
1446
  switch (this._state) {
1348
1447
  case GET_INFO:
1349
- err = this.getInfo();
1448
+ this.getInfo(cb);
1350
1449
  break;
1351
1450
  case GET_PAYLOAD_LENGTH_16:
1352
- err = this.getPayloadLength16();
1451
+ this.getPayloadLength16(cb);
1353
1452
  break;
1354
1453
  case GET_PAYLOAD_LENGTH_64:
1355
- err = this.getPayloadLength64();
1454
+ this.getPayloadLength64(cb);
1356
1455
  break;
1357
1456
  case GET_MASK:
1358
1457
  this.getMask();
1359
1458
  break;
1360
1459
  case GET_DATA:
1361
- err = this.getData(cb);
1460
+ this.getData(cb);
1362
1461
  break;
1363
- default:
1364
- // `INFLATING`
1462
+ case INFLATING:
1463
+ case DEFER_EVENT:
1365
1464
  this._loop = false;
1366
1465
  return;
1367
1466
  }
1368
1467
  } while (this._loop);
1369
1468
 
1370
- cb(err);
1469
+ if (!this._errored) cb();
1371
1470
  }
1372
1471
 
1373
1472
  /**
1374
1473
  * Reads the first two bytes of a frame.
1375
1474
  *
1376
- * @return {(RangeError|undefined)} A possible error
1475
+ * @param {Function} cb Callback
1377
1476
  * @private
1378
1477
  */
1379
- getInfo() {
1478
+ getInfo(cb) {
1380
1479
  if (this._bufferedBytes < 2) {
1381
1480
  this._loop = false;
1382
1481
  return;
@@ -1385,27 +1484,31 @@ let Receiver$1 = class Receiver extends Writable {
1385
1484
  const buf = this.consume(2);
1386
1485
 
1387
1486
  if ((buf[0] & 0x30) !== 0x00) {
1388
- this._loop = false;
1389
- return error(
1487
+ const error = this.createError(
1390
1488
  RangeError,
1391
1489
  'RSV2 and RSV3 must be clear',
1392
1490
  true,
1393
1491
  1002,
1394
1492
  'WS_ERR_UNEXPECTED_RSV_2_3'
1395
1493
  );
1494
+
1495
+ cb(error);
1496
+ return;
1396
1497
  }
1397
1498
 
1398
1499
  const compressed = (buf[0] & 0x40) === 0x40;
1399
1500
 
1400
- if (compressed && !this._extensions[PerMessageDeflate$3.extensionName]) {
1401
- this._loop = false;
1402
- return error(
1501
+ if (compressed && !this._extensions[PerMessageDeflate$2.extensionName]) {
1502
+ const error = this.createError(
1403
1503
  RangeError,
1404
1504
  'RSV1 must be clear',
1405
1505
  true,
1406
1506
  1002,
1407
1507
  'WS_ERR_UNEXPECTED_RSV_1'
1408
1508
  );
1509
+
1510
+ cb(error);
1511
+ return;
1409
1512
  }
1410
1513
 
1411
1514
  this._fin = (buf[0] & 0x80) === 0x80;
@@ -1414,83 +1517,100 @@ let Receiver$1 = class Receiver extends Writable {
1414
1517
 
1415
1518
  if (this._opcode === 0x00) {
1416
1519
  if (compressed) {
1417
- this._loop = false;
1418
- return error(
1520
+ const error = this.createError(
1419
1521
  RangeError,
1420
1522
  'RSV1 must be clear',
1421
1523
  true,
1422
1524
  1002,
1423
1525
  'WS_ERR_UNEXPECTED_RSV_1'
1424
1526
  );
1527
+
1528
+ cb(error);
1529
+ return;
1425
1530
  }
1426
1531
 
1427
1532
  if (!this._fragmented) {
1428
- this._loop = false;
1429
- return error(
1533
+ const error = this.createError(
1430
1534
  RangeError,
1431
1535
  'invalid opcode 0',
1432
1536
  true,
1433
1537
  1002,
1434
1538
  'WS_ERR_INVALID_OPCODE'
1435
1539
  );
1540
+
1541
+ cb(error);
1542
+ return;
1436
1543
  }
1437
1544
 
1438
1545
  this._opcode = this._fragmented;
1439
1546
  } else if (this._opcode === 0x01 || this._opcode === 0x02) {
1440
1547
  if (this._fragmented) {
1441
- this._loop = false;
1442
- return error(
1548
+ const error = this.createError(
1443
1549
  RangeError,
1444
1550
  `invalid opcode ${this._opcode}`,
1445
1551
  true,
1446
1552
  1002,
1447
1553
  'WS_ERR_INVALID_OPCODE'
1448
1554
  );
1555
+
1556
+ cb(error);
1557
+ return;
1449
1558
  }
1450
1559
 
1451
1560
  this._compressed = compressed;
1452
1561
  } else if (this._opcode > 0x07 && this._opcode < 0x0b) {
1453
1562
  if (!this._fin) {
1454
- this._loop = false;
1455
- return error(
1563
+ const error = this.createError(
1456
1564
  RangeError,
1457
1565
  'FIN must be set',
1458
1566
  true,
1459
1567
  1002,
1460
1568
  'WS_ERR_EXPECTED_FIN'
1461
1569
  );
1570
+
1571
+ cb(error);
1572
+ return;
1462
1573
  }
1463
1574
 
1464
1575
  if (compressed) {
1465
- this._loop = false;
1466
- return error(
1576
+ const error = this.createError(
1467
1577
  RangeError,
1468
1578
  'RSV1 must be clear',
1469
1579
  true,
1470
1580
  1002,
1471
1581
  'WS_ERR_UNEXPECTED_RSV_1'
1472
1582
  );
1583
+
1584
+ cb(error);
1585
+ return;
1473
1586
  }
1474
1587
 
1475
- if (this._payloadLength > 0x7d) {
1476
- this._loop = false;
1477
- return error(
1588
+ if (
1589
+ this._payloadLength > 0x7d ||
1590
+ (this._opcode === 0x08 && this._payloadLength === 1)
1591
+ ) {
1592
+ const error = this.createError(
1478
1593
  RangeError,
1479
1594
  `invalid payload length ${this._payloadLength}`,
1480
1595
  true,
1481
1596
  1002,
1482
1597
  'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
1483
1598
  );
1599
+
1600
+ cb(error);
1601
+ return;
1484
1602
  }
1485
1603
  } else {
1486
- this._loop = false;
1487
- return error(
1604
+ const error = this.createError(
1488
1605
  RangeError,
1489
1606
  `invalid opcode ${this._opcode}`,
1490
1607
  true,
1491
1608
  1002,
1492
1609
  'WS_ERR_INVALID_OPCODE'
1493
1610
  );
1611
+
1612
+ cb(error);
1613
+ return;
1494
1614
  }
1495
1615
 
1496
1616
  if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
@@ -1498,54 +1618,58 @@ let Receiver$1 = class Receiver extends Writable {
1498
1618
 
1499
1619
  if (this._isServer) {
1500
1620
  if (!this._masked) {
1501
- this._loop = false;
1502
- return error(
1621
+ const error = this.createError(
1503
1622
  RangeError,
1504
1623
  'MASK must be set',
1505
1624
  true,
1506
1625
  1002,
1507
1626
  'WS_ERR_EXPECTED_MASK'
1508
1627
  );
1628
+
1629
+ cb(error);
1630
+ return;
1509
1631
  }
1510
1632
  } else if (this._masked) {
1511
- this._loop = false;
1512
- return error(
1633
+ const error = this.createError(
1513
1634
  RangeError,
1514
1635
  'MASK must be clear',
1515
1636
  true,
1516
1637
  1002,
1517
1638
  'WS_ERR_UNEXPECTED_MASK'
1518
1639
  );
1640
+
1641
+ cb(error);
1642
+ return;
1519
1643
  }
1520
1644
 
1521
1645
  if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
1522
1646
  else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
1523
- else return this.haveLength();
1647
+ else this.haveLength(cb);
1524
1648
  }
1525
1649
 
1526
1650
  /**
1527
1651
  * Gets extended payload length (7+16).
1528
1652
  *
1529
- * @return {(RangeError|undefined)} A possible error
1653
+ * @param {Function} cb Callback
1530
1654
  * @private
1531
1655
  */
1532
- getPayloadLength16() {
1656
+ getPayloadLength16(cb) {
1533
1657
  if (this._bufferedBytes < 2) {
1534
1658
  this._loop = false;
1535
1659
  return;
1536
1660
  }
1537
1661
 
1538
1662
  this._payloadLength = this.consume(2).readUInt16BE(0);
1539
- return this.haveLength();
1663
+ this.haveLength(cb);
1540
1664
  }
1541
1665
 
1542
1666
  /**
1543
1667
  * Gets extended payload length (7+64).
1544
1668
  *
1545
- * @return {(RangeError|undefined)} A possible error
1669
+ * @param {Function} cb Callback
1546
1670
  * @private
1547
1671
  */
1548
- getPayloadLength64() {
1672
+ getPayloadLength64(cb) {
1549
1673
  if (this._bufferedBytes < 8) {
1550
1674
  this._loop = false;
1551
1675
  return;
@@ -1559,38 +1683,42 @@ let Receiver$1 = class Receiver extends Writable {
1559
1683
  // if payload length is greater than this number.
1560
1684
  //
1561
1685
  if (num > Math.pow(2, 53 - 32) - 1) {
1562
- this._loop = false;
1563
- return error(
1686
+ const error = this.createError(
1564
1687
  RangeError,
1565
1688
  'Unsupported WebSocket frame: payload length > 2^53 - 1',
1566
1689
  false,
1567
1690
  1009,
1568
1691
  'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
1569
1692
  );
1693
+
1694
+ cb(error);
1695
+ return;
1570
1696
  }
1571
1697
 
1572
1698
  this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
1573
- return this.haveLength();
1699
+ this.haveLength(cb);
1574
1700
  }
1575
1701
 
1576
1702
  /**
1577
1703
  * Payload length has been read.
1578
1704
  *
1579
- * @return {(RangeError|undefined)} A possible error
1705
+ * @param {Function} cb Callback
1580
1706
  * @private
1581
1707
  */
1582
- haveLength() {
1708
+ haveLength(cb) {
1583
1709
  if (this._payloadLength && this._opcode < 0x08) {
1584
1710
  this._totalPayloadLength += this._payloadLength;
1585
1711
  if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
1586
- this._loop = false;
1587
- return error(
1712
+ const error = this.createError(
1588
1713
  RangeError,
1589
1714
  'Max payload size exceeded',
1590
1715
  false,
1591
1716
  1009,
1592
1717
  'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
1593
1718
  );
1719
+
1720
+ cb(error);
1721
+ return;
1594
1722
  }
1595
1723
  }
1596
1724
 
@@ -1617,7 +1745,6 @@ let Receiver$1 = class Receiver extends Writable {
1617
1745
  * Reads data bytes.
1618
1746
  *
1619
1747
  * @param {Function} cb Callback
1620
- * @return {(Error|RangeError|undefined)} A possible error
1621
1748
  * @private
1622
1749
  */
1623
1750
  getData(cb) {
@@ -1630,10 +1757,19 @@ let Receiver$1 = class Receiver extends Writable {
1630
1757
  }
1631
1758
 
1632
1759
  data = this.consume(this._payloadLength);
1633
- if (this._masked) unmask(data, this._mask);
1760
+
1761
+ if (
1762
+ this._masked &&
1763
+ (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0
1764
+ ) {
1765
+ unmask(data, this._mask);
1766
+ }
1634
1767
  }
1635
1768
 
1636
- if (this._opcode > 0x07) return this.controlMessage(data);
1769
+ if (this._opcode > 0x07) {
1770
+ this.controlMessage(data, cb);
1771
+ return;
1772
+ }
1637
1773
 
1638
1774
  if (this._compressed) {
1639
1775
  this._state = INFLATING;
@@ -1643,14 +1779,14 @@ let Receiver$1 = class Receiver extends Writable {
1643
1779
 
1644
1780
  if (data.length) {
1645
1781
  //
1646
- // This message is not compressed so its lenght is the sum of the payload
1782
+ // This message is not compressed so its length is the sum of the payload
1647
1783
  // length of all fragments.
1648
1784
  //
1649
1785
  this._messageLength = this._totalPayloadLength;
1650
1786
  this._fragments.push(data);
1651
1787
  }
1652
1788
 
1653
- return this.dataMessage();
1789
+ this.dataMessage(cb);
1654
1790
  }
1655
1791
 
1656
1792
  /**
@@ -1661,7 +1797,7 @@ let Receiver$1 = class Receiver extends Writable {
1661
1797
  * @private
1662
1798
  */
1663
1799
  decompress(data, cb) {
1664
- const perMessageDeflate = this._extensions[PerMessageDeflate$3.extensionName];
1800
+ const perMessageDeflate = this._extensions[PerMessageDeflate$2.extensionName];
1665
1801
 
1666
1802
  perMessageDeflate.decompress(data, this._fin, (err, buf) => {
1667
1803
  if (err) return cb(err);
@@ -1669,74 +1805,98 @@ let Receiver$1 = class Receiver extends Writable {
1669
1805
  if (buf.length) {
1670
1806
  this._messageLength += buf.length;
1671
1807
  if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
1672
- return cb(
1673
- error(
1674
- RangeError,
1675
- 'Max payload size exceeded',
1676
- false,
1677
- 1009,
1678
- 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
1679
- )
1808
+ const error = this.createError(
1809
+ RangeError,
1810
+ 'Max payload size exceeded',
1811
+ false,
1812
+ 1009,
1813
+ 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
1680
1814
  );
1815
+
1816
+ cb(error);
1817
+ return;
1681
1818
  }
1682
1819
 
1683
1820
  this._fragments.push(buf);
1684
1821
  }
1685
1822
 
1686
- const er = this.dataMessage();
1687
- if (er) return cb(er);
1688
-
1689
- this.startLoop(cb);
1823
+ this.dataMessage(cb);
1824
+ if (this._state === GET_INFO) this.startLoop(cb);
1690
1825
  });
1691
1826
  }
1692
1827
 
1693
1828
  /**
1694
1829
  * Handles a data message.
1695
1830
  *
1696
- * @return {(Error|undefined)} A possible error
1831
+ * @param {Function} cb Callback
1697
1832
  * @private
1698
1833
  */
1699
- dataMessage() {
1700
- if (this._fin) {
1701
- const messageLength = this._messageLength;
1702
- const fragments = this._fragments;
1703
-
1704
- this._totalPayloadLength = 0;
1705
- this._messageLength = 0;
1706
- this._fragmented = 0;
1707
- this._fragments = [];
1708
-
1709
- if (this._opcode === 2) {
1710
- let data;
1711
-
1712
- if (this._binaryType === 'nodebuffer') {
1713
- data = concat(fragments, messageLength);
1714
- } else if (this._binaryType === 'arraybuffer') {
1715
- data = toArrayBuffer(concat(fragments, messageLength));
1716
- } else {
1717
- data = fragments;
1718
- }
1834
+ dataMessage(cb) {
1835
+ if (!this._fin) {
1836
+ this._state = GET_INFO;
1837
+ return;
1838
+ }
1839
+
1840
+ const messageLength = this._messageLength;
1841
+ const fragments = this._fragments;
1842
+
1843
+ this._totalPayloadLength = 0;
1844
+ this._messageLength = 0;
1845
+ this._fragmented = 0;
1846
+ this._fragments = [];
1719
1847
 
1720
- this.emit('message', data);
1848
+ if (this._opcode === 2) {
1849
+ let data;
1850
+
1851
+ if (this._binaryType === 'nodebuffer') {
1852
+ data = concat(fragments, messageLength);
1853
+ } else if (this._binaryType === 'arraybuffer') {
1854
+ data = toArrayBuffer(concat(fragments, messageLength));
1855
+ } else if (this._binaryType === 'blob') {
1856
+ data = new Blob(fragments);
1721
1857
  } else {
1722
- const buf = concat(fragments, messageLength);
1858
+ data = fragments;
1859
+ }
1723
1860
 
1724
- if (!isValidUTF8(buf)) {
1725
- this._loop = false;
1726
- return error(
1727
- Error,
1728
- 'invalid UTF-8 sequence',
1729
- true,
1730
- 1007,
1731
- 'WS_ERR_INVALID_UTF8'
1732
- );
1733
- }
1861
+ if (this._allowSynchronousEvents) {
1862
+ this.emit('message', data, true);
1863
+ this._state = GET_INFO;
1864
+ } else {
1865
+ this._state = DEFER_EVENT;
1866
+ setImmediate(() => {
1867
+ this.emit('message', data, true);
1868
+ this._state = GET_INFO;
1869
+ this.startLoop(cb);
1870
+ });
1871
+ }
1872
+ } else {
1873
+ const buf = concat(fragments, messageLength);
1734
1874
 
1735
- this.emit('message', buf.toString());
1875
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1876
+ const error = this.createError(
1877
+ Error,
1878
+ 'invalid UTF-8 sequence',
1879
+ true,
1880
+ 1007,
1881
+ 'WS_ERR_INVALID_UTF8'
1882
+ );
1883
+
1884
+ cb(error);
1885
+ return;
1736
1886
  }
1737
- }
1738
1887
 
1739
- this._state = GET_INFO;
1888
+ if (this._state === INFLATING || this._allowSynchronousEvents) {
1889
+ this.emit('message', buf, false);
1890
+ this._state = GET_INFO;
1891
+ } else {
1892
+ this._state = DEFER_EVENT;
1893
+ setImmediate(() => {
1894
+ this.emit('message', buf, false);
1895
+ this._state = GET_INFO;
1896
+ this.startLoop(cb);
1897
+ });
1898
+ }
1899
+ }
1740
1900
  }
1741
1901
 
1742
1902
  /**
@@ -1746,93 +1906,117 @@ let Receiver$1 = class Receiver extends Writable {
1746
1906
  * @return {(Error|RangeError|undefined)} A possible error
1747
1907
  * @private
1748
1908
  */
1749
- controlMessage(data) {
1909
+ controlMessage(data, cb) {
1750
1910
  if (this._opcode === 0x08) {
1751
- this._loop = false;
1752
-
1753
1911
  if (data.length === 0) {
1754
- this.emit('conclude', 1005, '');
1912
+ this._loop = false;
1913
+ this.emit('conclude', 1005, EMPTY_BUFFER$2);
1755
1914
  this.end();
1756
- } else if (data.length === 1) {
1757
- return error(
1758
- RangeError,
1759
- 'invalid payload length 1',
1760
- true,
1761
- 1002,
1762
- 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
1763
- );
1764
1915
  } else {
1765
1916
  const code = data.readUInt16BE(0);
1766
1917
 
1767
1918
  if (!isValidStatusCode$1(code)) {
1768
- return error(
1919
+ const error = this.createError(
1769
1920
  RangeError,
1770
1921
  `invalid status code ${code}`,
1771
1922
  true,
1772
1923
  1002,
1773
1924
  'WS_ERR_INVALID_CLOSE_CODE'
1774
1925
  );
1926
+
1927
+ cb(error);
1928
+ return;
1775
1929
  }
1776
1930
 
1777
- const buf = data.slice(2);
1931
+ const buf = new FastBuffer(
1932
+ data.buffer,
1933
+ data.byteOffset + 2,
1934
+ data.length - 2
1935
+ );
1778
1936
 
1779
- if (!isValidUTF8(buf)) {
1780
- return error(
1937
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1938
+ const error = this.createError(
1781
1939
  Error,
1782
1940
  'invalid UTF-8 sequence',
1783
1941
  true,
1784
1942
  1007,
1785
1943
  'WS_ERR_INVALID_UTF8'
1786
1944
  );
1945
+
1946
+ cb(error);
1947
+ return;
1787
1948
  }
1788
1949
 
1789
- this.emit('conclude', code, buf.toString());
1950
+ this._loop = false;
1951
+ this.emit('conclude', code, buf);
1790
1952
  this.end();
1791
1953
  }
1792
- } else if (this._opcode === 0x09) {
1793
- this.emit('ping', data);
1954
+
1955
+ this._state = GET_INFO;
1956
+ return;
1957
+ }
1958
+
1959
+ if (this._allowSynchronousEvents) {
1960
+ this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
1961
+ this._state = GET_INFO;
1794
1962
  } else {
1795
- this.emit('pong', data);
1963
+ this._state = DEFER_EVENT;
1964
+ setImmediate(() => {
1965
+ this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
1966
+ this._state = GET_INFO;
1967
+ this.startLoop(cb);
1968
+ });
1796
1969
  }
1970
+ }
1797
1971
 
1798
- this._state = GET_INFO;
1972
+ /**
1973
+ * Builds an error object.
1974
+ *
1975
+ * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
1976
+ * @param {String} message The error message
1977
+ * @param {Boolean} prefix Specifies whether or not to add a default prefix to
1978
+ * `message`
1979
+ * @param {Number} statusCode The status code
1980
+ * @param {String} errorCode The exposed error code
1981
+ * @return {(Error|RangeError)} The error
1982
+ * @private
1983
+ */
1984
+ createError(ErrorCtor, message, prefix, statusCode, errorCode) {
1985
+ this._loop = false;
1986
+ this._errored = true;
1987
+
1988
+ const err = new ErrorCtor(
1989
+ prefix ? `Invalid WebSocket frame: ${message}` : message
1990
+ );
1991
+
1992
+ Error.captureStackTrace(err, this.createError);
1993
+ err.code = errorCode;
1994
+ err[kStatusCode$1] = statusCode;
1995
+ return err;
1799
1996
  }
1800
1997
  };
1801
1998
 
1802
1999
  var receiver = Receiver$1;
1803
2000
 
1804
- /**
1805
- * Builds an error object.
1806
- *
1807
- * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
1808
- * @param {String} message The error message
1809
- * @param {Boolean} prefix Specifies whether or not to add a default prefix to
1810
- * `message`
1811
- * @param {Number} statusCode The status code
1812
- * @param {String} errorCode The exposed error code
1813
- * @return {(Error|RangeError)} The error
1814
- * @private
1815
- */
1816
- function error(ErrorCtor, message, prefix, statusCode, errorCode) {
1817
- const err = new ErrorCtor(
1818
- prefix ? `Invalid WebSocket frame: ${message}` : message
1819
- );
1820
-
1821
- Error.captureStackTrace(err, error);
1822
- err.code = errorCode;
1823
- err[kStatusCode$1] = statusCode;
1824
- return err;
1825
- }
2001
+ /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex" }] */
1826
2002
 
1827
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls$" }] */
1828
- const { randomFillSync } = require$$5;
2003
+ const { Duplex: Duplex$3 } = require$$0$3;
2004
+ const { randomFillSync } = require$$1$1;
1829
2005
 
1830
- const PerMessageDeflate$2 = permessageDeflate;
1831
- const { EMPTY_BUFFER: EMPTY_BUFFER$1 } = constants;
1832
- const { isValidStatusCode } = validationExports;
2006
+ const PerMessageDeflate$1 = permessageDeflate;
2007
+ const { EMPTY_BUFFER: EMPTY_BUFFER$1, kWebSocket: kWebSocket$2, NOOP: NOOP$1 } = constants;
2008
+ const { isBlob: isBlob$1, isValidStatusCode } = validationExports;
1833
2009
  const { mask: applyMask, toBuffer: toBuffer$1 } = bufferUtilExports;
1834
2010
 
1835
- const mask = Buffer.alloc(4);
2011
+ const kByteLength = Symbol('kByteLength');
2012
+ const maskBuffer = Buffer.alloc(4);
2013
+ const RANDOM_POOL_SIZE = 8 * 1024;
2014
+ let randomPool;
2015
+ let randomPoolPointer = RANDOM_POOL_SIZE;
2016
+
2017
+ const DEFAULT = 0;
2018
+ const DEFLATING = 1;
2019
+ const GET_BLOB_DATA = 2;
1836
2020
 
1837
2021
  /**
1838
2022
  * HyBi Sender implementation.
@@ -1841,52 +2025,116 @@ let Sender$1 = class Sender {
1841
2025
  /**
1842
2026
  * Creates a Sender instance.
1843
2027
  *
1844
- * @param {(net.Socket|tls.Socket)} socket The connection socket
2028
+ * @param {Duplex} socket The connection socket
1845
2029
  * @param {Object} [extensions] An object containing the negotiated extensions
2030
+ * @param {Function} [generateMask] The function used to generate the masking
2031
+ * key
1846
2032
  */
1847
- constructor(socket, extensions) {
2033
+ constructor(socket, extensions, generateMask) {
1848
2034
  this._extensions = extensions || {};
2035
+
2036
+ if (generateMask) {
2037
+ this._generateMask = generateMask;
2038
+ this._maskBuffer = Buffer.alloc(4);
2039
+ }
2040
+
1849
2041
  this._socket = socket;
1850
2042
 
1851
2043
  this._firstFragment = true;
1852
2044
  this._compress = false;
1853
2045
 
1854
2046
  this._bufferedBytes = 0;
1855
- this._deflating = false;
1856
2047
  this._queue = [];
2048
+ this._state = DEFAULT;
2049
+ this.onerror = NOOP$1;
2050
+ this[kWebSocket$2] = undefined;
1857
2051
  }
1858
2052
 
1859
2053
  /**
1860
2054
  * Frames a piece of data according to the HyBi WebSocket protocol.
1861
2055
  *
1862
- * @param {Buffer} data The data to frame
2056
+ * @param {(Buffer|String)} data The data to frame
1863
2057
  * @param {Object} options Options object
1864
- * @param {Number} options.opcode The opcode
1865
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1866
- * modified
1867
2058
  * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1868
2059
  * FIN bit
2060
+ * @param {Function} [options.generateMask] The function used to generate the
2061
+ * masking key
1869
2062
  * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1870
2063
  * `data`
2064
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
2065
+ * key
2066
+ * @param {Number} options.opcode The opcode
2067
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
2068
+ * modified
1871
2069
  * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1872
2070
  * RSV1 bit
1873
- * @return {Buffer[]} The framed data as a list of `Buffer` instances
2071
+ * @return {(Buffer|String)[]} The framed data
1874
2072
  * @public
1875
2073
  */
1876
2074
  static frame(data, options) {
1877
- const merge = options.mask && options.readOnly;
1878
- let offset = options.mask ? 6 : 2;
1879
- let payloadLength = data.length;
2075
+ let mask;
2076
+ let merge = false;
2077
+ let offset = 2;
2078
+ let skipMasking = false;
2079
+
2080
+ if (options.mask) {
2081
+ mask = options.maskBuffer || maskBuffer;
2082
+
2083
+ if (options.generateMask) {
2084
+ options.generateMask(mask);
2085
+ } else {
2086
+ if (randomPoolPointer === RANDOM_POOL_SIZE) {
2087
+ /* istanbul ignore else */
2088
+ if (randomPool === undefined) {
2089
+ //
2090
+ // This is lazily initialized because server-sent frames must not
2091
+ // be masked so it may never be used.
2092
+ //
2093
+ randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
2094
+ }
1880
2095
 
1881
- if (data.length >= 65536) {
2096
+ randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
2097
+ randomPoolPointer = 0;
2098
+ }
2099
+
2100
+ mask[0] = randomPool[randomPoolPointer++];
2101
+ mask[1] = randomPool[randomPoolPointer++];
2102
+ mask[2] = randomPool[randomPoolPointer++];
2103
+ mask[3] = randomPool[randomPoolPointer++];
2104
+ }
2105
+
2106
+ skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
2107
+ offset = 6;
2108
+ }
2109
+
2110
+ let dataLength;
2111
+
2112
+ if (typeof data === 'string') {
2113
+ if (
2114
+ (!options.mask || skipMasking) &&
2115
+ options[kByteLength] !== undefined
2116
+ ) {
2117
+ dataLength = options[kByteLength];
2118
+ } else {
2119
+ data = Buffer.from(data);
2120
+ dataLength = data.length;
2121
+ }
2122
+ } else {
2123
+ dataLength = data.length;
2124
+ merge = options.mask && options.readOnly && !skipMasking;
2125
+ }
2126
+
2127
+ let payloadLength = dataLength;
2128
+
2129
+ if (dataLength >= 65536) {
1882
2130
  offset += 8;
1883
2131
  payloadLength = 127;
1884
- } else if (data.length > 125) {
2132
+ } else if (dataLength > 125) {
1885
2133
  offset += 2;
1886
2134
  payloadLength = 126;
1887
2135
  }
1888
2136
 
1889
- const target = Buffer.allocUnsafe(merge ? data.length + offset : offset);
2137
+ const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
1890
2138
 
1891
2139
  target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
1892
2140
  if (options.rsv1) target[0] |= 0x40;
@@ -1894,28 +2142,28 @@ let Sender$1 = class Sender {
1894
2142
  target[1] = payloadLength;
1895
2143
 
1896
2144
  if (payloadLength === 126) {
1897
- target.writeUInt16BE(data.length, 2);
2145
+ target.writeUInt16BE(dataLength, 2);
1898
2146
  } else if (payloadLength === 127) {
1899
- target.writeUInt32BE(0, 2);
1900
- target.writeUInt32BE(data.length, 6);
2147
+ target[2] = target[3] = 0;
2148
+ target.writeUIntBE(dataLength, 4, 6);
1901
2149
  }
1902
2150
 
1903
2151
  if (!options.mask) return [target, data];
1904
2152
 
1905
- randomFillSync(mask, 0, 4);
1906
-
1907
2153
  target[1] |= 0x80;
1908
2154
  target[offset - 4] = mask[0];
1909
2155
  target[offset - 3] = mask[1];
1910
2156
  target[offset - 2] = mask[2];
1911
2157
  target[offset - 1] = mask[3];
1912
2158
 
2159
+ if (skipMasking) return [target, data];
2160
+
1913
2161
  if (merge) {
1914
- applyMask(data, mask, target, offset, data.length);
2162
+ applyMask(data, mask, target, offset, dataLength);
1915
2163
  return [target];
1916
2164
  }
1917
2165
 
1918
- applyMask(data, mask, data, 0, data.length);
2166
+ applyMask(data, mask, data, 0, dataLength);
1919
2167
  return [target, data];
1920
2168
  }
1921
2169
 
@@ -1923,7 +2171,7 @@ let Sender$1 = class Sender {
1923
2171
  * Sends a close message to the other peer.
1924
2172
  *
1925
2173
  * @param {Number} [code] The status code component of the body
1926
- * @param {String} [data] The message component of the body
2174
+ * @param {(String|Buffer)} [data] The message component of the body
1927
2175
  * @param {Boolean} [mask=false] Specifies whether or not to mask the message
1928
2176
  * @param {Function} [cb] Callback
1929
2177
  * @public
@@ -1935,7 +2183,7 @@ let Sender$1 = class Sender {
1935
2183
  buf = EMPTY_BUFFER$1;
1936
2184
  } else if (typeof code !== 'number' || !isValidStatusCode(code)) {
1937
2185
  throw new TypeError('First argument must be a valid error code number');
1938
- } else if (data === undefined || data === '') {
2186
+ } else if (data === undefined || !data.length) {
1939
2187
  buf = Buffer.allocUnsafe(2);
1940
2188
  buf.writeUInt16BE(code, 0);
1941
2189
  } else {
@@ -1947,37 +2195,32 @@ let Sender$1 = class Sender {
1947
2195
 
1948
2196
  buf = Buffer.allocUnsafe(2 + length);
1949
2197
  buf.writeUInt16BE(code, 0);
1950
- buf.write(data, 2);
2198
+
2199
+ if (typeof data === 'string') {
2200
+ buf.write(data, 2);
2201
+ } else {
2202
+ buf.set(data, 2);
2203
+ }
1951
2204
  }
1952
2205
 
1953
- if (this._deflating) {
1954
- this.enqueue([this.doClose, buf, mask, cb]);
2206
+ const options = {
2207
+ [kByteLength]: buf.length,
2208
+ fin: true,
2209
+ generateMask: this._generateMask,
2210
+ mask,
2211
+ maskBuffer: this._maskBuffer,
2212
+ opcode: 0x08,
2213
+ readOnly: false,
2214
+ rsv1: false
2215
+ };
2216
+
2217
+ if (this._state !== DEFAULT) {
2218
+ this.enqueue([this.dispatch, buf, false, options, cb]);
1955
2219
  } else {
1956
- this.doClose(buf, mask, cb);
2220
+ this.sendFrame(Sender.frame(buf, options), cb);
1957
2221
  }
1958
2222
  }
1959
2223
 
1960
- /**
1961
- * Frames and sends a close message.
1962
- *
1963
- * @param {Buffer} data The message to send
1964
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1965
- * @param {Function} [cb] Callback
1966
- * @private
1967
- */
1968
- doClose(data, mask, cb) {
1969
- this.sendFrame(
1970
- Sender.frame(data, {
1971
- fin: true,
1972
- rsv1: false,
1973
- opcode: 0x08,
1974
- mask,
1975
- readOnly: false
1976
- }),
1977
- cb
1978
- );
1979
- }
1980
-
1981
2224
  /**
1982
2225
  * Sends a ping message to the other peer.
1983
2226
  *
@@ -1987,41 +2230,49 @@ let Sender$1 = class Sender {
1987
2230
  * @public
1988
2231
  */
1989
2232
  ping(data, mask, cb) {
1990
- const buf = toBuffer$1(data);
2233
+ let byteLength;
2234
+ let readOnly;
2235
+
2236
+ if (typeof data === 'string') {
2237
+ byteLength = Buffer.byteLength(data);
2238
+ readOnly = false;
2239
+ } else if (isBlob$1(data)) {
2240
+ byteLength = data.size;
2241
+ readOnly = false;
2242
+ } else {
2243
+ data = toBuffer$1(data);
2244
+ byteLength = data.length;
2245
+ readOnly = toBuffer$1.readOnly;
2246
+ }
1991
2247
 
1992
- if (buf.length > 125) {
2248
+ if (byteLength > 125) {
1993
2249
  throw new RangeError('The data size must not be greater than 125 bytes');
1994
2250
  }
1995
2251
 
1996
- if (this._deflating) {
1997
- this.enqueue([this.doPing, buf, mask, toBuffer$1.readOnly, cb]);
2252
+ const options = {
2253
+ [kByteLength]: byteLength,
2254
+ fin: true,
2255
+ generateMask: this._generateMask,
2256
+ mask,
2257
+ maskBuffer: this._maskBuffer,
2258
+ opcode: 0x09,
2259
+ readOnly,
2260
+ rsv1: false
2261
+ };
2262
+
2263
+ if (isBlob$1(data)) {
2264
+ if (this._state !== DEFAULT) {
2265
+ this.enqueue([this.getBlobData, data, false, options, cb]);
2266
+ } else {
2267
+ this.getBlobData(data, false, options, cb);
2268
+ }
2269
+ } else if (this._state !== DEFAULT) {
2270
+ this.enqueue([this.dispatch, data, false, options, cb]);
1998
2271
  } else {
1999
- this.doPing(buf, mask, toBuffer$1.readOnly, cb);
2272
+ this.sendFrame(Sender.frame(data, options), cb);
2000
2273
  }
2001
2274
  }
2002
2275
 
2003
- /**
2004
- * Frames and sends a ping message.
2005
- *
2006
- * @param {Buffer} data The message to send
2007
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
2008
- * @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
2009
- * @param {Function} [cb] Callback
2010
- * @private
2011
- */
2012
- doPing(data, mask, readOnly, cb) {
2013
- this.sendFrame(
2014
- Sender.frame(data, {
2015
- fin: true,
2016
- rsv1: false,
2017
- opcode: 0x09,
2018
- mask,
2019
- readOnly
2020
- }),
2021
- cb
2022
- );
2023
- }
2024
-
2025
2276
  /**
2026
2277
  * Sends a pong message to the other peer.
2027
2278
  *
@@ -2031,50 +2282,58 @@ let Sender$1 = class Sender {
2031
2282
  * @public
2032
2283
  */
2033
2284
  pong(data, mask, cb) {
2034
- const buf = toBuffer$1(data);
2285
+ let byteLength;
2286
+ let readOnly;
2287
+
2288
+ if (typeof data === 'string') {
2289
+ byteLength = Buffer.byteLength(data);
2290
+ readOnly = false;
2291
+ } else if (isBlob$1(data)) {
2292
+ byteLength = data.size;
2293
+ readOnly = false;
2294
+ } else {
2295
+ data = toBuffer$1(data);
2296
+ byteLength = data.length;
2297
+ readOnly = toBuffer$1.readOnly;
2298
+ }
2035
2299
 
2036
- if (buf.length > 125) {
2300
+ if (byteLength > 125) {
2037
2301
  throw new RangeError('The data size must not be greater than 125 bytes');
2038
2302
  }
2039
2303
 
2040
- if (this._deflating) {
2041
- this.enqueue([this.doPong, buf, mask, toBuffer$1.readOnly, cb]);
2304
+ const options = {
2305
+ [kByteLength]: byteLength,
2306
+ fin: true,
2307
+ generateMask: this._generateMask,
2308
+ mask,
2309
+ maskBuffer: this._maskBuffer,
2310
+ opcode: 0x0a,
2311
+ readOnly,
2312
+ rsv1: false
2313
+ };
2314
+
2315
+ if (isBlob$1(data)) {
2316
+ if (this._state !== DEFAULT) {
2317
+ this.enqueue([this.getBlobData, data, false, options, cb]);
2318
+ } else {
2319
+ this.getBlobData(data, false, options, cb);
2320
+ }
2321
+ } else if (this._state !== DEFAULT) {
2322
+ this.enqueue([this.dispatch, data, false, options, cb]);
2042
2323
  } else {
2043
- this.doPong(buf, mask, toBuffer$1.readOnly, cb);
2324
+ this.sendFrame(Sender.frame(data, options), cb);
2044
2325
  }
2045
2326
  }
2046
2327
 
2047
- /**
2048
- * Frames and sends a pong message.
2049
- *
2050
- * @param {Buffer} data The message to send
2051
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
2052
- * @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
2053
- * @param {Function} [cb] Callback
2054
- * @private
2055
- */
2056
- doPong(data, mask, readOnly, cb) {
2057
- this.sendFrame(
2058
- Sender.frame(data, {
2059
- fin: true,
2060
- rsv1: false,
2061
- opcode: 0x0a,
2062
- mask,
2063
- readOnly
2064
- }),
2065
- cb
2066
- );
2067
- }
2068
-
2069
2328
  /**
2070
2329
  * Sends a data message to the other peer.
2071
2330
  *
2072
2331
  * @param {*} data The message to send
2073
2332
  * @param {Object} options Options object
2074
- * @param {Boolean} [options.compress=false] Specifies whether or not to
2075
- * compress `data`
2076
2333
  * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
2077
2334
  * or text
2335
+ * @param {Boolean} [options.compress=false] Specifies whether or not to
2336
+ * compress `data`
2078
2337
  * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
2079
2338
  * last one
2080
2339
  * @param {Boolean} [options.mask=false] Specifies whether or not to mask
@@ -2083,15 +2342,37 @@ let Sender$1 = class Sender {
2083
2342
  * @public
2084
2343
  */
2085
2344
  send(data, options, cb) {
2086
- const buf = toBuffer$1(data);
2087
- const perMessageDeflate = this._extensions[PerMessageDeflate$2.extensionName];
2345
+ const perMessageDeflate = this._extensions[PerMessageDeflate$1.extensionName];
2088
2346
  let opcode = options.binary ? 2 : 1;
2089
2347
  let rsv1 = options.compress;
2090
2348
 
2349
+ let byteLength;
2350
+ let readOnly;
2351
+
2352
+ if (typeof data === 'string') {
2353
+ byteLength = Buffer.byteLength(data);
2354
+ readOnly = false;
2355
+ } else if (isBlob$1(data)) {
2356
+ byteLength = data.size;
2357
+ readOnly = false;
2358
+ } else {
2359
+ data = toBuffer$1(data);
2360
+ byteLength = data.length;
2361
+ readOnly = toBuffer$1.readOnly;
2362
+ }
2363
+
2091
2364
  if (this._firstFragment) {
2092
2365
  this._firstFragment = false;
2093
- if (rsv1 && perMessageDeflate) {
2094
- rsv1 = buf.length >= perMessageDeflate._threshold;
2366
+ if (
2367
+ rsv1 &&
2368
+ perMessageDeflate &&
2369
+ perMessageDeflate.params[
2370
+ perMessageDeflate._isServer
2371
+ ? 'server_no_context_takeover'
2372
+ : 'client_no_context_takeover'
2373
+ ]
2374
+ ) {
2375
+ rsv1 = byteLength >= perMessageDeflate._threshold;
2095
2376
  }
2096
2377
  this._compress = rsv1;
2097
2378
  } else {
@@ -2101,48 +2382,112 @@ let Sender$1 = class Sender {
2101
2382
 
2102
2383
  if (options.fin) this._firstFragment = true;
2103
2384
 
2104
- if (perMessageDeflate) {
2105
- const opts = {
2106
- fin: options.fin,
2107
- rsv1,
2108
- opcode,
2109
- mask: options.mask,
2110
- readOnly: toBuffer$1.readOnly
2111
- };
2385
+ const opts = {
2386
+ [kByteLength]: byteLength,
2387
+ fin: options.fin,
2388
+ generateMask: this._generateMask,
2389
+ mask: options.mask,
2390
+ maskBuffer: this._maskBuffer,
2391
+ opcode,
2392
+ readOnly,
2393
+ rsv1
2394
+ };
2112
2395
 
2113
- if (this._deflating) {
2114
- this.enqueue([this.dispatch, buf, this._compress, opts, cb]);
2396
+ if (isBlob$1(data)) {
2397
+ if (this._state !== DEFAULT) {
2398
+ this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
2115
2399
  } else {
2116
- this.dispatch(buf, this._compress, opts, cb);
2400
+ this.getBlobData(data, this._compress, opts, cb);
2117
2401
  }
2402
+ } else if (this._state !== DEFAULT) {
2403
+ this.enqueue([this.dispatch, data, this._compress, opts, cb]);
2118
2404
  } else {
2119
- this.sendFrame(
2120
- Sender.frame(buf, {
2121
- fin: options.fin,
2122
- rsv1: false,
2123
- opcode,
2124
- mask: options.mask,
2125
- readOnly: toBuffer$1.readOnly
2126
- }),
2127
- cb
2128
- );
2405
+ this.dispatch(data, this._compress, opts, cb);
2129
2406
  }
2130
2407
  }
2131
2408
 
2132
2409
  /**
2133
- * Dispatches a data message.
2410
+ * Gets the contents of a blob as binary data.
2134
2411
  *
2135
- * @param {Buffer} data The message to send
2412
+ * @param {Blob} blob The blob
2136
2413
  * @param {Boolean} [compress=false] Specifies whether or not to compress
2137
- * `data`
2414
+ * the data
2138
2415
  * @param {Object} options Options object
2416
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
2417
+ * FIN bit
2418
+ * @param {Function} [options.generateMask] The function used to generate the
2419
+ * masking key
2420
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
2421
+ * `data`
2422
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
2423
+ * key
2139
2424
  * @param {Number} options.opcode The opcode
2140
2425
  * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
2141
2426
  * modified
2427
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
2428
+ * RSV1 bit
2429
+ * @param {Function} [cb] Callback
2430
+ * @private
2431
+ */
2432
+ getBlobData(blob, compress, options, cb) {
2433
+ this._bufferedBytes += options[kByteLength];
2434
+ this._state = GET_BLOB_DATA;
2435
+
2436
+ blob
2437
+ .arrayBuffer()
2438
+ .then((arrayBuffer) => {
2439
+ if (this._socket.destroyed) {
2440
+ const err = new Error(
2441
+ 'The socket was closed while the blob was being read'
2442
+ );
2443
+
2444
+ //
2445
+ // `callCallbacks` is called in the next tick to ensure that errors
2446
+ // that might be thrown in the callbacks behave like errors thrown
2447
+ // outside the promise chain.
2448
+ //
2449
+ process.nextTick(callCallbacks, this, err, cb);
2450
+ return;
2451
+ }
2452
+
2453
+ this._bufferedBytes -= options[kByteLength];
2454
+ const data = toBuffer$1(arrayBuffer);
2455
+
2456
+ if (!compress) {
2457
+ this._state = DEFAULT;
2458
+ this.sendFrame(Sender.frame(data, options), cb);
2459
+ this.dequeue();
2460
+ } else {
2461
+ this.dispatch(data, compress, options, cb);
2462
+ }
2463
+ })
2464
+ .catch((err) => {
2465
+ //
2466
+ // `onError` is called in the next tick for the same reason that
2467
+ // `callCallbacks` above is.
2468
+ //
2469
+ process.nextTick(onError, this, err, cb);
2470
+ });
2471
+ }
2472
+
2473
+ /**
2474
+ * Dispatches a message.
2475
+ *
2476
+ * @param {(Buffer|String)} data The message to send
2477
+ * @param {Boolean} [compress=false] Specifies whether or not to compress
2478
+ * `data`
2479
+ * @param {Object} options Options object
2142
2480
  * @param {Boolean} [options.fin=false] Specifies whether or not to set the
2143
2481
  * FIN bit
2482
+ * @param {Function} [options.generateMask] The function used to generate the
2483
+ * masking key
2144
2484
  * @param {Boolean} [options.mask=false] Specifies whether or not to mask
2145
2485
  * `data`
2486
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
2487
+ * key
2488
+ * @param {Number} options.opcode The opcode
2489
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
2490
+ * modified
2146
2491
  * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
2147
2492
  * RSV1 bit
2148
2493
  * @param {Function} [cb] Callback
@@ -2154,29 +2499,22 @@ let Sender$1 = class Sender {
2154
2499
  return;
2155
2500
  }
2156
2501
 
2157
- const perMessageDeflate = this._extensions[PerMessageDeflate$2.extensionName];
2502
+ const perMessageDeflate = this._extensions[PerMessageDeflate$1.extensionName];
2158
2503
 
2159
- this._bufferedBytes += data.length;
2160
- this._deflating = true;
2504
+ this._bufferedBytes += options[kByteLength];
2505
+ this._state = DEFLATING;
2161
2506
  perMessageDeflate.compress(data, options.fin, (_, buf) => {
2162
2507
  if (this._socket.destroyed) {
2163
2508
  const err = new Error(
2164
2509
  'The socket was closed while data was being compressed'
2165
2510
  );
2166
2511
 
2167
- if (typeof cb === 'function') cb(err);
2168
-
2169
- for (let i = 0; i < this._queue.length; i++) {
2170
- const callback = this._queue[i][4];
2171
-
2172
- if (typeof callback === 'function') callback(err);
2173
- }
2174
-
2512
+ callCallbacks(this, err, cb);
2175
2513
  return;
2176
2514
  }
2177
2515
 
2178
- this._bufferedBytes -= data.length;
2179
- this._deflating = false;
2516
+ this._bufferedBytes -= options[kByteLength];
2517
+ this._state = DEFAULT;
2180
2518
  options.readOnly = false;
2181
2519
  this.sendFrame(Sender.frame(buf, options), cb);
2182
2520
  this.dequeue();
@@ -2189,10 +2527,10 @@ let Sender$1 = class Sender {
2189
2527
  * @private
2190
2528
  */
2191
2529
  dequeue() {
2192
- while (!this._deflating && this._queue.length) {
2530
+ while (this._state === DEFAULT && this._queue.length) {
2193
2531
  const params = this._queue.shift();
2194
2532
 
2195
- this._bufferedBytes -= params[1].length;
2533
+ this._bufferedBytes -= params[3][kByteLength];
2196
2534
  Reflect.apply(params[0], this, params.slice(1));
2197
2535
  }
2198
2536
  }
@@ -2204,14 +2542,14 @@ let Sender$1 = class Sender {
2204
2542
  * @private
2205
2543
  */
2206
2544
  enqueue(params) {
2207
- this._bufferedBytes += params[1].length;
2545
+ this._bufferedBytes += params[3][kByteLength];
2208
2546
  this._queue.push(params);
2209
2547
  }
2210
2548
 
2211
2549
  /**
2212
2550
  * Sends a frame.
2213
2551
  *
2214
- * @param {Buffer[]} list The frame to send
2552
+ * @param {(Buffer | String)[]} list The frame to send
2215
2553
  * @param {Function} [cb] Callback
2216
2554
  * @private
2217
2555
  */
@@ -2230,111 +2568,204 @@ let Sender$1 = class Sender {
2230
2568
  var sender = Sender$1;
2231
2569
 
2232
2570
  /**
2233
- * Class representing an event.
2571
+ * Calls queued callbacks with an error.
2234
2572
  *
2573
+ * @param {Sender} sender The `Sender` instance
2574
+ * @param {Error} err The error to call the callbacks with
2575
+ * @param {Function} [cb] The first callback
2235
2576
  * @private
2236
2577
  */
2237
- class Event {
2238
- /**
2239
- * Create a new `Event`.
2240
- *
2241
- * @param {String} type The name of the event
2242
- * @param {Object} target A reference to the target to which the event was
2243
- * dispatched
2244
- */
2245
- constructor(type, target) {
2246
- this.target = target;
2247
- this.type = type;
2578
+ function callCallbacks(sender, err, cb) {
2579
+ if (typeof cb === 'function') cb(err);
2580
+
2581
+ for (let i = 0; i < sender._queue.length; i++) {
2582
+ const params = sender._queue[i];
2583
+ const callback = params[params.length - 1];
2584
+
2585
+ if (typeof callback === 'function') callback(err);
2248
2586
  }
2249
2587
  }
2250
2588
 
2251
2589
  /**
2252
- * Class representing a message event.
2590
+ * Handles a `Sender` error.
2253
2591
  *
2254
- * @extends Event
2592
+ * @param {Sender} sender The `Sender` instance
2593
+ * @param {Error} err The error
2594
+ * @param {Function} [cb] The first pending callback
2255
2595
  * @private
2256
2596
  */
2257
- class MessageEvent extends Event {
2597
+ function onError(sender, err, cb) {
2598
+ callCallbacks(sender, err, cb);
2599
+ sender.onerror(err);
2600
+ }
2601
+
2602
+ const { kForOnEventAttribute: kForOnEventAttribute$1, kListener: kListener$1 } = constants;
2603
+
2604
+ const kCode = Symbol('kCode');
2605
+ const kData = Symbol('kData');
2606
+ const kError = Symbol('kError');
2607
+ const kMessage = Symbol('kMessage');
2608
+ const kReason = Symbol('kReason');
2609
+ const kTarget = Symbol('kTarget');
2610
+ const kType = Symbol('kType');
2611
+ const kWasClean = Symbol('kWasClean');
2612
+
2613
+ /**
2614
+ * Class representing an event.
2615
+ */
2616
+ class Event {
2258
2617
  /**
2259
- * Create a new `MessageEvent`.
2618
+ * Create a new `Event`.
2260
2619
  *
2261
- * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data
2262
- * @param {WebSocket} target A reference to the target to which the event was
2263
- * dispatched
2620
+ * @param {String} type The name of the event
2621
+ * @throws {TypeError} If the `type` argument is not specified
2622
+ */
2623
+ constructor(type) {
2624
+ this[kTarget] = null;
2625
+ this[kType] = type;
2626
+ }
2627
+
2628
+ /**
2629
+ * @type {*}
2264
2630
  */
2265
- constructor(data, target) {
2266
- super('message', target);
2631
+ get target() {
2632
+ return this[kTarget];
2633
+ }
2267
2634
 
2268
- this.data = data;
2635
+ /**
2636
+ * @type {String}
2637
+ */
2638
+ get type() {
2639
+ return this[kType];
2269
2640
  }
2270
2641
  }
2271
2642
 
2643
+ Object.defineProperty(Event.prototype, 'target', { enumerable: true });
2644
+ Object.defineProperty(Event.prototype, 'type', { enumerable: true });
2645
+
2272
2646
  /**
2273
2647
  * Class representing a close event.
2274
2648
  *
2275
2649
  * @extends Event
2276
- * @private
2277
2650
  */
2278
2651
  class CloseEvent extends Event {
2279
2652
  /**
2280
2653
  * Create a new `CloseEvent`.
2281
2654
  *
2282
- * @param {Number} code The status code explaining why the connection is being
2283
- * closed
2284
- * @param {String} reason A human-readable string explaining why the
2285
- * connection is closing
2286
- * @param {WebSocket} target A reference to the target to which the event was
2287
- * dispatched
2655
+ * @param {String} type The name of the event
2656
+ * @param {Object} [options] A dictionary object that allows for setting
2657
+ * attributes via object members of the same name
2658
+ * @param {Number} [options.code=0] The status code explaining why the
2659
+ * connection was closed
2660
+ * @param {String} [options.reason=''] A human-readable string explaining why
2661
+ * the connection was closed
2662
+ * @param {Boolean} [options.wasClean=false] Indicates whether or not the
2663
+ * connection was cleanly closed
2664
+ */
2665
+ constructor(type, options = {}) {
2666
+ super(type);
2667
+
2668
+ this[kCode] = options.code === undefined ? 0 : options.code;
2669
+ this[kReason] = options.reason === undefined ? '' : options.reason;
2670
+ this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;
2671
+ }
2672
+
2673
+ /**
2674
+ * @type {Number}
2675
+ */
2676
+ get code() {
2677
+ return this[kCode];
2678
+ }
2679
+
2680
+ /**
2681
+ * @type {String}
2288
2682
  */
2289
- constructor(code, reason, target) {
2290
- super('close', target);
2683
+ get reason() {
2684
+ return this[kReason];
2685
+ }
2291
2686
 
2292
- this.wasClean = target._closeFrameReceived && target._closeFrameSent;
2293
- this.reason = reason;
2294
- this.code = code;
2687
+ /**
2688
+ * @type {Boolean}
2689
+ */
2690
+ get wasClean() {
2691
+ return this[kWasClean];
2295
2692
  }
2296
2693
  }
2297
2694
 
2695
+ Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });
2696
+ Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });
2697
+ Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });
2698
+
2298
2699
  /**
2299
- * Class representing an open event.
2700
+ * Class representing an error event.
2300
2701
  *
2301
2702
  * @extends Event
2302
- * @private
2303
2703
  */
2304
- class OpenEvent extends Event {
2704
+ class ErrorEvent extends Event {
2305
2705
  /**
2306
- * Create a new `OpenEvent`.
2706
+ * Create a new `ErrorEvent`.
2307
2707
  *
2308
- * @param {WebSocket} target A reference to the target to which the event was
2309
- * dispatched
2708
+ * @param {String} type The name of the event
2709
+ * @param {Object} [options] A dictionary object that allows for setting
2710
+ * attributes via object members of the same name
2711
+ * @param {*} [options.error=null] The error that generated this event
2712
+ * @param {String} [options.message=''] The error message
2713
+ */
2714
+ constructor(type, options = {}) {
2715
+ super(type);
2716
+
2717
+ this[kError] = options.error === undefined ? null : options.error;
2718
+ this[kMessage] = options.message === undefined ? '' : options.message;
2719
+ }
2720
+
2721
+ /**
2722
+ * @type {*}
2723
+ */
2724
+ get error() {
2725
+ return this[kError];
2726
+ }
2727
+
2728
+ /**
2729
+ * @type {String}
2310
2730
  */
2311
- constructor(target) {
2312
- super('open', target);
2731
+ get message() {
2732
+ return this[kMessage];
2313
2733
  }
2314
2734
  }
2315
2735
 
2736
+ Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });
2737
+ Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });
2738
+
2316
2739
  /**
2317
- * Class representing an error event.
2740
+ * Class representing a message event.
2318
2741
  *
2319
2742
  * @extends Event
2320
- * @private
2321
2743
  */
2322
- class ErrorEvent extends Event {
2744
+ class MessageEvent extends Event {
2323
2745
  /**
2324
- * Create a new `ErrorEvent`.
2746
+ * Create a new `MessageEvent`.
2325
2747
  *
2326
- * @param {Object} error The error that generated this event
2327
- * @param {WebSocket} target A reference to the target to which the event was
2328
- * dispatched
2748
+ * @param {String} type The name of the event
2749
+ * @param {Object} [options] A dictionary object that allows for setting
2750
+ * attributes via object members of the same name
2751
+ * @param {*} [options.data=null] The message content
2329
2752
  */
2330
- constructor(error, target) {
2331
- super('error', target);
2753
+ constructor(type, options = {}) {
2754
+ super(type);
2332
2755
 
2333
- this.message = error.message;
2334
- this.error = error;
2756
+ this[kData] = options.data === undefined ? null : options.data;
2757
+ }
2758
+
2759
+ /**
2760
+ * @type {*}
2761
+ */
2762
+ get data() {
2763
+ return this[kData];
2335
2764
  }
2336
2765
  }
2337
2766
 
2767
+ Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });
2768
+
2338
2769
  /**
2339
2770
  * This provides methods for emulating the `EventTarget` interface. It's not
2340
2771
  * meant to be used directly.
@@ -2346,49 +2777,75 @@ const EventTarget = {
2346
2777
  * Register an event listener.
2347
2778
  *
2348
2779
  * @param {String} type A string representing the event type to listen for
2349
- * @param {Function} listener The listener to add
2780
+ * @param {(Function|Object)} handler The listener to add
2350
2781
  * @param {Object} [options] An options object specifies characteristics about
2351
2782
  * the event listener
2352
- * @param {Boolean} [options.once=false] A `Boolean`` indicating that the
2783
+ * @param {Boolean} [options.once=false] A `Boolean` indicating that the
2353
2784
  * listener should be invoked at most once after being added. If `true`,
2354
2785
  * the listener would be automatically removed when invoked.
2355
2786
  * @public
2356
2787
  */
2357
- addEventListener(type, listener, options) {
2358
- if (typeof listener !== 'function') return;
2359
-
2360
- function onMessage(data) {
2361
- listener.call(this, new MessageEvent(data, this));
2362
- }
2363
-
2364
- function onClose(code, message) {
2365
- listener.call(this, new CloseEvent(code, message, this));
2366
- }
2367
-
2368
- function onError(error) {
2369
- listener.call(this, new ErrorEvent(error, this));
2370
- }
2371
-
2372
- function onOpen() {
2373
- listener.call(this, new OpenEvent(this));
2788
+ addEventListener(type, handler, options = {}) {
2789
+ for (const listener of this.listeners(type)) {
2790
+ if (
2791
+ !options[kForOnEventAttribute$1] &&
2792
+ listener[kListener$1] === handler &&
2793
+ !listener[kForOnEventAttribute$1]
2794
+ ) {
2795
+ return;
2796
+ }
2374
2797
  }
2375
2798
 
2376
- const method = options && options.once ? 'once' : 'on';
2799
+ let wrapper;
2377
2800
 
2378
2801
  if (type === 'message') {
2379
- onMessage._listener = listener;
2380
- this[method](type, onMessage);
2802
+ wrapper = function onMessage(data, isBinary) {
2803
+ const event = new MessageEvent('message', {
2804
+ data: isBinary ? data : data.toString()
2805
+ });
2806
+
2807
+ event[kTarget] = this;
2808
+ callListener(handler, this, event);
2809
+ };
2381
2810
  } else if (type === 'close') {
2382
- onClose._listener = listener;
2383
- this[method](type, onClose);
2811
+ wrapper = function onClose(code, message) {
2812
+ const event = new CloseEvent('close', {
2813
+ code,
2814
+ reason: message.toString(),
2815
+ wasClean: this._closeFrameReceived && this._closeFrameSent
2816
+ });
2817
+
2818
+ event[kTarget] = this;
2819
+ callListener(handler, this, event);
2820
+ };
2384
2821
  } else if (type === 'error') {
2385
- onError._listener = listener;
2386
- this[method](type, onError);
2822
+ wrapper = function onError(error) {
2823
+ const event = new ErrorEvent('error', {
2824
+ error,
2825
+ message: error.message
2826
+ });
2827
+
2828
+ event[kTarget] = this;
2829
+ callListener(handler, this, event);
2830
+ };
2387
2831
  } else if (type === 'open') {
2388
- onOpen._listener = listener;
2389
- this[method](type, onOpen);
2832
+ wrapper = function onOpen() {
2833
+ const event = new Event('open');
2834
+
2835
+ event[kTarget] = this;
2836
+ callListener(handler, this, event);
2837
+ };
2838
+ } else {
2839
+ return;
2840
+ }
2841
+
2842
+ wrapper[kForOnEventAttribute$1] = !!options[kForOnEventAttribute$1];
2843
+ wrapper[kListener$1] = handler;
2844
+
2845
+ if (options.once) {
2846
+ this.once(type, wrapper);
2390
2847
  } else {
2391
- this[method](type, listener);
2848
+ this.on(type, wrapper);
2392
2849
  }
2393
2850
  },
2394
2851
 
@@ -2396,44 +2853,39 @@ const EventTarget = {
2396
2853
  * Remove an event listener.
2397
2854
  *
2398
2855
  * @param {String} type A string representing the event type to remove
2399
- * @param {Function} listener The listener to remove
2856
+ * @param {(Function|Object)} handler The listener to remove
2400
2857
  * @public
2401
2858
  */
2402
- removeEventListener(type, listener) {
2403
- const listeners = this.listeners(type);
2404
-
2405
- for (let i = 0; i < listeners.length; i++) {
2406
- if (listeners[i] === listener || listeners[i]._listener === listener) {
2407
- this.removeListener(type, listeners[i]);
2859
+ removeEventListener(type, handler) {
2860
+ for (const listener of this.listeners(type)) {
2861
+ if (listener[kListener$1] === handler && !listener[kForOnEventAttribute$1]) {
2862
+ this.removeListener(type, listener);
2863
+ break;
2408
2864
  }
2409
2865
  }
2410
2866
  }
2411
2867
  };
2412
2868
 
2413
- var eventTarget = EventTarget;
2869
+ var eventTarget = {
2870
+ EventTarget};
2414
2871
 
2415
- //
2416
- // Allowed token characters:
2417
- //
2418
- // '!', '#', '$', '%', '&', ''', '*', '+', '-',
2419
- // '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
2420
- //
2421
- // tokenChars[32] === 0 // ' '
2422
- // tokenChars[33] === 1 // '!'
2423
- // tokenChars[34] === 0 // '"'
2424
- // ...
2425
- //
2426
- // prettier-ignore
2427
- const tokenChars = [
2428
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
2429
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
2430
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
2431
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
2432
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
2433
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
2434
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
2435
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
2436
- ];
2872
+ /**
2873
+ * Call an event listener
2874
+ *
2875
+ * @param {(Function|Object)} listener The listener to call
2876
+ * @param {*} thisArg The value to use as `this`` when calling the listener
2877
+ * @param {Event} event The event to pass to the listener
2878
+ * @private
2879
+ */
2880
+ function callListener(listener, thisArg, event) {
2881
+ if (typeof listener === 'object' && listener.handleEvent) {
2882
+ listener.handleEvent.call(listener, event);
2883
+ } else {
2884
+ listener.call(thisArg, event);
2885
+ }
2886
+ }
2887
+
2888
+ const { tokenChars: tokenChars$1 } = validationExports;
2437
2889
 
2438
2890
  /**
2439
2891
  * Adds an offer to the map of extension offers or a parameter to the map of
@@ -2457,11 +2909,8 @@ function push(dest, name, elem) {
2457
2909
  * @return {Object} The parsed object
2458
2910
  * @public
2459
2911
  */
2460
- function parse$2(header) {
2912
+ function parse$1(header) {
2461
2913
  const offers = Object.create(null);
2462
-
2463
- if (header === undefined || header === '') return offers;
2464
-
2465
2914
  let params = Object.create(null);
2466
2915
  let mustUnescape = false;
2467
2916
  let isEscaping = false;
@@ -2469,16 +2918,20 @@ function parse$2(header) {
2469
2918
  let extensionName;
2470
2919
  let paramName;
2471
2920
  let start = -1;
2921
+ let code = -1;
2472
2922
  let end = -1;
2473
2923
  let i = 0;
2474
2924
 
2475
2925
  for (; i < header.length; i++) {
2476
- const code = header.charCodeAt(i);
2926
+ code = header.charCodeAt(i);
2477
2927
 
2478
2928
  if (extensionName === undefined) {
2479
- if (end === -1 && tokenChars[code] === 1) {
2929
+ if (end === -1 && tokenChars$1[code] === 1) {
2480
2930
  if (start === -1) start = i;
2481
- } else if (code === 0x20 /* ' ' */ || code === 0x09 /* '\t' */) {
2931
+ } else if (
2932
+ i !== 0 &&
2933
+ (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
2934
+ ) {
2482
2935
  if (end === -1 && start !== -1) end = i;
2483
2936
  } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
2484
2937
  if (start === -1) {
@@ -2499,7 +2952,7 @@ function parse$2(header) {
2499
2952
  throw new SyntaxError(`Unexpected character at index ${i}`);
2500
2953
  }
2501
2954
  } else if (paramName === undefined) {
2502
- if (end === -1 && tokenChars[code] === 1) {
2955
+ if (end === -1 && tokenChars$1[code] === 1) {
2503
2956
  if (start === -1) start = i;
2504
2957
  } else if (code === 0x20 || code === 0x09) {
2505
2958
  if (end === -1 && start !== -1) end = i;
@@ -2530,14 +2983,14 @@ function parse$2(header) {
2530
2983
  // Ref: https://tools.ietf.org/html/rfc6455#section-9.1
2531
2984
  //
2532
2985
  if (isEscaping) {
2533
- if (tokenChars[code] !== 1) {
2986
+ if (tokenChars$1[code] !== 1) {
2534
2987
  throw new SyntaxError(`Unexpected character at index ${i}`);
2535
2988
  }
2536
2989
  if (start === -1) start = i;
2537
2990
  else if (!mustUnescape) mustUnescape = true;
2538
2991
  isEscaping = false;
2539
2992
  } else if (inQuotes) {
2540
- if (tokenChars[code] === 1) {
2993
+ if (tokenChars$1[code] === 1) {
2541
2994
  if (start === -1) start = i;
2542
2995
  } else if (code === 0x22 /* '"' */ && start !== -1) {
2543
2996
  inQuotes = false;
@@ -2549,7 +3002,7 @@ function parse$2(header) {
2549
3002
  }
2550
3003
  } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
2551
3004
  inQuotes = true;
2552
- } else if (end === -1 && tokenChars[code] === 1) {
3005
+ } else if (end === -1 && tokenChars$1[code] === 1) {
2553
3006
  if (start === -1) start = i;
2554
3007
  } else if (start !== -1 && (code === 0x20 || code === 0x09)) {
2555
3008
  if (end === -1) end = i;
@@ -2579,7 +3032,7 @@ function parse$2(header) {
2579
3032
  }
2580
3033
  }
2581
3034
 
2582
- if (start === -1 || inQuotes) {
3035
+ if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
2583
3036
  throw new SyntaxError('Unexpected end of input');
2584
3037
  }
2585
3038
 
@@ -2608,7 +3061,7 @@ function parse$2(header) {
2608
3061
  * @return {String} A string representing the given object
2609
3062
  * @public
2610
3063
  */
2611
- function format$2(extensions) {
3064
+ function format$1(extensions) {
2612
3065
  return Object.keys(extensions)
2613
3066
  .map((extension) => {
2614
3067
  let configurations = extensions[extension];
@@ -2632,44 +3085,52 @@ function format$2(extensions) {
2632
3085
  .join(', ');
2633
3086
  }
2634
3087
 
2635
- var extension = { format: format$2, parse: parse$2 };
3088
+ var extension = { format: format$1, parse: parse$1 };
2636
3089
 
2637
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Readable$" }] */
3090
+ /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
2638
3091
 
2639
- const EventEmitter$1 = require$$0$3;
2640
- const https = require$$1$1;
2641
- const http$1 = require$$2$1;
3092
+ const EventEmitter = require$$0$4;
3093
+ const https = require$$1$2;
3094
+ const http = require$$2$1;
2642
3095
  const net = require$$3;
2643
3096
  const tls = require$$4;
2644
- const { randomBytes, createHash: createHash$1 } = require$$5;
2645
- const { Readable } = require$$0$2;
3097
+ const { randomBytes, createHash: createHash$1 } = require$$1$1;
3098
+ const { Duplex: Duplex$2, Readable } = require$$0$3;
2646
3099
  const { URL } = require$$7;
2647
3100
 
2648
- const PerMessageDeflate$1 = permessageDeflate;
3101
+ const PerMessageDeflate = permessageDeflate;
2649
3102
  const Receiver = receiver;
2650
3103
  const Sender = sender;
3104
+ const { isBlob } = validationExports;
3105
+
2651
3106
  const {
2652
3107
  BINARY_TYPES,
3108
+ CLOSE_TIMEOUT: CLOSE_TIMEOUT$1,
2653
3109
  EMPTY_BUFFER,
2654
3110
  GUID: GUID$1,
3111
+ kForOnEventAttribute,
3112
+ kListener,
2655
3113
  kStatusCode,
2656
3114
  kWebSocket: kWebSocket$1,
2657
3115
  NOOP
2658
3116
  } = constants;
2659
- const { addEventListener, removeEventListener } = eventTarget;
2660
- const { format: format$1, parse: parse$1 } = extension;
3117
+ const {
3118
+ EventTarget: { addEventListener, removeEventListener }
3119
+ } = eventTarget;
3120
+ const { format, parse } = extension;
2661
3121
  const { toBuffer } = bufferUtilExports;
2662
3122
 
2663
- const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
3123
+ const kAborted = Symbol('kAborted');
2664
3124
  const protocolVersions = [8, 13];
2665
- const closeTimeout = 30 * 1000;
3125
+ const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
3126
+ const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
2666
3127
 
2667
3128
  /**
2668
3129
  * Class representing a WebSocket.
2669
3130
  *
2670
3131
  * @extends EventEmitter
2671
3132
  */
2672
- let WebSocket$3 = class WebSocket extends EventEmitter$1 {
3133
+ let WebSocket$1 = class WebSocket extends EventEmitter {
2673
3134
  /**
2674
3135
  * Create a new `WebSocket`.
2675
3136
  *
@@ -2684,9 +3145,11 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2684
3145
  this._closeCode = 1006;
2685
3146
  this._closeFrameReceived = false;
2686
3147
  this._closeFrameSent = false;
2687
- this._closeMessage = '';
3148
+ this._closeMessage = EMPTY_BUFFER;
2688
3149
  this._closeTimer = null;
3150
+ this._errorEmitted = false;
2689
3151
  this._extensions = {};
3152
+ this._paused = false;
2690
3153
  this._protocol = '';
2691
3154
  this._readyState = WebSocket.CONNECTING;
2692
3155
  this._receiver = null;
@@ -2698,23 +3161,28 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2698
3161
  this._isServer = false;
2699
3162
  this._redirects = 0;
2700
3163
 
2701
- if (Array.isArray(protocols)) {
2702
- protocols = protocols.join(', ');
2703
- } else if (typeof protocols === 'object' && protocols !== null) {
2704
- options = protocols;
2705
- protocols = undefined;
3164
+ if (protocols === undefined) {
3165
+ protocols = [];
3166
+ } else if (!Array.isArray(protocols)) {
3167
+ if (typeof protocols === 'object' && protocols !== null) {
3168
+ options = protocols;
3169
+ protocols = [];
3170
+ } else {
3171
+ protocols = [protocols];
3172
+ }
2706
3173
  }
2707
3174
 
2708
3175
  initAsClient(this, address, protocols, options);
2709
3176
  } else {
3177
+ this._autoPong = options.autoPong;
3178
+ this._closeTimeout = options.closeTimeout;
2710
3179
  this._isServer = true;
2711
3180
  }
2712
3181
  }
2713
3182
 
2714
3183
  /**
2715
- * This deviates from the WHATWG interface since ws doesn't support the
2716
- * required default "blob" type (instead we define a custom "nodebuffer"
2717
- * type).
3184
+ * For historical reasons, the custom "nodebuffer" type is used by the default
3185
+ * instead of "blob".
2718
3186
  *
2719
3187
  * @type {String}
2720
3188
  */
@@ -2750,49 +3218,44 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2750
3218
  }
2751
3219
 
2752
3220
  /**
2753
- * @type {Function}
3221
+ * @type {Boolean}
2754
3222
  */
2755
- /* istanbul ignore next */
2756
- get onclose() {
2757
- return undefined;
3223
+ get isPaused() {
3224
+ return this._paused;
2758
3225
  }
2759
3226
 
2760
- /* istanbul ignore next */
2761
- set onclose(listener) {}
2762
-
2763
3227
  /**
2764
3228
  * @type {Function}
2765
3229
  */
2766
3230
  /* istanbul ignore next */
2767
- get onerror() {
2768
- return undefined;
3231
+ get onclose() {
3232
+ return null;
2769
3233
  }
2770
3234
 
3235
+ /**
3236
+ * @type {Function}
3237
+ */
2771
3238
  /* istanbul ignore next */
2772
- set onerror(listener) {}
3239
+ get onerror() {
3240
+ return null;
3241
+ }
2773
3242
 
2774
3243
  /**
2775
3244
  * @type {Function}
2776
3245
  */
2777
3246
  /* istanbul ignore next */
2778
3247
  get onopen() {
2779
- return undefined;
3248
+ return null;
2780
3249
  }
2781
3250
 
2782
- /* istanbul ignore next */
2783
- set onopen(listener) {}
2784
-
2785
3251
  /**
2786
3252
  * @type {Function}
2787
3253
  */
2788
3254
  /* istanbul ignore next */
2789
3255
  get onmessage() {
2790
- return undefined;
3256
+ return null;
2791
3257
  }
2792
3258
 
2793
- /* istanbul ignore next */
2794
- set onmessage(listener) {}
2795
-
2796
3259
  /**
2797
3260
  * @type {String}
2798
3261
  */
@@ -2817,25 +3280,37 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2817
3280
  /**
2818
3281
  * Set up the socket and the internal resources.
2819
3282
  *
2820
- * @param {(net.Socket|tls.Socket)} socket The network socket between the
2821
- * server and client
3283
+ * @param {Duplex} socket The network socket between the server and client
2822
3284
  * @param {Buffer} head The first packet of the upgraded stream
2823
- * @param {Number} [maxPayload=0] The maximum allowed message size
3285
+ * @param {Object} options Options object
3286
+ * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
3287
+ * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
3288
+ * multiple times in the same tick
3289
+ * @param {Function} [options.generateMask] The function used to generate the
3290
+ * masking key
3291
+ * @param {Number} [options.maxPayload=0] The maximum allowed message size
3292
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
3293
+ * not to skip UTF-8 validation for text and close messages
2824
3294
  * @private
2825
3295
  */
2826
- setSocket(socket, head, maxPayload) {
2827
- const receiver = new Receiver(
2828
- this.binaryType,
2829
- this._extensions,
2830
- this._isServer,
2831
- maxPayload
2832
- );
3296
+ setSocket(socket, head, options) {
3297
+ const receiver = new Receiver({
3298
+ allowSynchronousEvents: options.allowSynchronousEvents,
3299
+ binaryType: this.binaryType,
3300
+ extensions: this._extensions,
3301
+ isServer: this._isServer,
3302
+ maxPayload: options.maxPayload,
3303
+ skipUTF8Validation: options.skipUTF8Validation
3304
+ });
3305
+
3306
+ const sender = new Sender(socket, this._extensions, options.generateMask);
2833
3307
 
2834
- this._sender = new Sender(socket, this._extensions);
2835
3308
  this._receiver = receiver;
3309
+ this._sender = sender;
2836
3310
  this._socket = socket;
2837
3311
 
2838
3312
  receiver[kWebSocket$1] = this;
3313
+ sender[kWebSocket$1] = this;
2839
3314
  socket[kWebSocket$1] = this;
2840
3315
 
2841
3316
  receiver.on('conclude', receiverOnConclude);
@@ -2845,15 +3320,20 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2845
3320
  receiver.on('ping', receiverOnPing);
2846
3321
  receiver.on('pong', receiverOnPong);
2847
3322
 
2848
- socket.setTimeout(0);
2849
- socket.setNoDelay();
3323
+ sender.onerror = senderOnError;
3324
+
3325
+ //
3326
+ // These methods may not be available if `socket` is just a `Duplex`.
3327
+ //
3328
+ if (socket.setTimeout) socket.setTimeout(0);
3329
+ if (socket.setNoDelay) socket.setNoDelay();
2850
3330
 
2851
3331
  if (head.length > 0) socket.unshift(head);
2852
3332
 
2853
3333
  socket.on('close', socketOnClose);
2854
3334
  socket.on('data', socketOnData);
2855
3335
  socket.on('end', socketOnEnd);
2856
- socket.on('error', socketOnError$1);
3336
+ socket.on('error', socketOnError);
2857
3337
 
2858
3338
  this._readyState = WebSocket.OPEN;
2859
3339
  this.emit('open');
@@ -2871,8 +3351,8 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2871
3351
  return;
2872
3352
  }
2873
3353
 
2874
- if (this._extensions[PerMessageDeflate$1.extensionName]) {
2875
- this._extensions[PerMessageDeflate$1.extensionName].cleanup();
3354
+ if (this._extensions[PerMessageDeflate.extensionName]) {
3355
+ this._extensions[PerMessageDeflate.extensionName].cleanup();
2876
3356
  }
2877
3357
 
2878
3358
  this._receiver.removeAllListeners();
@@ -2896,14 +3376,16 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2896
3376
  * +---+
2897
3377
  *
2898
3378
  * @param {Number} [code] Status code explaining why the connection is closing
2899
- * @param {String} [data] A string explaining why the connection is closing
3379
+ * @param {(String|Buffer)} [data] The reason why the connection is
3380
+ * closing
2900
3381
  * @public
2901
3382
  */
2902
3383
  close(code, data) {
2903
3384
  if (this.readyState === WebSocket.CLOSED) return;
2904
3385
  if (this.readyState === WebSocket.CONNECTING) {
2905
3386
  const msg = 'WebSocket was closed before the connection was established';
2906
- return abortHandshake$1(this, this._req, msg);
3387
+ abortHandshake(this, this._req, msg);
3388
+ return;
2907
3389
  }
2908
3390
 
2909
3391
  if (this.readyState === WebSocket.CLOSING) {
@@ -2935,13 +3417,24 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
2935
3417
  }
2936
3418
  });
2937
3419
 
2938
- //
2939
- // Specify a timeout for the closing handshake to complete.
2940
- //
2941
- this._closeTimer = setTimeout(
2942
- this._socket.destroy.bind(this._socket),
2943
- closeTimeout
2944
- );
3420
+ setCloseTimer(this);
3421
+ }
3422
+
3423
+ /**
3424
+ * Pause the socket.
3425
+ *
3426
+ * @public
3427
+ */
3428
+ pause() {
3429
+ if (
3430
+ this.readyState === WebSocket.CONNECTING ||
3431
+ this.readyState === WebSocket.CLOSED
3432
+ ) {
3433
+ return;
3434
+ }
3435
+
3436
+ this._paused = true;
3437
+ this._socket.pause();
2945
3438
  }
2946
3439
 
2947
3440
  /**
@@ -3008,15 +3501,32 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
3008
3501
  this._sender.pong(data || EMPTY_BUFFER, mask, cb);
3009
3502
  }
3010
3503
 
3504
+ /**
3505
+ * Resume the socket.
3506
+ *
3507
+ * @public
3508
+ */
3509
+ resume() {
3510
+ if (
3511
+ this.readyState === WebSocket.CONNECTING ||
3512
+ this.readyState === WebSocket.CLOSED
3513
+ ) {
3514
+ return;
3515
+ }
3516
+
3517
+ this._paused = false;
3518
+ if (!this._receiver._writableState.needDrain) this._socket.resume();
3519
+ }
3520
+
3011
3521
  /**
3012
3522
  * Send a data message.
3013
3523
  *
3014
3524
  * @param {*} data The message to send
3015
3525
  * @param {Object} [options] Options object
3016
- * @param {Boolean} [options.compress] Specifies whether or not to compress
3017
- * `data`
3018
3526
  * @param {Boolean} [options.binary] Specifies whether `data` is binary or
3019
3527
  * text
3528
+ * @param {Boolean} [options.compress] Specifies whether or not to compress
3529
+ * `data`
3020
3530
  * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
3021
3531
  * last one
3022
3532
  * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
@@ -3048,7 +3558,7 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
3048
3558
  ...options
3049
3559
  };
3050
3560
 
3051
- if (!this._extensions[PerMessageDeflate$1.extensionName]) {
3561
+ if (!this._extensions[PerMessageDeflate.extensionName]) {
3052
3562
  opts.compress = false;
3053
3563
  }
3054
3564
 
@@ -3064,7 +3574,8 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
3064
3574
  if (this.readyState === WebSocket.CLOSED) return;
3065
3575
  if (this.readyState === WebSocket.CONNECTING) {
3066
3576
  const msg = 'WebSocket was closed before the connection was established';
3067
- return abortHandshake$1(this, this._req, msg);
3577
+ abortHandshake(this, this._req, msg);
3578
+ return;
3068
3579
  }
3069
3580
 
3070
3581
  if (this._socket) {
@@ -3078,7 +3589,7 @@ let WebSocket$3 = class WebSocket extends EventEmitter$1 {
3078
3589
  * @constant {Number} CONNECTING
3079
3590
  * @memberof WebSocket
3080
3591
  */
3081
- Object.defineProperty(WebSocket$3, 'CONNECTING', {
3592
+ Object.defineProperty(WebSocket$1, 'CONNECTING', {
3082
3593
  enumerable: true,
3083
3594
  value: readyStates.indexOf('CONNECTING')
3084
3595
  });
@@ -3087,7 +3598,7 @@ Object.defineProperty(WebSocket$3, 'CONNECTING', {
3087
3598
  * @constant {Number} CONNECTING
3088
3599
  * @memberof WebSocket.prototype
3089
3600
  */
3090
- Object.defineProperty(WebSocket$3.prototype, 'CONNECTING', {
3601
+ Object.defineProperty(WebSocket$1.prototype, 'CONNECTING', {
3091
3602
  enumerable: true,
3092
3603
  value: readyStates.indexOf('CONNECTING')
3093
3604
  });
@@ -3096,7 +3607,7 @@ Object.defineProperty(WebSocket$3.prototype, 'CONNECTING', {
3096
3607
  * @constant {Number} OPEN
3097
3608
  * @memberof WebSocket
3098
3609
  */
3099
- Object.defineProperty(WebSocket$3, 'OPEN', {
3610
+ Object.defineProperty(WebSocket$1, 'OPEN', {
3100
3611
  enumerable: true,
3101
3612
  value: readyStates.indexOf('OPEN')
3102
3613
  });
@@ -3105,7 +3616,7 @@ Object.defineProperty(WebSocket$3, 'OPEN', {
3105
3616
  * @constant {Number} OPEN
3106
3617
  * @memberof WebSocket.prototype
3107
3618
  */
3108
- Object.defineProperty(WebSocket$3.prototype, 'OPEN', {
3619
+ Object.defineProperty(WebSocket$1.prototype, 'OPEN', {
3109
3620
  enumerable: true,
3110
3621
  value: readyStates.indexOf('OPEN')
3111
3622
  });
@@ -3114,7 +3625,7 @@ Object.defineProperty(WebSocket$3.prototype, 'OPEN', {
3114
3625
  * @constant {Number} CLOSING
3115
3626
  * @memberof WebSocket
3116
3627
  */
3117
- Object.defineProperty(WebSocket$3, 'CLOSING', {
3628
+ Object.defineProperty(WebSocket$1, 'CLOSING', {
3118
3629
  enumerable: true,
3119
3630
  value: readyStates.indexOf('CLOSING')
3120
3631
  });
@@ -3123,7 +3634,7 @@ Object.defineProperty(WebSocket$3, 'CLOSING', {
3123
3634
  * @constant {Number} CLOSING
3124
3635
  * @memberof WebSocket.prototype
3125
3636
  */
3126
- Object.defineProperty(WebSocket$3.prototype, 'CLOSING', {
3637
+ Object.defineProperty(WebSocket$1.prototype, 'CLOSING', {
3127
3638
  enumerable: true,
3128
3639
  value: readyStates.indexOf('CLOSING')
3129
3640
  });
@@ -3132,7 +3643,7 @@ Object.defineProperty(WebSocket$3.prototype, 'CLOSING', {
3132
3643
  * @constant {Number} CLOSED
3133
3644
  * @memberof WebSocket
3134
3645
  */
3135
- Object.defineProperty(WebSocket$3, 'CLOSED', {
3646
+ Object.defineProperty(WebSocket$1, 'CLOSED', {
3136
3647
  enumerable: true,
3137
3648
  value: readyStates.indexOf('CLOSED')
3138
3649
  });
@@ -3141,7 +3652,7 @@ Object.defineProperty(WebSocket$3, 'CLOSED', {
3141
3652
  * @constant {Number} CLOSED
3142
3653
  * @memberof WebSocket.prototype
3143
3654
  */
3144
- Object.defineProperty(WebSocket$3.prototype, 'CLOSED', {
3655
+ Object.defineProperty(WebSocket$1.prototype, 'CLOSED', {
3145
3656
  enumerable: true,
3146
3657
  value: readyStates.indexOf('CLOSED')
3147
3658
  });
@@ -3150,11 +3661,12 @@ Object.defineProperty(WebSocket$3.prototype, 'CLOSED', {
3150
3661
  'binaryType',
3151
3662
  'bufferedAmount',
3152
3663
  'extensions',
3664
+ 'isPaused',
3153
3665
  'protocol',
3154
3666
  'readyState',
3155
3667
  'url'
3156
3668
  ].forEach((property) => {
3157
- Object.defineProperty(WebSocket$3.prototype, property, { enumerable: true });
3669
+ Object.defineProperty(WebSocket$1.prototype, property, { enumerable: true });
3158
3670
  });
3159
3671
 
3160
3672
  //
@@ -3162,76 +3674,98 @@ Object.defineProperty(WebSocket$3.prototype, 'CLOSED', {
3162
3674
  // See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
3163
3675
  //
3164
3676
  ['open', 'error', 'close', 'message'].forEach((method) => {
3165
- Object.defineProperty(WebSocket$3.prototype, `on${method}`, {
3677
+ Object.defineProperty(WebSocket$1.prototype, `on${method}`, {
3166
3678
  enumerable: true,
3167
3679
  get() {
3168
- const listeners = this.listeners(method);
3169
- for (let i = 0; i < listeners.length; i++) {
3170
- if (listeners[i]._listener) return listeners[i]._listener;
3680
+ for (const listener of this.listeners(method)) {
3681
+ if (listener[kForOnEventAttribute]) return listener[kListener];
3171
3682
  }
3172
3683
 
3173
- return undefined;
3684
+ return null;
3174
3685
  },
3175
- set(listener) {
3176
- const listeners = this.listeners(method);
3177
- for (let i = 0; i < listeners.length; i++) {
3178
- //
3179
- // Remove only the listeners added via `addEventListener`.
3180
- //
3181
- if (listeners[i]._listener) this.removeListener(method, listeners[i]);
3686
+ set(handler) {
3687
+ for (const listener of this.listeners(method)) {
3688
+ if (listener[kForOnEventAttribute]) {
3689
+ this.removeListener(method, listener);
3690
+ break;
3691
+ }
3182
3692
  }
3183
- this.addEventListener(method, listener);
3693
+
3694
+ if (typeof handler !== 'function') return;
3695
+
3696
+ this.addEventListener(method, handler, {
3697
+ [kForOnEventAttribute]: true
3698
+ });
3184
3699
  }
3185
3700
  });
3186
3701
  });
3187
3702
 
3188
- WebSocket$3.prototype.addEventListener = addEventListener;
3189
- WebSocket$3.prototype.removeEventListener = removeEventListener;
3703
+ WebSocket$1.prototype.addEventListener = addEventListener;
3704
+ WebSocket$1.prototype.removeEventListener = removeEventListener;
3190
3705
 
3191
- var websocket = WebSocket$3;
3706
+ var websocket = WebSocket$1;
3192
3707
 
3193
3708
  /**
3194
3709
  * Initialize a WebSocket client.
3195
3710
  *
3196
3711
  * @param {WebSocket} websocket The client to initialize
3197
3712
  * @param {(String|URL)} address The URL to which to connect
3198
- * @param {String} [protocols] The subprotocols
3713
+ * @param {Array} protocols The subprotocols
3199
3714
  * @param {Object} [options] Connection options
3200
- * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
3201
- * permessage-deflate
3715
+ * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
3716
+ * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
3717
+ * times in the same tick
3718
+ * @param {Boolean} [options.autoPong=true] Specifies whether or not to
3719
+ * automatically send a pong in response to a ping
3720
+ * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
3721
+ * for the closing handshake to finish after `websocket.close()` is called
3722
+ * @param {Function} [options.finishRequest] A function which can be used to
3723
+ * customize the headers of each http request before it is sent
3724
+ * @param {Boolean} [options.followRedirects=false] Whether or not to follow
3725
+ * redirects
3726
+ * @param {Function} [options.generateMask] The function used to generate the
3727
+ * masking key
3202
3728
  * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
3203
3729
  * handshake request
3204
- * @param {Number} [options.protocolVersion=13] Value of the
3205
- * `Sec-WebSocket-Version` header
3206
- * @param {String} [options.origin] Value of the `Origin` or
3207
- * `Sec-WebSocket-Origin` header
3208
3730
  * @param {Number} [options.maxPayload=104857600] The maximum allowed message
3209
3731
  * size
3210
- * @param {Boolean} [options.followRedirects=false] Whether or not to follow
3211
- * redirects
3212
3732
  * @param {Number} [options.maxRedirects=10] The maximum number of redirects
3213
3733
  * allowed
3734
+ * @param {String} [options.origin] Value of the `Origin` or
3735
+ * `Sec-WebSocket-Origin` header
3736
+ * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
3737
+ * permessage-deflate
3738
+ * @param {Number} [options.protocolVersion=13] Value of the
3739
+ * `Sec-WebSocket-Version` header
3740
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
3741
+ * not to skip UTF-8 validation for text and close messages
3214
3742
  * @private
3215
3743
  */
3216
3744
  function initAsClient(websocket, address, protocols, options) {
3217
3745
  const opts = {
3746
+ allowSynchronousEvents: true,
3747
+ autoPong: true,
3748
+ closeTimeout: CLOSE_TIMEOUT$1,
3218
3749
  protocolVersion: protocolVersions[1],
3219
3750
  maxPayload: 100 * 1024 * 1024,
3751
+ skipUTF8Validation: false,
3220
3752
  perMessageDeflate: true,
3221
3753
  followRedirects: false,
3222
3754
  maxRedirects: 10,
3223
3755
  ...options,
3224
- createConnection: undefined,
3225
3756
  socketPath: undefined,
3226
3757
  hostname: undefined,
3227
3758
  protocol: undefined,
3228
3759
  timeout: undefined,
3229
- method: undefined,
3760
+ method: 'GET',
3230
3761
  host: undefined,
3231
3762
  path: undefined,
3232
3763
  port: undefined
3233
3764
  };
3234
3765
 
3766
+ websocket._autoPong = opts.autoPong;
3767
+ websocket._closeTimeout = opts.closeTimeout;
3768
+
3235
3769
  if (!protocolVersions.includes(opts.protocolVersion)) {
3236
3770
  throw new RangeError(
3237
3771
  `Unsupported protocol version: ${opts.protocolVersion} ` +
@@ -3243,16 +3777,38 @@ function initAsClient(websocket, address, protocols, options) {
3243
3777
 
3244
3778
  if (address instanceof URL) {
3245
3779
  parsedUrl = address;
3246
- websocket._url = address.href;
3247
3780
  } else {
3248
- parsedUrl = new URL(address);
3249
- websocket._url = address;
3781
+ try {
3782
+ parsedUrl = new URL(address);
3783
+ } catch {
3784
+ throw new SyntaxError(`Invalid URL: ${address}`);
3785
+ }
3786
+ }
3787
+
3788
+ if (parsedUrl.protocol === 'http:') {
3789
+ parsedUrl.protocol = 'ws:';
3790
+ } else if (parsedUrl.protocol === 'https:') {
3791
+ parsedUrl.protocol = 'wss:';
3250
3792
  }
3251
3793
 
3252
- const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
3794
+ websocket._url = parsedUrl.href;
3795
+
3796
+ const isSecure = parsedUrl.protocol === 'wss:';
3797
+ const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
3798
+ let invalidUrlMessage;
3799
+
3800
+ if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
3801
+ invalidUrlMessage =
3802
+ 'The URL\'s protocol must be one of "ws:", "wss:", ' +
3803
+ '"http:", "https:", or "ws+unix:"';
3804
+ } else if (isIpcUrl && !parsedUrl.pathname) {
3805
+ invalidUrlMessage = "The URL's pathname is empty";
3806
+ } else if (parsedUrl.hash) {
3807
+ invalidUrlMessage = 'The URL contains a fragment identifier';
3808
+ }
3253
3809
 
3254
- if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
3255
- const err = new Error(`Invalid URL: ${websocket.url}`);
3810
+ if (invalidUrlMessage) {
3811
+ const err = new SyntaxError(invalidUrlMessage);
3256
3812
 
3257
3813
  if (websocket._redirects === 0) {
3258
3814
  throw err;
@@ -3262,41 +3818,55 @@ function initAsClient(websocket, address, protocols, options) {
3262
3818
  }
3263
3819
  }
3264
3820
 
3265
- const isSecure =
3266
- parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
3267
3821
  const defaultPort = isSecure ? 443 : 80;
3268
3822
  const key = randomBytes(16).toString('base64');
3269
- const get = isSecure ? https.get : http$1.get;
3823
+ const request = isSecure ? https.request : http.request;
3824
+ const protocolSet = new Set();
3270
3825
  let perMessageDeflate;
3271
3826
 
3272
- opts.createConnection = isSecure ? tlsConnect : netConnect;
3827
+ opts.createConnection =
3828
+ opts.createConnection || (isSecure ? tlsConnect : netConnect);
3273
3829
  opts.defaultPort = opts.defaultPort || defaultPort;
3274
3830
  opts.port = parsedUrl.port || defaultPort;
3275
3831
  opts.host = parsedUrl.hostname.startsWith('[')
3276
3832
  ? parsedUrl.hostname.slice(1, -1)
3277
3833
  : parsedUrl.hostname;
3278
3834
  opts.headers = {
3835
+ ...opts.headers,
3279
3836
  'Sec-WebSocket-Version': opts.protocolVersion,
3280
3837
  'Sec-WebSocket-Key': key,
3281
3838
  Connection: 'Upgrade',
3282
- Upgrade: 'websocket',
3283
- ...opts.headers
3839
+ Upgrade: 'websocket'
3284
3840
  };
3285
3841
  opts.path = parsedUrl.pathname + parsedUrl.search;
3286
3842
  opts.timeout = opts.handshakeTimeout;
3287
3843
 
3288
3844
  if (opts.perMessageDeflate) {
3289
- perMessageDeflate = new PerMessageDeflate$1(
3290
- opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
3291
- false,
3292
- opts.maxPayload
3293
- );
3294
- opts.headers['Sec-WebSocket-Extensions'] = format$1({
3295
- [PerMessageDeflate$1.extensionName]: perMessageDeflate.offer()
3845
+ perMessageDeflate = new PerMessageDeflate({
3846
+ ...opts.perMessageDeflate,
3847
+ isServer: false,
3848
+ maxPayload: opts.maxPayload
3849
+ });
3850
+ opts.headers['Sec-WebSocket-Extensions'] = format({
3851
+ [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
3296
3852
  });
3297
3853
  }
3298
- if (protocols) {
3299
- opts.headers['Sec-WebSocket-Protocol'] = protocols;
3854
+ if (protocols.length) {
3855
+ for (const protocol of protocols) {
3856
+ if (
3857
+ typeof protocol !== 'string' ||
3858
+ !subprotocolRegex.test(protocol) ||
3859
+ protocolSet.has(protocol)
3860
+ ) {
3861
+ throw new SyntaxError(
3862
+ 'An invalid or duplicated subprotocol was specified'
3863
+ );
3864
+ }
3865
+
3866
+ protocolSet.add(protocol);
3867
+ }
3868
+
3869
+ opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');
3300
3870
  }
3301
3871
  if (opts.origin) {
3302
3872
  if (opts.protocolVersion < 13) {
@@ -3309,18 +3879,20 @@ function initAsClient(websocket, address, protocols, options) {
3309
3879
  opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
3310
3880
  }
3311
3881
 
3312
- if (isUnixSocket) {
3882
+ if (isIpcUrl) {
3313
3883
  const parts = opts.path.split(':');
3314
3884
 
3315
3885
  opts.socketPath = parts[0];
3316
3886
  opts.path = parts[1];
3317
3887
  }
3318
3888
 
3889
+ let req;
3890
+
3319
3891
  if (opts.followRedirects) {
3320
3892
  if (websocket._redirects === 0) {
3321
- websocket._originalUnixSocket = isUnixSocket;
3893
+ websocket._originalIpc = isIpcUrl;
3322
3894
  websocket._originalSecure = isSecure;
3323
- websocket._originalHostOrSocketPath = isUnixSocket
3895
+ websocket._originalHostOrSocketPath = isIpcUrl
3324
3896
  ? opts.socketPath
3325
3897
  : parsedUrl.host;
3326
3898
 
@@ -3337,14 +3909,14 @@ function initAsClient(websocket, address, protocols, options) {
3337
3909
  options.headers[key.toLowerCase()] = value;
3338
3910
  }
3339
3911
  }
3340
- } else {
3341
- const isSameHost = isUnixSocket
3342
- ? websocket._originalUnixSocket
3912
+ } else if (websocket.listenerCount('redirect') === 0) {
3913
+ const isSameHost = isIpcUrl
3914
+ ? websocket._originalIpc
3343
3915
  ? opts.socketPath === websocket._originalHostOrSocketPath
3344
3916
  : false
3345
- : websocket._originalUnixSocket
3346
- ? false
3347
- : parsedUrl.host === websocket._originalHostOrSocketPath;
3917
+ : websocket._originalIpc
3918
+ ? false
3919
+ : parsedUrl.host === websocket._originalHostOrSocketPath;
3348
3920
 
3349
3921
  if (!isSameHost || (websocket._originalSecure && !isSecure)) {
3350
3922
  //
@@ -3369,18 +3941,33 @@ function initAsClient(websocket, address, protocols, options) {
3369
3941
  options.headers.authorization =
3370
3942
  'Basic ' + Buffer.from(opts.auth).toString('base64');
3371
3943
  }
3372
- }
3373
3944
 
3374
- let req = (websocket._req = get(opts));
3945
+ req = websocket._req = request(opts);
3946
+
3947
+ if (websocket._redirects) {
3948
+ //
3949
+ // Unlike what is done for the `'upgrade'` event, no early exit is
3950
+ // triggered here if the user calls `websocket.close()` or
3951
+ // `websocket.terminate()` from a listener of the `'redirect'` event. This
3952
+ // is because the user can also call `request.destroy()` with an error
3953
+ // before calling `websocket.close()` or `websocket.terminate()` and this
3954
+ // would result in an error being emitted on the `request` object with no
3955
+ // `'error'` event listeners attached.
3956
+ //
3957
+ websocket.emit('redirect', websocket.url, req);
3958
+ }
3959
+ } else {
3960
+ req = websocket._req = request(opts);
3961
+ }
3375
3962
 
3376
3963
  if (opts.timeout) {
3377
3964
  req.on('timeout', () => {
3378
- abortHandshake$1(websocket, req, 'Opening handshake has timed out');
3965
+ abortHandshake(websocket, req, 'Opening handshake has timed out');
3379
3966
  });
3380
3967
  }
3381
3968
 
3382
3969
  req.on('error', (err) => {
3383
- if (req === null || req.aborted) return;
3970
+ if (req === null || req[kAborted]) return;
3384
3971
 
3385
3972
  req = websocket._req = null;
3386
3973
  emitErrorAndClose(websocket, err);
@@ -3397,7 +3984,7 @@ function initAsClient(websocket, address, protocols, options) {
3397
3984
  statusCode < 400
3398
3985
  ) {
3399
3986
  if (++websocket._redirects > opts.maxRedirects) {
3400
- abortHandshake$1(websocket, req, 'Maximum redirects exceeded');
3987
+ abortHandshake(websocket, req, 'Maximum redirects exceeded');
3401
3988
  return;
3402
3989
  }
3403
3990
 
@@ -3407,14 +3994,15 @@ function initAsClient(websocket, address, protocols, options) {
3407
3994
 
3408
3995
  try {
3409
3996
  addr = new URL(location, address);
3410
- } catch (err) {
3997
+ } catch (e) {
3998
+ const err = new SyntaxError(`Invalid URL: ${location}`);
3411
3999
  emitErrorAndClose(websocket, err);
3412
4000
  return;
3413
4001
  }
3414
4002
 
3415
4003
  initAsClient(websocket, addr, protocols, options);
3416
4004
  } else if (!websocket.emit('unexpected-response', req, res)) {
3417
- abortHandshake$1(
4005
+ abortHandshake(
3418
4006
  websocket,
3419
4007
  req,
3420
4008
  `Unexpected server response: ${res.statusCode}`
@@ -3426,17 +4014,17 @@ function initAsClient(websocket, address, protocols, options) {
3426
4014
  websocket.emit('upgrade', res);
3427
4015
 
3428
4016
  //
3429
- // The user may have closed the connection from a listener of the `upgrade`
3430
- // event.
4017
+ // The user may have closed the connection from a listener of the
4018
+ // `'upgrade'` event.
3431
4019
  //
3432
- if (websocket.readyState !== WebSocket$3.CONNECTING) return;
4020
+ if (websocket.readyState !== WebSocket$1.CONNECTING) return;
3433
4021
 
3434
4022
  req = websocket._req = null;
3435
4023
 
3436
4024
  const upgrade = res.headers.upgrade;
3437
4025
 
3438
4026
  if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
3439
- abortHandshake$1(websocket, socket, 'Invalid Upgrade header');
4027
+ abortHandshake(websocket, socket, 'Invalid Upgrade header');
3440
4028
  return;
3441
4029
  }
3442
4030
 
@@ -3445,24 +4033,25 @@ function initAsClient(websocket, address, protocols, options) {
3445
4033
  .digest('base64');
3446
4034
 
3447
4035
  if (res.headers['sec-websocket-accept'] !== digest) {
3448
- abortHandshake$1(websocket, socket, 'Invalid Sec-WebSocket-Accept header');
4036
+ abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');
3449
4037
  return;
3450
4038
  }
3451
4039
 
3452
4040
  const serverProt = res.headers['sec-websocket-protocol'];
3453
- const protList = (protocols || '').split(/, */);
3454
4041
  let protError;
3455
4042
 
3456
- if (!protocols && serverProt) {
3457
- protError = 'Server sent a subprotocol but none was requested';
3458
- } else if (protocols && !serverProt) {
4043
+ if (serverProt !== undefined) {
4044
+ if (!protocolSet.size) {
4045
+ protError = 'Server sent a subprotocol but none was requested';
4046
+ } else if (!protocolSet.has(serverProt)) {
4047
+ protError = 'Server sent an invalid subprotocol';
4048
+ }
4049
+ } else if (protocolSet.size) {
3459
4050
  protError = 'Server sent no subprotocol';
3460
- } else if (serverProt && !protList.includes(serverProt)) {
3461
- protError = 'Server sent an invalid subprotocol';
3462
4051
  }
3463
4052
 
3464
4053
  if (protError) {
3465
- abortHandshake$1(websocket, socket, protError);
4054
+ abortHandshake(websocket, socket, protError);
3466
4055
  return;
3467
4056
  }
3468
4057
 
@@ -3475,59 +4064,72 @@ function initAsClient(websocket, address, protocols, options) {
3475
4064
  const message =
3476
4065
  'Server sent a Sec-WebSocket-Extensions header but no extension ' +
3477
4066
  'was requested';
3478
- abortHandshake$1(websocket, socket, message);
4067
+ abortHandshake(websocket, socket, message);
3479
4068
  return;
3480
4069
  }
3481
4070
 
3482
4071
  let extensions;
3483
4072
 
3484
4073
  try {
3485
- extensions = parse$1(secWebSocketExtensions);
4074
+ extensions = parse(secWebSocketExtensions);
3486
4075
  } catch (err) {
3487
4076
  const message = 'Invalid Sec-WebSocket-Extensions header';
3488
- abortHandshake$1(websocket, socket, message);
4077
+ abortHandshake(websocket, socket, message);
3489
4078
  return;
3490
4079
  }
3491
4080
 
3492
4081
  const extensionNames = Object.keys(extensions);
3493
4082
 
3494
- if (extensionNames.length) {
3495
- if (
3496
- extensionNames.length !== 1 ||
3497
- extensionNames[0] !== PerMessageDeflate$1.extensionName
3498
- ) {
3499
- const message =
3500
- 'Server indicated an extension that was not requested';
3501
- abortHandshake$1(websocket, socket, message);
3502
- return;
3503
- }
3504
-
3505
- try {
3506
- perMessageDeflate.accept(extensions[PerMessageDeflate$1.extensionName]);
3507
- } catch (err) {
3508
- const message = 'Invalid Sec-WebSocket-Extensions header';
3509
- abortHandshake$1(websocket, socket, message);
3510
- return;
3511
- }
4083
+ if (
4084
+ extensionNames.length !== 1 ||
4085
+ extensionNames[0] !== PerMessageDeflate.extensionName
4086
+ ) {
4087
+ const message = 'Server indicated an extension that was not requested';
4088
+ abortHandshake(websocket, socket, message);
4089
+ return;
4090
+ }
3512
4091
 
3513
- websocket._extensions[PerMessageDeflate$1.extensionName] =
3514
- perMessageDeflate;
4092
+ try {
4093
+ perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
4094
+ } catch (err) {
4095
+ const message = 'Invalid Sec-WebSocket-Extensions header';
4096
+ abortHandshake(websocket, socket, message);
4097
+ return;
3515
4098
  }
4099
+
4100
+ websocket._extensions[PerMessageDeflate.extensionName] =
4101
+ perMessageDeflate;
3516
4102
  }
3517
4103
 
3518
- websocket.setSocket(socket, head, opts.maxPayload);
4104
+ websocket.setSocket(socket, head, {
4105
+ allowSynchronousEvents: opts.allowSynchronousEvents,
4106
+ generateMask: opts.generateMask,
4107
+ maxPayload: opts.maxPayload,
4108
+ skipUTF8Validation: opts.skipUTF8Validation
4109
+ });
3519
4110
  });
4111
+
4112
+ if (opts.finishRequest) {
4113
+ opts.finishRequest(req, websocket);
4114
+ } else {
4115
+ req.end();
4116
+ }
3520
4117
  }
3521
4118
 
3522
4119
  /**
3523
- * Emit the `'error'` and `'close'` event.
4120
+ * Emit the `'error'` and `'close'` events.
3524
4121
  *
3525
4122
  * @param {WebSocket} websocket The WebSocket instance
3526
4123
  * @param {Error} The error to emit
3527
4124
  * @private
3528
4125
  */
3529
4126
  function emitErrorAndClose(websocket, err) {
3530
- websocket._readyState = WebSocket$3.CLOSING;
4127
+ websocket._readyState = WebSocket$1.CLOSING;
4128
+ //
4129
+ // The following assignment is practically useless and is done only for
4130
+ // consistency.
4131
+ //
4132
+ websocket._errorEmitted = true;
3531
4133
  websocket.emit('error', err);
3532
4134
  websocket.emitClose();
3533
4135
  }
@@ -3570,13 +4172,14 @@ function tlsConnect(options) {
3570
4172
  * @param {String} message The error message
3571
4173
  * @private
3572
4174
  */
3573
- function abortHandshake$1(websocket, stream, message) {
3574
- websocket._readyState = WebSocket$3.CLOSING;
4175
+ function abortHandshake(websocket, stream, message) {
4176
+ websocket._readyState = WebSocket$1.CLOSING;
3575
4177
 
3576
4178
  const err = new Error(message);
3577
- Error.captureStackTrace(err, abortHandshake$1);
4179
+ Error.captureStackTrace(err, abortHandshake);
3578
4180
 
3579
4181
  if (stream.setHeader) {
4182
+ stream[kAborted] = true;
3580
4183
  stream.abort();
3581
4184
 
3582
4185
  if (stream.socket && !stream.socket.destroyed) {
@@ -3588,8 +4191,7 @@ function abortHandshake$1(websocket, stream, message) {
3588
4191
  stream.socket.destroy();
3589
4192
  }
3590
4193
 
3591
- stream.once('abort', websocket.emitClose.bind(websocket));
3592
- websocket.emit('error', err);
4194
+ process.nextTick(emitErrorAndClose, websocket, err);
3593
4195
  } else {
3594
4196
  stream.destroy(err);
3595
4197
  stream.once('error', websocket.emit.bind(websocket, 'error'));
@@ -3608,7 +4210,7 @@ function abortHandshake$1(websocket, stream, message) {
3608
4210
  */
3609
4211
  function sendAfterClose(websocket, data, cb) {
3610
4212
  if (data) {
3611
- const length = toBuffer(data).length;
4213
+ const length = isBlob(data) ? data.size : toBuffer(data).length;
3612
4214
 
3613
4215
  //
3614
4216
  // The `_bufferedAmount` property is used only when the peer is a client and
@@ -3625,7 +4227,7 @@ function sendAfterClose(websocket, data, cb) {
3625
4227
  `WebSocket is not open: readyState ${websocket.readyState} ` +
3626
4228
  `(${readyStates[websocket.readyState]})`
3627
4229
  );
3628
- cb(err);
4230
+ process.nextTick(cb, err);
3629
4231
  }
3630
4232
  }
3631
4233
 
@@ -3633,7 +4235,7 @@ function sendAfterClose(websocket, data, cb) {
3633
4235
  * The listener of the `Receiver` `'conclude'` event.
3634
4236
  *
3635
4237
  * @param {Number} code The status code
3636
- * @param {String} reason The reason for closing
4238
+ * @param {Buffer} reason The reason for closing
3637
4239
  * @private
3638
4240
  */
3639
4241
  function receiverOnConclude(code, reason) {
@@ -3658,7 +4260,9 @@ function receiverOnConclude(code, reason) {
3658
4260
  * @private
3659
4261
  */
3660
4262
  function receiverOnDrain() {
3661
- this[kWebSocket$1]._socket.resume();
4263
+ const websocket = this[kWebSocket$1];
4264
+
4265
+ if (!websocket.isPaused) websocket._socket.resume();
3662
4266
  }
3663
4267
 
3664
4268
  /**
@@ -3682,7 +4286,10 @@ function receiverOnError(err) {
3682
4286
  websocket.close(err[kStatusCode]);
3683
4287
  }
3684
4288
 
3685
- websocket.emit('error', err);
4289
+ if (!websocket._errorEmitted) {
4290
+ websocket._errorEmitted = true;
4291
+ websocket.emit('error', err);
4292
+ }
3686
4293
  }
3687
4294
 
3688
4295
  /**
@@ -3697,11 +4304,12 @@ function receiverOnFinish() {
3697
4304
  /**
3698
4305
  * The listener of the `Receiver` `'message'` event.
3699
4306
  *
3700
- * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The message
4307
+ * @param {Buffer|ArrayBuffer|Buffer[])} data The message
4308
+ * @param {Boolean} isBinary Specifies whether the message is binary or not
3701
4309
  * @private
3702
4310
  */
3703
- function receiverOnMessage(data) {
3704
- this[kWebSocket$1].emit('message', data);
4311
+ function receiverOnMessage(data, isBinary) {
4312
+ this[kWebSocket$1].emit('message', data, isBinary);
3705
4313
  }
3706
4314
 
3707
4315
  /**
@@ -3713,7 +4321,7 @@ function receiverOnMessage(data) {
3713
4321
  function receiverOnPing(data) {
3714
4322
  const websocket = this[kWebSocket$1];
3715
4323
 
3716
- websocket.pong(data, !websocket._isServer, NOOP);
4324
+ if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
3717
4325
  websocket.emit('ping', data);
3718
4326
  }
3719
4327
 
@@ -3738,7 +4346,48 @@ function resume(stream) {
3738
4346
  }
3739
4347
 
3740
4348
  /**
3741
- * The listener of the `net.Socket` `'close'` event.
4349
+ * The `Sender` error event handler.
4350
+ *
4351
+ * @param {Error} The error
4352
+ * @private
4353
+ */
4354
+ function senderOnError(err) {
4355
+ const websocket = this[kWebSocket$1];
4356
+
4357
+ if (websocket.readyState === WebSocket$1.CLOSED) return;
4358
+ if (websocket.readyState === WebSocket$1.OPEN) {
4359
+ websocket._readyState = WebSocket$1.CLOSING;
4360
+ setCloseTimer(websocket);
4361
+ }
4362
+
4363
+ //
4364
+ // `socket.end()` is used instead of `socket.destroy()` to allow the other
4365
+ // peer to finish sending queued data. There is no need to set a timer here
4366
+ // because `CLOSING` means that it is already set or not needed.
4367
+ //
4368
+ this._socket.end();
4369
+
4370
+ if (!websocket._errorEmitted) {
4371
+ websocket._errorEmitted = true;
4372
+ websocket.emit('error', err);
4373
+ }
4374
+ }
4375
+
4376
+ /**
4377
+ * Set a timer to destroy the underlying raw socket of a WebSocket.
4378
+ *
4379
+ * @param {WebSocket} websocket The WebSocket instance
4380
+ * @private
4381
+ */
4382
+ function setCloseTimer(websocket) {
4383
+ websocket._closeTimer = setTimeout(
4384
+ websocket._socket.destroy.bind(websocket._socket),
4385
+ websocket._closeTimeout
4386
+ );
4387
+ }
4388
+
4389
+ /**
4390
+ * The listener of the socket `'close'` event.
3742
4391
  *
3743
4392
  * @private
3744
4393
  */
@@ -3749,25 +4398,25 @@ function socketOnClose() {
3749
4398
  this.removeListener('data', socketOnData);
3750
4399
  this.removeListener('end', socketOnEnd);
3751
4400
 
3752
- websocket._readyState = WebSocket$3.CLOSING;
3753
-
3754
- let chunk;
4401
+ websocket._readyState = WebSocket$1.CLOSING;
3755
4402
 
3756
4403
  //
3757
4404
  // The close frame might not have been received or the `'end'` event emitted,
3758
4405
  // for example, if the socket was destroyed due to an error. Ensure that the
3759
4406
  // `receiver` stream is closed after writing any remaining buffered data to
3760
4407
  // it. If the readable side of the socket is in flowing mode then there is no
3761
- // buffered data as everything has been already written and `readable.read()`
3762
- // will return `null`. If instead, the socket is paused, any possible buffered
3763
- // data will be read as a single chunk.
4408
+ // buffered data as everything has been already written. If instead, the
4409
+ // socket is paused, any possible buffered data will be read as a single
4410
+ // chunk.
3764
4411
  //
3765
4412
  if (
3766
4413
  !this._readableState.endEmitted &&
3767
4414
  !websocket._closeFrameReceived &&
3768
4415
  !websocket._receiver._writableState.errorEmitted &&
3769
- (chunk = websocket._socket.read()) !== null
4416
+ this._readableState.length !== 0
3770
4417
  ) {
4418
+ const chunk = this.read(this._readableState.length);
4419
+
3771
4420
  websocket._receiver.write(chunk);
3772
4421
  }
3773
4422
 
@@ -3789,7 +4438,7 @@ function socketOnClose() {
3789
4438
  }
3790
4439
 
3791
4440
  /**
3792
- * The listener of the `net.Socket` `'data'` event.
4441
+ * The listener of the socket `'data'` event.
3793
4442
  *
3794
4443
  * @param {Buffer} chunk A chunk of data
3795
4444
  * @private
@@ -3801,680 +4450,54 @@ function socketOnData(chunk) {
3801
4450
  }
3802
4451
 
3803
4452
  /**
3804
- * The listener of the `net.Socket` `'end'` event.
4453
+ * The listener of the socket `'end'` event.
3805
4454
  *
3806
4455
  * @private
3807
4456
  */
3808
4457
  function socketOnEnd() {
3809
4458
  const websocket = this[kWebSocket$1];
3810
4459
 
3811
- websocket._readyState = WebSocket$3.CLOSING;
4460
+ websocket._readyState = WebSocket$1.CLOSING;
3812
4461
  websocket._receiver.end();
3813
4462
  this.end();
3814
4463
  }
3815
4464
 
3816
4465
  /**
3817
- * The listener of the `net.Socket` `'error'` event.
4466
+ * The listener of the socket `'error'` event.
3818
4467
  *
3819
4468
  * @private
3820
4469
  */
3821
- function socketOnError$1() {
4470
+ function socketOnError() {
3822
4471
  const websocket = this[kWebSocket$1];
3823
4472
 
3824
- this.removeListener('error', socketOnError$1);
4473
+ this.removeListener('error', socketOnError);
3825
4474
  this.on('error', NOOP);
3826
4475
 
3827
4476
  if (websocket) {
3828
- websocket._readyState = WebSocket$3.CLOSING;
3829
- this.destroy();
3830
- }
3831
- }
3832
-
3833
- const { Duplex } = require$$0$2;
3834
-
3835
- /**
3836
- * Emits the `'close'` event on a stream.
3837
- *
3838
- * @param {Duplex} stream The stream.
3839
- * @private
3840
- */
3841
- function emitClose$1(stream) {
3842
- stream.emit('close');
3843
- }
3844
-
3845
- /**
3846
- * The listener of the `'end'` event.
3847
- *
3848
- * @private
3849
- */
3850
- function duplexOnEnd() {
3851
- if (!this.destroyed && this._writableState.finished) {
4477
+ websocket._readyState = WebSocket$1.CLOSING;
3852
4478
  this.destroy();
3853
4479
  }
3854
4480
  }
3855
4481
 
3856
- /**
3857
- * The listener of the `'error'` event.
3858
- *
3859
- * @param {Error} err The error
3860
- * @private
3861
- */
3862
- function duplexOnError(err) {
3863
- this.removeListener('error', duplexOnError);
3864
- this.destroy();
3865
- if (this.listenerCount('error') === 0) {
3866
- // Do not suppress the throwing behavior.
3867
- this.emit('error', err);
3868
- }
3869
- }
3870
-
3871
- /**
3872
- * Wraps a `WebSocket` in a duplex stream.
3873
- *
3874
- * @param {WebSocket} ws The `WebSocket` to wrap
3875
- * @param {Object} [options] The options for the `Duplex` constructor
3876
- * @return {Duplex} The duplex stream
3877
- * @public
3878
- */
3879
- function createWebSocketStream(ws, options) {
3880
- let resumeOnReceiverDrain = true;
3881
- let terminateOnDestroy = true;
3882
-
3883
- function receiverOnDrain() {
3884
- if (resumeOnReceiverDrain) ws._socket.resume();
3885
- }
3886
-
3887
- if (ws.readyState === ws.CONNECTING) {
3888
- ws.once('open', function open() {
3889
- ws._receiver.removeAllListeners('drain');
3890
- ws._receiver.on('drain', receiverOnDrain);
3891
- });
3892
- } else {
3893
- ws._receiver.removeAllListeners('drain');
3894
- ws._receiver.on('drain', receiverOnDrain);
3895
- }
3896
-
3897
- const duplex = new Duplex({
3898
- ...options,
3899
- autoDestroy: false,
3900
- emitClose: false,
3901
- objectMode: false,
3902
- writableObjectMode: false
3903
- });
3904
-
3905
- ws.on('message', function message(msg) {
3906
- if (!duplex.push(msg)) {
3907
- resumeOnReceiverDrain = false;
3908
- ws._socket.pause();
3909
- }
3910
- });
3911
-
3912
- ws.once('error', function error(err) {
3913
- if (duplex.destroyed) return;
3914
-
3915
- // Prevent `ws.terminate()` from being called by `duplex._destroy()`.
3916
- //
3917
- // - If the `'error'` event is emitted before the `'open'` event, then
3918
- // `ws.terminate()` is a noop as no socket is assigned.
3919
- // - Otherwise, the error is re-emitted by the listener of the `'error'`
3920
- // event of the `Receiver` object. The listener already closes the
3921
- // connection by calling `ws.close()`. This allows a close frame to be
3922
- // sent to the other peer. If `ws.terminate()` is called right after this,
3923
- // then the close frame might not be sent.
3924
- terminateOnDestroy = false;
3925
- duplex.destroy(err);
3926
- });
3927
-
3928
- ws.once('close', function close() {
3929
- if (duplex.destroyed) return;
3930
-
3931
- duplex.push(null);
3932
- });
3933
-
3934
- duplex._destroy = function (err, callback) {
3935
- if (ws.readyState === ws.CLOSED) {
3936
- callback(err);
3937
- process.nextTick(emitClose$1, duplex);
3938
- return;
3939
- }
3940
-
3941
- let called = false;
3942
-
3943
- ws.once('error', function error(err) {
3944
- called = true;
3945
- callback(err);
3946
- });
3947
-
3948
- ws.once('close', function close() {
3949
- if (!called) callback(err);
3950
- process.nextTick(emitClose$1, duplex);
3951
- });
3952
-
3953
- if (terminateOnDestroy) ws.terminate();
3954
- };
3955
-
3956
- duplex._final = function (callback) {
3957
- if (ws.readyState === ws.CONNECTING) {
3958
- ws.once('open', function open() {
3959
- duplex._final(callback);
3960
- });
3961
- return;
3962
- }
3963
-
3964
- // If the value of the `_socket` property is `null` it means that `ws` is a
3965
- // client websocket and the handshake failed. In fact, when this happens, a
3966
- // socket is never assigned to the websocket. Wait for the `'error'` event
3967
- // that will be emitted by the websocket.
3968
- if (ws._socket === null) return;
3969
-
3970
- if (ws._socket._writableState.finished) {
3971
- callback();
3972
- if (duplex._readableState.endEmitted) duplex.destroy();
3973
- } else {
3974
- ws._socket.once('finish', function finish() {
3975
- // `duplex` is not destroyed here because the `'end'` event will be
3976
- // emitted on `duplex` after this `'finish'` event. The EOF signaling
3977
- // `null` chunk is, in fact, pushed when the websocket emits `'close'`.
3978
- callback();
3979
- });
3980
- ws.close();
3981
- }
3982
- };
3983
-
3984
- duplex._read = function () {
3985
- if (
3986
- (ws.readyState === ws.OPEN || ws.readyState === ws.CLOSING) &&
3987
- !resumeOnReceiverDrain
3988
- ) {
3989
- resumeOnReceiverDrain = true;
3990
- if (!ws._receiver._writableState.needDrain) ws._socket.resume();
3991
- }
3992
- };
3993
-
3994
- duplex._write = function (chunk, encoding, callback) {
3995
- if (ws.readyState === ws.CONNECTING) {
3996
- ws.once('open', function open() {
3997
- duplex._write(chunk, encoding, callback);
3998
- });
3999
- return;
4000
- }
4001
-
4002
- ws.send(chunk, callback);
4003
- };
4004
-
4005
- duplex.on('end', duplexOnEnd);
4006
- duplex.on('error', duplexOnError);
4007
- return duplex;
4008
- }
4009
-
4010
- var stream = createWebSocketStream;
4011
-
4012
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^net|tls|https$" }] */
4013
-
4014
- const EventEmitter = require$$0$3;
4015
- const http = require$$2$1;
4016
- const { createHash } = require$$5;
4017
-
4018
- const PerMessageDeflate = permessageDeflate;
4019
- const WebSocket$2 = websocket;
4020
- const { format, parse } = extension;
4021
- const { GUID, kWebSocket } = constants;
4022
-
4023
- const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
4024
-
4025
- const RUNNING = 0;
4026
- const CLOSING = 1;
4027
- const CLOSED = 2;
4028
-
4029
- /**
4030
- * Class representing a WebSocket server.
4031
- *
4032
- * @extends EventEmitter
4033
- */
4034
- class WebSocketServer extends EventEmitter {
4035
- /**
4036
- * Create a `WebSocketServer` instance.
4037
- *
4038
- * @param {Object} options Configuration options
4039
- * @param {Number} [options.backlog=511] The maximum length of the queue of
4040
- * pending connections
4041
- * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
4042
- * track clients
4043
- * @param {Function} [options.handleProtocols] A hook to handle protocols
4044
- * @param {String} [options.host] The hostname where to bind the server
4045
- * @param {Number} [options.maxPayload=104857600] The maximum allowed message
4046
- * size
4047
- * @param {Boolean} [options.noServer=false] Enable no server mode
4048
- * @param {String} [options.path] Accept only connections matching this path
4049
- * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
4050
- * permessage-deflate
4051
- * @param {Number} [options.port] The port where to bind the server
4052
- * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
4053
- * server to use
4054
- * @param {Function} [options.verifyClient] A hook to reject connections
4055
- * @param {Function} [callback] A listener for the `listening` event
4056
- */
4057
- constructor(options, callback) {
4058
- super();
4059
-
4060
- options = {
4061
- maxPayload: 100 * 1024 * 1024,
4062
- perMessageDeflate: false,
4063
- handleProtocols: null,
4064
- clientTracking: true,
4065
- verifyClient: null,
4066
- noServer: false,
4067
- backlog: null, // use default (511 as implemented in net.js)
4068
- server: null,
4069
- host: null,
4070
- path: null,
4071
- port: null,
4072
- ...options
4073
- };
4074
-
4075
- if (
4076
- (options.port == null && !options.server && !options.noServer) ||
4077
- (options.port != null && (options.server || options.noServer)) ||
4078
- (options.server && options.noServer)
4079
- ) {
4080
- throw new TypeError(
4081
- 'One and only one of the "port", "server", or "noServer" options ' +
4082
- 'must be specified'
4083
- );
4084
- }
4085
-
4086
- if (options.port != null) {
4087
- this._server = http.createServer((req, res) => {
4088
- const body = http.STATUS_CODES[426];
4089
-
4090
- res.writeHead(426, {
4091
- 'Content-Length': body.length,
4092
- 'Content-Type': 'text/plain'
4093
- });
4094
- res.end(body);
4095
- });
4096
- this._server.listen(
4097
- options.port,
4098
- options.host,
4099
- options.backlog,
4100
- callback
4101
- );
4102
- } else if (options.server) {
4103
- this._server = options.server;
4104
- }
4105
-
4106
- if (this._server) {
4107
- const emitConnection = this.emit.bind(this, 'connection');
4108
-
4109
- this._removeListeners = addListeners(this._server, {
4110
- listening: this.emit.bind(this, 'listening'),
4111
- error: this.emit.bind(this, 'error'),
4112
- upgrade: (req, socket, head) => {
4113
- this.handleUpgrade(req, socket, head, emitConnection);
4114
- }
4115
- });
4116
- }
4117
-
4118
- if (options.perMessageDeflate === true) options.perMessageDeflate = {};
4119
- if (options.clientTracking) this.clients = new Set();
4120
- this.options = options;
4121
- this._state = RUNNING;
4122
- }
4123
-
4124
- /**
4125
- * Returns the bound address, the address family name, and port of the server
4126
- * as reported by the operating system if listening on an IP socket.
4127
- * If the server is listening on a pipe or UNIX domain socket, the name is
4128
- * returned as a string.
4129
- *
4130
- * @return {(Object|String|null)} The address of the server
4131
- * @public
4132
- */
4133
- address() {
4134
- if (this.options.noServer) {
4135
- throw new Error('The server is operating in "noServer" mode');
4136
- }
4137
-
4138
- if (!this._server) return null;
4139
- return this._server.address();
4140
- }
4141
-
4142
- /**
4143
- * Close the server.
4144
- *
4145
- * @param {Function} [cb] Callback
4146
- * @public
4147
- */
4148
- close(cb) {
4149
- if (cb) this.once('close', cb);
4150
-
4151
- if (this._state === CLOSED) {
4152
- process.nextTick(emitClose, this);
4153
- return;
4154
- }
4155
-
4156
- if (this._state === CLOSING) return;
4157
- this._state = CLOSING;
4158
-
4159
- //
4160
- // Terminate all associated clients.
4161
- //
4162
- if (this.clients) {
4163
- for (const client of this.clients) client.terminate();
4164
- }
4165
-
4166
- const server = this._server;
4167
-
4168
- if (server) {
4169
- this._removeListeners();
4170
- this._removeListeners = this._server = null;
4171
-
4172
- //
4173
- // Close the http server if it was internally created.
4174
- //
4175
- if (this.options.port != null) {
4176
- server.close(emitClose.bind(undefined, this));
4177
- return;
4178
- }
4179
- }
4180
-
4181
- process.nextTick(emitClose, this);
4182
- }
4183
-
4184
- /**
4185
- * See if a given request should be handled by this server instance.
4186
- *
4187
- * @param {http.IncomingMessage} req Request object to inspect
4188
- * @return {Boolean} `true` if the request is valid, else `false`
4189
- * @public
4190
- */
4191
- shouldHandle(req) {
4192
- if (this.options.path) {
4193
- const index = req.url.indexOf('?');
4194
- const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
4195
-
4196
- if (pathname !== this.options.path) return false;
4197
- }
4198
-
4199
- return true;
4200
- }
4201
-
4202
- /**
4203
- * Handle a HTTP Upgrade request.
4204
- *
4205
- * @param {http.IncomingMessage} req The request object
4206
- * @param {(net.Socket|tls.Socket)} socket The network socket between the
4207
- * server and client
4208
- * @param {Buffer} head The first packet of the upgraded stream
4209
- * @param {Function} cb Callback
4210
- * @public
4211
- */
4212
- handleUpgrade(req, socket, head, cb) {
4213
- socket.on('error', socketOnError);
4214
-
4215
- const key =
4216
- req.headers['sec-websocket-key'] !== undefined
4217
- ? req.headers['sec-websocket-key'].trim()
4218
- : false;
4219
- const upgrade = req.headers.upgrade;
4220
- const version = +req.headers['sec-websocket-version'];
4221
- const extensions = {};
4222
-
4223
- if (
4224
- req.method !== 'GET' ||
4225
- upgrade === undefined ||
4226
- upgrade.toLowerCase() !== 'websocket' ||
4227
- !key ||
4228
- !keyRegex.test(key) ||
4229
- (version !== 8 && version !== 13) ||
4230
- !this.shouldHandle(req)
4231
- ) {
4232
- return abortHandshake(socket, 400);
4233
- }
4234
-
4235
- if (this.options.perMessageDeflate) {
4236
- const perMessageDeflate = new PerMessageDeflate(
4237
- this.options.perMessageDeflate,
4238
- true,
4239
- this.options.maxPayload
4240
- );
4241
-
4242
- try {
4243
- const offers = parse(req.headers['sec-websocket-extensions']);
4244
-
4245
- if (offers[PerMessageDeflate.extensionName]) {
4246
- perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
4247
- extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
4248
- }
4249
- } catch (err) {
4250
- return abortHandshake(socket, 400);
4251
- }
4252
- }
4253
-
4254
- //
4255
- // Optionally call external client verification handler.
4256
- //
4257
- if (this.options.verifyClient) {
4258
- const info = {
4259
- origin:
4260
- req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],
4261
- secure: !!(req.socket.authorized || req.socket.encrypted),
4262
- req
4263
- };
4264
-
4265
- if (this.options.verifyClient.length === 2) {
4266
- this.options.verifyClient(info, (verified, code, message, headers) => {
4267
- if (!verified) {
4268
- return abortHandshake(socket, code || 401, message, headers);
4269
- }
4270
-
4271
- this.completeUpgrade(key, extensions, req, socket, head, cb);
4272
- });
4273
- return;
4274
- }
4275
-
4276
- if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
4277
- }
4278
-
4279
- this.completeUpgrade(key, extensions, req, socket, head, cb);
4280
- }
4281
-
4282
- /**
4283
- * Upgrade the connection to WebSocket.
4284
- *
4285
- * @param {String} key The value of the `Sec-WebSocket-Key` header
4286
- * @param {Object} extensions The accepted extensions
4287
- * @param {http.IncomingMessage} req The request object
4288
- * @param {(net.Socket|tls.Socket)} socket The network socket between the
4289
- * server and client
4290
- * @param {Buffer} head The first packet of the upgraded stream
4291
- * @param {Function} cb Callback
4292
- * @throws {Error} If called more than once with the same socket
4293
- * @private
4294
- */
4295
- completeUpgrade(key, extensions, req, socket, head, cb) {
4296
- //
4297
- // Destroy the socket if the client has already sent a FIN packet.
4298
- //
4299
- if (!socket.readable || !socket.writable) return socket.destroy();
4300
-
4301
- if (socket[kWebSocket]) {
4302
- throw new Error(
4303
- 'server.handleUpgrade() was called more than once with the same ' +
4304
- 'socket, possibly due to a misconfiguration'
4305
- );
4306
- }
4307
-
4308
- if (this._state > RUNNING) return abortHandshake(socket, 503);
4309
-
4310
- const digest = createHash('sha1')
4311
- .update(key + GUID)
4312
- .digest('base64');
4313
-
4314
- const headers = [
4315
- 'HTTP/1.1 101 Switching Protocols',
4316
- 'Upgrade: websocket',
4317
- 'Connection: Upgrade',
4318
- `Sec-WebSocket-Accept: ${digest}`
4319
- ];
4320
-
4321
- const ws = new WebSocket$2(null);
4322
- let protocol = req.headers['sec-websocket-protocol'];
4323
-
4324
- if (protocol) {
4325
- protocol = protocol.split(',').map(trim);
4326
-
4327
- //
4328
- // Optionally call external protocol selection handler.
4329
- //
4330
- if (this.options.handleProtocols) {
4331
- protocol = this.options.handleProtocols(protocol, req);
4332
- } else {
4333
- protocol = protocol[0];
4334
- }
4335
-
4336
- if (protocol) {
4337
- headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
4338
- ws._protocol = protocol;
4339
- }
4340
- }
4341
-
4342
- if (extensions[PerMessageDeflate.extensionName]) {
4343
- const params = extensions[PerMessageDeflate.extensionName].params;
4344
- const value = format({
4345
- [PerMessageDeflate.extensionName]: [params]
4346
- });
4347
- headers.push(`Sec-WebSocket-Extensions: ${value}`);
4348
- ws._extensions = extensions;
4349
- }
4350
-
4351
- //
4352
- // Allow external modification/inspection of handshake headers.
4353
- //
4354
- this.emit('headers', headers, req);
4355
-
4356
- socket.write(headers.concat('\r\n').join('\r\n'));
4357
- socket.removeListener('error', socketOnError);
4358
-
4359
- ws.setSocket(socket, head, this.options.maxPayload);
4360
-
4361
- if (this.clients) {
4362
- this.clients.add(ws);
4363
- ws.on('close', () => this.clients.delete(ws));
4364
- }
4365
-
4366
- cb(ws, req);
4367
- }
4368
- }
4369
-
4370
- var websocketServer = WebSocketServer;
4371
-
4372
- /**
4373
- * Add event listeners on an `EventEmitter` using a map of <event, listener>
4374
- * pairs.
4375
- *
4376
- * @param {EventEmitter} server The event emitter
4377
- * @param {Object.<String, Function>} map The listeners to add
4378
- * @return {Function} A function that will remove the added listeners when
4379
- * called
4380
- * @private
4381
- */
4382
- function addListeners(server, map) {
4383
- for (const event of Object.keys(map)) server.on(event, map[event]);
4384
-
4385
- return function removeListeners() {
4386
- for (const event of Object.keys(map)) {
4387
- server.removeListener(event, map[event]);
4388
- }
4389
- };
4390
- }
4391
-
4392
- /**
4393
- * Emit a `'close'` event on an `EventEmitter`.
4394
- *
4395
- * @param {EventEmitter} server The event emitter
4396
- * @private
4397
- */
4398
- function emitClose(server) {
4399
- server._state = CLOSED;
4400
- server.emit('close');
4401
- }
4402
-
4403
- /**
4404
- * Handle premature socket errors.
4405
- *
4406
- * @private
4407
- */
4408
- function socketOnError() {
4409
- this.destroy();
4410
- }
4411
-
4412
- /**
4413
- * Close the connection when preconditions are not fulfilled.
4414
- *
4415
- * @param {(net.Socket|tls.Socket)} socket The socket of the upgrade request
4416
- * @param {Number} code The HTTP response status code
4417
- * @param {String} [message] The HTTP response body
4418
- * @param {Object} [headers] Additional HTTP response headers
4419
- * @private
4420
- */
4421
- function abortHandshake(socket, code, message, headers) {
4422
- if (socket.writable) {
4423
- message = message || http.STATUS_CODES[code];
4424
- headers = {
4425
- Connection: 'close',
4426
- 'Content-Type': 'text/html',
4427
- 'Content-Length': Buffer.byteLength(message),
4428
- ...headers
4429
- };
4430
-
4431
- socket.write(
4432
- `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
4433
- Object.keys(headers)
4434
- .map((h) => `${h}: ${headers[h]}`)
4435
- .join('\r\n') +
4436
- '\r\n\r\n' +
4437
- message
4438
- );
4439
- }
4440
-
4441
- socket.removeListener('error', socketOnError);
4442
- socket.destroy();
4443
- }
4444
-
4445
- /**
4446
- * Remove whitespace characters from both ends of a string.
4447
- *
4448
- * @param {String} str The string
4449
- * @return {String} A new string representing `str` stripped of whitespace
4450
- * characters from both its beginning and end
4451
- * @private
4452
- */
4453
- function trim(str) {
4454
- return str.trim();
4455
- }
4456
-
4457
- const WebSocket$1 = websocket;
4482
+ var WebSocket$2 = /*@__PURE__*/getDefaultExportFromCjs(websocket);
4458
4483
 
4459
- WebSocket$1.createWebSocketStream = stream;
4460
- WebSocket$1.Server = websocketServer;
4461
- WebSocket$1.Receiver = receiver;
4462
- WebSocket$1.Sender = sender;
4484
+ /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^WebSocket$" }] */
4485
+ const { Duplex: Duplex$1 } = require$$0$3;
4463
4486
 
4464
- var ws = WebSocket$1;
4487
+ const { tokenChars } = validationExports;
4465
4488
 
4466
- var ws$1 = /*@__PURE__*/getDefaultExportFromCjs(ws);
4489
+ /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */
4490
+ const { Duplex } = require$$0$3;
4491
+ const { createHash } = require$$1$1;
4492
+ const { CLOSE_TIMEOUT, GUID, kWebSocket } = constants;
4467
4493
 
4468
4494
  /**
4469
4495
  * Re-exports WebSocket and WebSocketServer from the ws package.
4470
4496
  *
4471
- * ws is a CJS module named exports like WebSocketServer aren't available
4472
- * at runtime when Node auto-detects ESM from tsc output. This module works
4473
- * around that by extracting them from the default export and re-exporting
4474
- * them as merged type+value pairs.
4497
+ * ws is a CJS module with different shapes for default and namespace imports.
4498
+ * This module normalizes those imports and re-exports them as merged type+value pairs.
4475
4499
  */
4476
- const WebSocket = ws$1;
4477
- ws$1.Server;
4500
+ const WebSocket = WebSocket$2;
4478
4501
 
4479
4502
  const CONFIG_FILENAME = ".babyloninspector";
4480
4503
  const DefaultBrowserPort = 4400;