@xapp/chat-widget 1.70.2 → 1.71.0

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.
package/dist/index.es.js CHANGED
@@ -2296,9 +2296,9 @@ var StentorDirectChat = /** @class */ (function () {
2296
2296
  return __assign(__assign({}, user), { nick: user.nick || bot.nick || "Bot", displayName: user.displayName || bot.displayName || "Bot", avatarPath: user.avatarPath || bot.avatarPath });
2297
2297
  };
2298
2298
  StentorDirectChat.prototype.sendChatMsgRequest = function (serviceRequest, cb) {
2299
- var _a;
2300
2299
  return __awaiter$1(this, void 0, void 0, function () {
2301
2300
  var agentResponse;
2301
+ var _a;
2302
2302
  return __generator$1(this, function (_b) {
2303
2303
  switch (_b.label) {
2304
2304
  case 0: return [4 /*yield*/, this.postMessage(serviceRequest)];
@@ -2354,10 +2354,10 @@ var StentorDirectChat = /** @class */ (function () {
2354
2354
  StentorDirectChat.prototype.wakeup = function () {
2355
2355
  };
2356
2356
  StentorDirectChat.prototype.postMessage = function (message) {
2357
- var _a, _b, _c, _d, _e;
2358
2357
  return __awaiter$1(this, void 0, void 0, function () {
2359
2358
  var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2360
2359
  var _this = this;
2360
+ var _a, _b, _c, _d, _e;
2361
2361
  return __generator$1(this, function (_f) {
2362
2362
  switch (_f.label) {
2363
2363
  case 0:
@@ -3367,7 +3367,7 @@ PACKET_TYPES["message"] = "4";
3367
3367
  PACKET_TYPES["upgrade"] = "5";
3368
3368
  PACKET_TYPES["noop"] = "6";
3369
3369
  const PACKET_TYPES_REVERSE = Object.create(null);
3370
- Object.keys(PACKET_TYPES).forEach(key => {
3370
+ Object.keys(PACKET_TYPES).forEach((key) => {
3371
3371
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
3372
3372
  });
3373
3373
  const ERROR_PACKET = { type: "error", data: "parser error" };
@@ -3377,7 +3377,7 @@ const withNativeBlob$1 = typeof Blob === "function" ||
3377
3377
  Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
3378
3378
  const withNativeArrayBuffer$2 = typeof ArrayBuffer === "function";
3379
3379
  // ArrayBuffer.isView method is not defined in IE10
3380
- const isView$1 = obj => {
3380
+ const isView$1 = (obj) => {
3381
3381
  return typeof ArrayBuffer.isView === "function"
3382
3382
  ? ArrayBuffer.isView(obj)
3383
3383
  : obj && obj.buffer instanceof ArrayBuffer;
@@ -3411,6 +3411,33 @@ const encodeBlobAsBase64 = (data, callback) => {
3411
3411
  };
3412
3412
  return fileReader.readAsDataURL(data);
3413
3413
  };
3414
+ function toArray(data) {
3415
+ if (data instanceof Uint8Array) {
3416
+ return data;
3417
+ }
3418
+ else if (data instanceof ArrayBuffer) {
3419
+ return new Uint8Array(data);
3420
+ }
3421
+ else {
3422
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
3423
+ }
3424
+ }
3425
+ let TEXT_ENCODER;
3426
+ function encodePacketToBinary(packet, callback) {
3427
+ if (withNativeBlob$1 && packet.data instanceof Blob) {
3428
+ return packet.data.arrayBuffer().then(toArray).then(callback);
3429
+ }
3430
+ else if (withNativeArrayBuffer$2 &&
3431
+ (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
3432
+ return callback(toArray(packet.data));
3433
+ }
3434
+ encodePacket(packet, false, (encoded) => {
3435
+ if (!TEXT_ENCODER) {
3436
+ TEXT_ENCODER = new TextEncoder();
3437
+ }
3438
+ callback(TEXT_ENCODER.encode(encoded));
3439
+ });
3440
+ }
3414
3441
 
3415
3442
  // imported from https://github.com/socketio/base64-arraybuffer
3416
3443
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -3445,14 +3472,14 @@ const decodePacket = (encodedPacket, binaryType) => {
3445
3472
  if (typeof encodedPacket !== "string") {
3446
3473
  return {
3447
3474
  type: "message",
3448
- data: mapBinary(encodedPacket, binaryType)
3475
+ data: mapBinary(encodedPacket, binaryType),
3449
3476
  };
3450
3477
  }
3451
3478
  const type = encodedPacket.charAt(0);
3452
3479
  if (type === "b") {
3453
3480
  return {
3454
3481
  type: "message",
3455
- data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
3482
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
3456
3483
  };
3457
3484
  }
3458
3485
  const packetType = PACKET_TYPES_REVERSE[type];
@@ -3462,10 +3489,10 @@ const decodePacket = (encodedPacket, binaryType) => {
3462
3489
  return encodedPacket.length > 1
3463
3490
  ? {
3464
3491
  type: PACKET_TYPES_REVERSE[type],
3465
- data: encodedPacket.substring(1)
3492
+ data: encodedPacket.substring(1),
3466
3493
  }
3467
3494
  : {
3468
- type: PACKET_TYPES_REVERSE[type]
3495
+ type: PACKET_TYPES_REVERSE[type],
3469
3496
  };
3470
3497
  };
3471
3498
  const decodeBase64Packet = (data, binaryType) => {
@@ -3480,10 +3507,24 @@ const decodeBase64Packet = (data, binaryType) => {
3480
3507
  const mapBinary = (data, binaryType) => {
3481
3508
  switch (binaryType) {
3482
3509
  case "blob":
3483
- return data instanceof ArrayBuffer ? new Blob([data]) : data;
3510
+ if (data instanceof Blob) {
3511
+ // from WebSocket + binaryType "blob"
3512
+ return data;
3513
+ }
3514
+ else {
3515
+ // from HTTP long-polling or WebTransport
3516
+ return new Blob([data]);
3517
+ }
3484
3518
  case "arraybuffer":
3485
3519
  default:
3486
- return data; // assuming the data is already an ArrayBuffer
3520
+ if (data instanceof ArrayBuffer) {
3521
+ // from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
3522
+ return data;
3523
+ }
3524
+ else {
3525
+ // from WebTransport (Uint8Array)
3526
+ return data.buffer;
3527
+ }
3487
3528
  }
3488
3529
  };
3489
3530
 
@@ -3495,7 +3536,7 @@ const encodePayload = (packets, callback) => {
3495
3536
  let count = 0;
3496
3537
  packets.forEach((packet, i) => {
3497
3538
  // force base64 encoding for binary packets
3498
- encodePacket(packet, false, encodedPacket => {
3539
+ encodePacket(packet, false, (encodedPacket) => {
3499
3540
  encodedPackets[i] = encodedPacket;
3500
3541
  if (++count === length) {
3501
3542
  callback(encodedPackets.join(SEPARATOR));
@@ -3515,6 +3556,131 @@ const decodePayload = (encodedPayload, binaryType) => {
3515
3556
  }
3516
3557
  return packets;
3517
3558
  };
3559
+ function createPacketEncoderStream() {
3560
+ // @ts-expect-error
3561
+ return new TransformStream({
3562
+ transform(packet, controller) {
3563
+ encodePacketToBinary(packet, (encodedPacket) => {
3564
+ const payloadLength = encodedPacket.length;
3565
+ let header;
3566
+ // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
3567
+ if (payloadLength < 126) {
3568
+ header = new Uint8Array(1);
3569
+ new DataView(header.buffer).setUint8(0, payloadLength);
3570
+ }
3571
+ else if (payloadLength < 65536) {
3572
+ header = new Uint8Array(3);
3573
+ const view = new DataView(header.buffer);
3574
+ view.setUint8(0, 126);
3575
+ view.setUint16(1, payloadLength);
3576
+ }
3577
+ else {
3578
+ header = new Uint8Array(9);
3579
+ const view = new DataView(header.buffer);
3580
+ view.setUint8(0, 127);
3581
+ view.setBigUint64(1, BigInt(payloadLength));
3582
+ }
3583
+ // first bit indicates whether the payload is plain text (0) or binary (1)
3584
+ if (packet.data && typeof packet.data !== "string") {
3585
+ header[0] |= 0x80;
3586
+ }
3587
+ controller.enqueue(header);
3588
+ controller.enqueue(encodedPacket);
3589
+ });
3590
+ },
3591
+ });
3592
+ }
3593
+ let TEXT_DECODER;
3594
+ function totalLength(chunks) {
3595
+ return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
3596
+ }
3597
+ function concatChunks(chunks, size) {
3598
+ if (chunks[0].length === size) {
3599
+ return chunks.shift();
3600
+ }
3601
+ const buffer = new Uint8Array(size);
3602
+ let j = 0;
3603
+ for (let i = 0; i < size; i++) {
3604
+ buffer[i] = chunks[0][j++];
3605
+ if (j === chunks[0].length) {
3606
+ chunks.shift();
3607
+ j = 0;
3608
+ }
3609
+ }
3610
+ if (chunks.length && j < chunks[0].length) {
3611
+ chunks[0] = chunks[0].slice(j);
3612
+ }
3613
+ return buffer;
3614
+ }
3615
+ function createPacketDecoderStream(maxPayload, binaryType) {
3616
+ if (!TEXT_DECODER) {
3617
+ TEXT_DECODER = new TextDecoder();
3618
+ }
3619
+ const chunks = [];
3620
+ let state = 0 /* READ_HEADER */;
3621
+ let expectedLength = -1;
3622
+ let isBinary = false;
3623
+ // @ts-expect-error
3624
+ return new TransformStream({
3625
+ transform(chunk, controller) {
3626
+ chunks.push(chunk);
3627
+ while (true) {
3628
+ if (state === 0 /* READ_HEADER */) {
3629
+ if (totalLength(chunks) < 1) {
3630
+ break;
3631
+ }
3632
+ const header = concatChunks(chunks, 1);
3633
+ isBinary = (header[0] & 0x80) === 0x80;
3634
+ expectedLength = header[0] & 0x7f;
3635
+ if (expectedLength < 126) {
3636
+ state = 3 /* READ_PAYLOAD */;
3637
+ }
3638
+ else if (expectedLength === 126) {
3639
+ state = 1 /* READ_EXTENDED_LENGTH_16 */;
3640
+ }
3641
+ else {
3642
+ state = 2 /* READ_EXTENDED_LENGTH_64 */;
3643
+ }
3644
+ }
3645
+ else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
3646
+ if (totalLength(chunks) < 2) {
3647
+ break;
3648
+ }
3649
+ const headerArray = concatChunks(chunks, 2);
3650
+ expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
3651
+ state = 3 /* READ_PAYLOAD */;
3652
+ }
3653
+ else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
3654
+ if (totalLength(chunks) < 8) {
3655
+ break;
3656
+ }
3657
+ const headerArray = concatChunks(chunks, 8);
3658
+ const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
3659
+ const n = view.getUint32(0);
3660
+ if (n > Math.pow(2, 53 - 32) - 1) {
3661
+ // the maximum safe integer in JavaScript is 2^53 - 1
3662
+ controller.enqueue(ERROR_PACKET);
3663
+ break;
3664
+ }
3665
+ expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
3666
+ state = 3 /* READ_PAYLOAD */;
3667
+ }
3668
+ else {
3669
+ if (totalLength(chunks) < expectedLength) {
3670
+ break;
3671
+ }
3672
+ const data = concatChunks(chunks, expectedLength);
3673
+ controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
3674
+ state = 0 /* READ_HEADER */;
3675
+ }
3676
+ if (expectedLength === 0 || expectedLength > maxPayload) {
3677
+ controller.enqueue(ERROR_PACKET);
3678
+ break;
3679
+ }
3680
+ }
3681
+ },
3682
+ });
3683
+ }
3518
3684
  const protocol$1 = 4;
3519
3685
 
3520
3686
  /**
@@ -3714,16 +3880,16 @@ function pick(obj, ...attr) {
3714
3880
  }, {});
3715
3881
  }
3716
3882
  // Keep a reference to the real timeout functions so they can be used when overridden
3717
- const NATIVE_SET_TIMEOUT = setTimeout;
3718
- const NATIVE_CLEAR_TIMEOUT = clearTimeout;
3883
+ const NATIVE_SET_TIMEOUT = globalThisShim.setTimeout;
3884
+ const NATIVE_CLEAR_TIMEOUT = globalThisShim.clearTimeout;
3719
3885
  function installTimerFunctions(obj, opts) {
3720
3886
  if (opts.useNativeTimers) {
3721
3887
  obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThisShim);
3722
3888
  obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThisShim);
3723
3889
  }
3724
3890
  else {
3725
- obj.setTimeoutFn = setTimeout.bind(globalThisShim);
3726
- obj.clearTimeoutFn = clearTimeout.bind(globalThisShim);
3891
+ obj.setTimeoutFn = globalThisShim.setTimeout.bind(globalThisShim);
3892
+ obj.clearTimeoutFn = globalThisShim.clearTimeout.bind(globalThisShim);
3727
3893
  }
3728
3894
  }
3729
3895
  // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
@@ -3757,6 +3923,41 @@ function utf8Length(str) {
3757
3923
  return length;
3758
3924
  }
3759
3925
 
3926
+ // imported from https://github.com/galkn/querystring
3927
+ /**
3928
+ * Compiles a querystring
3929
+ * Returns string representation of the object
3930
+ *
3931
+ * @param {Object}
3932
+ * @api private
3933
+ */
3934
+ function encode$1(obj) {
3935
+ let str = '';
3936
+ for (let i in obj) {
3937
+ if (obj.hasOwnProperty(i)) {
3938
+ if (str.length)
3939
+ str += '&';
3940
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3941
+ }
3942
+ }
3943
+ return str;
3944
+ }
3945
+ /**
3946
+ * Parses a simple querystring into an object
3947
+ *
3948
+ * @param {String} qs
3949
+ * @api private
3950
+ */
3951
+ function decode(qs) {
3952
+ let qry = {};
3953
+ let pairs = qs.split('&');
3954
+ for (let i = 0, l = pairs.length; i < l; i++) {
3955
+ let pair = pairs[i].split('=');
3956
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3957
+ }
3958
+ return qry;
3959
+ }
3960
+
3760
3961
  class TransportError extends Error {
3761
3962
  constructor(reason, description, context) {
3762
3963
  super(reason);
@@ -3769,8 +3970,8 @@ class Transport extends Emitter_1 {
3769
3970
  /**
3770
3971
  * Transport abstract constructor.
3771
3972
  *
3772
- * @param {Object} options.
3773
- * @api private
3973
+ * @param {Object} opts - options
3974
+ * @protected
3774
3975
  */
3775
3976
  constructor(opts) {
3776
3977
  super();
@@ -3778,7 +3979,6 @@ class Transport extends Emitter_1 {
3778
3979
  installTimerFunctions(this, opts);
3779
3980
  this.opts = opts;
3780
3981
  this.query = opts.query;
3781
- this.readyState = "";
3782
3982
  this.socket = opts.socket;
3783
3983
  }
3784
3984
  /**
@@ -3788,7 +3988,7 @@ class Transport extends Emitter_1 {
3788
3988
  * @param description
3789
3989
  * @param context - the error context
3790
3990
  * @return {Transport} for chaining
3791
- * @api protected
3991
+ * @protected
3792
3992
  */
3793
3993
  onError(reason, description, context) {
3794
3994
  super.emitReserved("error", new TransportError(reason, description, context));
@@ -3796,23 +3996,17 @@ class Transport extends Emitter_1 {
3796
3996
  }
3797
3997
  /**
3798
3998
  * Opens the transport.
3799
- *
3800
- * @api public
3801
3999
  */
3802
4000
  open() {
3803
- if ("closed" === this.readyState || "" === this.readyState) {
3804
- this.readyState = "opening";
3805
- this.doOpen();
3806
- }
4001
+ this.readyState = "opening";
4002
+ this.doOpen();
3807
4003
  return this;
3808
4004
  }
3809
4005
  /**
3810
4006
  * Closes the transport.
3811
- *
3812
- * @api public
3813
4007
  */
3814
4008
  close() {
3815
- if ("opening" === this.readyState || "open" === this.readyState) {
4009
+ if (this.readyState === "opening" || this.readyState === "open") {
3816
4010
  this.doClose();
3817
4011
  this.onClose();
3818
4012
  }
@@ -3822,17 +4016,16 @@ class Transport extends Emitter_1 {
3822
4016
  * Sends multiple packets.
3823
4017
  *
3824
4018
  * @param {Array} packets
3825
- * @api public
3826
4019
  */
3827
4020
  send(packets) {
3828
- if ("open" === this.readyState) {
4021
+ if (this.readyState === "open") {
3829
4022
  this.write(packets);
3830
4023
  }
3831
4024
  }
3832
4025
  /**
3833
4026
  * Called upon open
3834
4027
  *
3835
- * @api protected
4028
+ * @protected
3836
4029
  */
3837
4030
  onOpen() {
3838
4031
  this.readyState = "open";
@@ -3843,7 +4036,7 @@ class Transport extends Emitter_1 {
3843
4036
  * Called with data.
3844
4037
  *
3845
4038
  * @param {String} data
3846
- * @api protected
4039
+ * @protected
3847
4040
  */
3848
4041
  onData(data) {
3849
4042
  const packet = decodePacket(data, this.socket.binaryType);
@@ -3852,7 +4045,7 @@ class Transport extends Emitter_1 {
3852
4045
  /**
3853
4046
  * Called with a decoded packet.
3854
4047
  *
3855
- * @api protected
4048
+ * @protected
3856
4049
  */
3857
4050
  onPacket(packet) {
3858
4051
  super.emitReserved("packet", packet);
@@ -3860,12 +4053,44 @@ class Transport extends Emitter_1 {
3860
4053
  /**
3861
4054
  * Called upon close.
3862
4055
  *
3863
- * @api protected
4056
+ * @protected
3864
4057
  */
3865
4058
  onClose(details) {
3866
4059
  this.readyState = "closed";
3867
4060
  super.emitReserved("close", details);
3868
4061
  }
4062
+ /**
4063
+ * Pauses the transport, in order not to lose packets during an upgrade.
4064
+ *
4065
+ * @param onPause
4066
+ */
4067
+ pause(onPause) { }
4068
+ createUri(schema, query = {}) {
4069
+ return (schema +
4070
+ "://" +
4071
+ this._hostname() +
4072
+ this._port() +
4073
+ this.opts.path +
4074
+ this._query(query));
4075
+ }
4076
+ _hostname() {
4077
+ const hostname = this.opts.hostname;
4078
+ return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
4079
+ }
4080
+ _port() {
4081
+ if (this.opts.port &&
4082
+ ((this.opts.secure && Number(this.opts.port !== 443)) ||
4083
+ (!this.opts.secure && Number(this.opts.port) !== 80))) {
4084
+ return ":" + this.opts.port;
4085
+ }
4086
+ else {
4087
+ return "";
4088
+ }
4089
+ }
4090
+ _query(query) {
4091
+ const encodedQuery = encode$1(query);
4092
+ return encodedQuery.length ? "?" + encodedQuery : "";
4093
+ }
3869
4094
  }
3870
4095
 
3871
4096
  // imported from https://github.com/unshiftio/yeast
@@ -3878,7 +4103,7 @@ let seed = 0, i = 0, prev;
3878
4103
  * @returns {String} The string representation of the number.
3879
4104
  * @api public
3880
4105
  */
3881
- function encode$1(num) {
4106
+ function encode(num) {
3882
4107
  let encoded = '';
3883
4108
  do {
3884
4109
  encoded = alphabet[num % length] + encoded;
@@ -3893,10 +4118,10 @@ function encode$1(num) {
3893
4118
  * @api public
3894
4119
  */
3895
4120
  function yeast() {
3896
- const now = encode$1(+new Date());
4121
+ const now = encode(+new Date());
3897
4122
  if (now !== prev)
3898
4123
  return seed = 0, prev = now;
3899
- return now + '.' + encode$1(seed++);
4124
+ return now + '.' + encode(seed++);
3900
4125
  }
3901
4126
  //
3902
4127
  // Map each character to its index.
@@ -3904,41 +4129,6 @@ function yeast() {
3904
4129
  for (; i < length; i++)
3905
4130
  map[alphabet[i]] = i;
3906
4131
 
3907
- // imported from https://github.com/galkn/querystring
3908
- /**
3909
- * Compiles a querystring
3910
- * Returns string representation of the object
3911
- *
3912
- * @param {Object}
3913
- * @api private
3914
- */
3915
- function encode(obj) {
3916
- let str = '';
3917
- for (let i in obj) {
3918
- if (obj.hasOwnProperty(i)) {
3919
- if (str.length)
3920
- str += '&';
3921
- str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3922
- }
3923
- }
3924
- return str;
3925
- }
3926
- /**
3927
- * Parses a simple querystring into an object
3928
- *
3929
- * @param {String} qs
3930
- * @api private
3931
- */
3932
- function decode(qs) {
3933
- let qry = {};
3934
- let pairs = qs.split('&');
3935
- for (let i = 0, l = pairs.length; i < l; i++) {
3936
- let pair = pairs[i].split('=');
3937
- qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3938
- }
3939
- return qry;
3940
- }
3941
-
3942
4132
  // imported from https://github.com/component/has-cors
3943
4133
  let value = false;
3944
4134
  try {
@@ -3968,11 +4158,12 @@ function XHR(opts) {
3968
4158
  catch (e) { }
3969
4159
  }
3970
4160
  }
4161
+ function createCookieJar() { }
3971
4162
 
3972
4163
  function empty$2() { }
3973
4164
  const hasXHR2 = (function () {
3974
4165
  const xhr = new XHR({
3975
- xdomain: false
4166
+ xdomain: false,
3976
4167
  });
3977
4168
  return null != xhr.responseType;
3978
4169
  })();
@@ -3981,7 +4172,7 @@ class Polling extends Transport {
3981
4172
  * XHR Polling constructor.
3982
4173
  *
3983
4174
  * @param {Object} opts
3984
- * @api public
4175
+ * @package
3985
4176
  */
3986
4177
  constructor(opts) {
3987
4178
  super(opts);
@@ -3997,17 +4188,16 @@ class Polling extends Transport {
3997
4188
  (typeof location !== "undefined" &&
3998
4189
  opts.hostname !== location.hostname) ||
3999
4190
  port !== opts.port;
4000
- this.xs = opts.secure !== isSSL;
4001
4191
  }
4002
4192
  /**
4003
4193
  * XHR supports binary
4004
4194
  */
4005
4195
  const forceBase64 = opts && opts.forceBase64;
4006
4196
  this.supportsBinary = hasXHR2 && !forceBase64;
4197
+ if (this.opts.withCredentials) {
4198
+ this.cookieJar = createCookieJar();
4199
+ }
4007
4200
  }
4008
- /**
4009
- * Transport name.
4010
- */
4011
4201
  get name() {
4012
4202
  return "polling";
4013
4203
  }
@@ -4015,7 +4205,7 @@ class Polling extends Transport {
4015
4205
  * Opens the socket (triggers polling). We write a PING message to determine
4016
4206
  * when the transport is open.
4017
4207
  *
4018
- * @api private
4208
+ * @protected
4019
4209
  */
4020
4210
  doOpen() {
4021
4211
  this.poll();
@@ -4023,8 +4213,8 @@ class Polling extends Transport {
4023
4213
  /**
4024
4214
  * Pauses polling.
4025
4215
  *
4026
- * @param {Function} callback upon buffers are flushed and transport is paused
4027
- * @api private
4216
+ * @param {Function} onPause - callback upon buffers are flushed and transport is paused
4217
+ * @package
4028
4218
  */
4029
4219
  pause(onPause) {
4030
4220
  this.readyState = "pausing";
@@ -4054,7 +4244,7 @@ class Polling extends Transport {
4054
4244
  /**
4055
4245
  * Starts polling cycle.
4056
4246
  *
4057
- * @api public
4247
+ * @private
4058
4248
  */
4059
4249
  poll() {
4060
4250
  this.polling = true;
@@ -4064,10 +4254,10 @@ class Polling extends Transport {
4064
4254
  /**
4065
4255
  * Overloads onData to detect payloads.
4066
4256
  *
4067
- * @api private
4257
+ * @protected
4068
4258
  */
4069
4259
  onData(data) {
4070
- const callback = packet => {
4260
+ const callback = (packet) => {
4071
4261
  // if its the first message we consider the transport open
4072
4262
  if ("opening" === this.readyState && packet.type === "open") {
4073
4263
  this.onOpen();
@@ -4095,7 +4285,7 @@ class Polling extends Transport {
4095
4285
  /**
4096
4286
  * For polling, send a close packet.
4097
4287
  *
4098
- * @api private
4288
+ * @protected
4099
4289
  */
4100
4290
  doClose() {
4101
4291
  const close = () => {
@@ -4113,13 +4303,12 @@ class Polling extends Transport {
4113
4303
  /**
4114
4304
  * Writes a packets payload.
4115
4305
  *
4116
- * @param {Array} data packets
4117
- * @param {Function} drain callback
4118
- * @api private
4306
+ * @param {Array} packets - data packets
4307
+ * @protected
4119
4308
  */
4120
4309
  write(packets) {
4121
4310
  this.writable = false;
4122
- encodePayload(packets, data => {
4311
+ encodePayload(packets, (data) => {
4123
4312
  this.doWrite(data, () => {
4124
4313
  this.writable = true;
4125
4314
  this.emitReserved("drain");
@@ -4129,12 +4318,11 @@ class Polling extends Transport {
4129
4318
  /**
4130
4319
  * Generates uri for connection.
4131
4320
  *
4132
- * @api private
4321
+ * @private
4133
4322
  */
4134
4323
  uri() {
4135
- let query = this.query || {};
4136
4324
  const schema = this.opts.secure ? "https" : "http";
4137
- let port = "";
4325
+ const query = this.query || {};
4138
4326
  // cache busting is forced
4139
4327
  if (false !== this.opts.timestampRequests) {
4140
4328
  query[this.opts.timestampParam] = yeast();
@@ -4142,29 +4330,16 @@ class Polling extends Transport {
4142
4330
  if (!this.supportsBinary && !query.sid) {
4143
4331
  query.b64 = 1;
4144
4332
  }
4145
- // avoid port if default for schema
4146
- if (this.opts.port &&
4147
- (("https" === schema && Number(this.opts.port) !== 443) ||
4148
- ("http" === schema && Number(this.opts.port) !== 80))) {
4149
- port = ":" + this.opts.port;
4150
- }
4151
- const encodedQuery = encode(query);
4152
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4153
- return (schema +
4154
- "://" +
4155
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4156
- port +
4157
- this.opts.path +
4158
- (encodedQuery.length ? "?" + encodedQuery : ""));
4333
+ return this.createUri(schema, query);
4159
4334
  }
4160
4335
  /**
4161
4336
  * Creates a request.
4162
4337
  *
4163
4338
  * @param {String} method
4164
- * @api private
4339
+ * @private
4165
4340
  */
4166
4341
  request(opts = {}) {
4167
- Object.assign(opts, { xd: this.xd, xs: this.xs }, this.opts);
4342
+ Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4168
4343
  return new Request(this.uri(), opts);
4169
4344
  }
4170
4345
  /**
@@ -4172,12 +4347,12 @@ class Polling extends Transport {
4172
4347
  *
4173
4348
  * @param {String} data to send.
4174
4349
  * @param {Function} called upon flush.
4175
- * @api private
4350
+ * @private
4176
4351
  */
4177
4352
  doWrite(data, fn) {
4178
4353
  const req = this.request({
4179
4354
  method: "POST",
4180
- data: data
4355
+ data: data,
4181
4356
  });
4182
4357
  req.on("success", fn);
4183
4358
  req.on("error", (xhrStatus, context) => {
@@ -4187,7 +4362,7 @@ class Polling extends Transport {
4187
4362
  /**
4188
4363
  * Starts a poll cycle.
4189
4364
  *
4190
- * @api private
4365
+ * @private
4191
4366
  */
4192
4367
  doPoll() {
4193
4368
  const req = this.request();
@@ -4203,7 +4378,7 @@ class Request extends Emitter_1 {
4203
4378
  * Request constructor
4204
4379
  *
4205
4380
  * @param {Object} options
4206
- * @api public
4381
+ * @package
4207
4382
  */
4208
4383
  constructor(uri, opts) {
4209
4384
  super();
@@ -4211,22 +4386,21 @@ class Request extends Emitter_1 {
4211
4386
  this.opts = opts;
4212
4387
  this.method = opts.method || "GET";
4213
4388
  this.uri = uri;
4214
- this.async = false !== opts.async;
4215
4389
  this.data = undefined !== opts.data ? opts.data : null;
4216
4390
  this.create();
4217
4391
  }
4218
4392
  /**
4219
4393
  * Creates the XHR object and sends the request.
4220
4394
  *
4221
- * @api private
4395
+ * @private
4222
4396
  */
4223
4397
  create() {
4398
+ var _a;
4224
4399
  const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4225
4400
  opts.xdomain = !!this.opts.xd;
4226
- opts.xscheme = !!this.opts.xs;
4227
4401
  const xhr = (this.xhr = new XHR(opts));
4228
4402
  try {
4229
- xhr.open(this.method, this.uri, this.async);
4403
+ xhr.open(this.method, this.uri, true);
4230
4404
  try {
4231
4405
  if (this.opts.extraHeaders) {
4232
4406
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
@@ -4248,6 +4422,7 @@ class Request extends Emitter_1 {
4248
4422
  xhr.setRequestHeader("Accept", "*/*");
4249
4423
  }
4250
4424
  catch (e) { }
4425
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4251
4426
  // ie6 check
4252
4427
  if ("withCredentials" in xhr) {
4253
4428
  xhr.withCredentials = this.opts.withCredentials;
@@ -4256,6 +4431,10 @@ class Request extends Emitter_1 {
4256
4431
  xhr.timeout = this.opts.requestTimeout;
4257
4432
  }
4258
4433
  xhr.onreadystatechange = () => {
4434
+ var _a;
4435
+ if (xhr.readyState === 3) {
4436
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4437
+ }
4259
4438
  if (4 !== xhr.readyState)
4260
4439
  return;
4261
4440
  if (200 === xhr.status || 1223 === xhr.status) {
@@ -4288,7 +4467,7 @@ class Request extends Emitter_1 {
4288
4467
  /**
4289
4468
  * Called upon error.
4290
4469
  *
4291
- * @api private
4470
+ * @private
4292
4471
  */
4293
4472
  onError(err) {
4294
4473
  this.emitReserved("error", err, this.xhr);
@@ -4297,7 +4476,7 @@ class Request extends Emitter_1 {
4297
4476
  /**
4298
4477
  * Cleans up house.
4299
4478
  *
4300
- * @api private
4479
+ * @private
4301
4480
  */
4302
4481
  cleanup(fromError) {
4303
4482
  if ("undefined" === typeof this.xhr || null === this.xhr) {
@@ -4318,7 +4497,7 @@ class Request extends Emitter_1 {
4318
4497
  /**
4319
4498
  * Called upon load.
4320
4499
  *
4321
- * @api private
4500
+ * @private
4322
4501
  */
4323
4502
  onLoad() {
4324
4503
  const data = this.xhr.responseText;
@@ -4331,7 +4510,7 @@ class Request extends Emitter_1 {
4331
4510
  /**
4332
4511
  * Aborts the request.
4333
4512
  *
4334
- * @api public
4513
+ * @package
4335
4514
  */
4336
4515
  abort() {
4337
4516
  this.cleanup();
@@ -4366,7 +4545,7 @@ function unloadHandler() {
4366
4545
  const nextTick = (() => {
4367
4546
  const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4368
4547
  if (isPromiseAvailable) {
4369
- return cb => Promise.resolve().then(cb);
4548
+ return (cb) => Promise.resolve().then(cb);
4370
4549
  }
4371
4550
  else {
4372
4551
  return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
@@ -4384,26 +4563,16 @@ class WS extends Transport {
4384
4563
  /**
4385
4564
  * WebSocket transport constructor.
4386
4565
  *
4387
- * @api {Object} connection options
4388
- * @api public
4566
+ * @param {Object} opts - connection options
4567
+ * @protected
4389
4568
  */
4390
4569
  constructor(opts) {
4391
4570
  super(opts);
4392
4571
  this.supportsBinary = !opts.forceBase64;
4393
4572
  }
4394
- /**
4395
- * Transport name.
4396
- *
4397
- * @api public
4398
- */
4399
4573
  get name() {
4400
4574
  return "websocket";
4401
4575
  }
4402
- /**
4403
- * Opens socket.
4404
- *
4405
- * @api private
4406
- */
4407
4576
  doOpen() {
4408
4577
  if (!this.check()) {
4409
4578
  // let probe timeout
@@ -4429,13 +4598,13 @@ class WS extends Transport {
4429
4598
  catch (err) {
4430
4599
  return this.emitReserved("error", err);
4431
4600
  }
4432
- this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
4601
+ this.ws.binaryType = this.socket.binaryType;
4433
4602
  this.addEventListeners();
4434
4603
  }
4435
4604
  /**
4436
4605
  * Adds event listeners to the socket
4437
4606
  *
4438
- * @api private
4607
+ * @private
4439
4608
  */
4440
4609
  addEventListeners() {
4441
4610
  this.ws.onopen = () => {
@@ -4444,19 +4613,13 @@ class WS extends Transport {
4444
4613
  }
4445
4614
  this.onOpen();
4446
4615
  };
4447
- this.ws.onclose = closeEvent => this.onClose({
4616
+ this.ws.onclose = (closeEvent) => this.onClose({
4448
4617
  description: "websocket connection closed",
4449
- context: closeEvent
4618
+ context: closeEvent,
4450
4619
  });
4451
- this.ws.onmessage = ev => this.onData(ev.data);
4452
- this.ws.onerror = e => this.onError("websocket error", e);
4620
+ this.ws.onmessage = (ev) => this.onData(ev.data);
4621
+ this.ws.onerror = (e) => this.onError("websocket error", e);
4453
4622
  }
4454
- /**
4455
- * Writes data to socket.
4456
- *
4457
- * @param {Array} array of packets.
4458
- * @api private
4459
- */
4460
4623
  write(packets) {
4461
4624
  this.writable = false;
4462
4625
  // encodePacket efficient as it uses WS framing
@@ -4464,7 +4627,7 @@ class WS extends Transport {
4464
4627
  for (let i = 0; i < packets.length; i++) {
4465
4628
  const packet = packets[i];
4466
4629
  const lastPacket = i === packets.length - 1;
4467
- encodePacket(packet, this.supportsBinary, data => {
4630
+ encodePacket(packet, this.supportsBinary, (data) => {
4468
4631
  // always create a new object (GH-437)
4469
4632
  const opts = {};
4470
4633
  // Sometimes the websocket has already been closed but the browser didn't
@@ -4489,11 +4652,6 @@ class WS extends Transport {
4489
4652
  });
4490
4653
  }
4491
4654
  }
4492
- /**
4493
- * Closes socket.
4494
- *
4495
- * @api private
4496
- */
4497
4655
  doClose() {
4498
4656
  if (typeof this.ws !== "undefined") {
4499
4657
  this.ws.close();
@@ -4503,18 +4661,11 @@ class WS extends Transport {
4503
4661
  /**
4504
4662
  * Generates uri for connection.
4505
4663
  *
4506
- * @api private
4664
+ * @private
4507
4665
  */
4508
4666
  uri() {
4509
- let query = this.query || {};
4510
4667
  const schema = this.opts.secure ? "wss" : "ws";
4511
- let port = "";
4512
- // avoid port if default for schema
4513
- if (this.opts.port &&
4514
- (("wss" === schema && Number(this.opts.port) !== 443) ||
4515
- ("ws" === schema && Number(this.opts.port) !== 80))) {
4516
- port = ":" + this.opts.port;
4517
- }
4668
+ const query = this.query || {};
4518
4669
  // append timestamp to URI
4519
4670
  if (this.opts.timestampRequests) {
4520
4671
  query[this.opts.timestampParam] = yeast();
@@ -4523,43 +4674,121 @@ class WS extends Transport {
4523
4674
  if (!this.supportsBinary) {
4524
4675
  query.b64 = 1;
4525
4676
  }
4526
- const encodedQuery = encode(query);
4527
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4528
- return (schema +
4529
- "://" +
4530
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4531
- port +
4532
- this.opts.path +
4533
- (encodedQuery.length ? "?" + encodedQuery : ""));
4677
+ return this.createUri(schema, query);
4534
4678
  }
4535
4679
  /**
4536
4680
  * Feature detection for WebSocket.
4537
4681
  *
4538
4682
  * @return {Boolean} whether this transport is available.
4539
- * @api public
4683
+ * @private
4540
4684
  */
4541
4685
  check() {
4542
4686
  return !!WebSocket$1;
4543
4687
  }
4544
4688
  }
4545
4689
 
4690
+ class WT extends Transport {
4691
+ get name() {
4692
+ return "webtransport";
4693
+ }
4694
+ doOpen() {
4695
+ // @ts-ignore
4696
+ if (typeof WebTransport !== "function") {
4697
+ return;
4698
+ }
4699
+ // @ts-ignore
4700
+ this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4701
+ this.transport.closed
4702
+ .then(() => {
4703
+ this.onClose();
4704
+ })
4705
+ .catch((err) => {
4706
+ this.onError("webtransport error", err);
4707
+ });
4708
+ // note: we could have used async/await, but that would require some additional polyfills
4709
+ this.transport.ready.then(() => {
4710
+ this.transport.createBidirectionalStream().then((stream) => {
4711
+ const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4712
+ const reader = stream.readable.pipeThrough(decoderStream).getReader();
4713
+ const encoderStream = createPacketEncoderStream();
4714
+ encoderStream.readable.pipeTo(stream.writable);
4715
+ this.writer = encoderStream.writable.getWriter();
4716
+ const read = () => {
4717
+ reader
4718
+ .read()
4719
+ .then(({ done, value }) => {
4720
+ if (done) {
4721
+ return;
4722
+ }
4723
+ this.onPacket(value);
4724
+ read();
4725
+ })
4726
+ .catch((err) => {
4727
+ });
4728
+ };
4729
+ read();
4730
+ const packet = { type: "open" };
4731
+ if (this.query.sid) {
4732
+ packet.data = `{"sid":"${this.query.sid}"}`;
4733
+ }
4734
+ this.writer.write(packet).then(() => this.onOpen());
4735
+ });
4736
+ });
4737
+ }
4738
+ write(packets) {
4739
+ this.writable = false;
4740
+ for (let i = 0; i < packets.length; i++) {
4741
+ const packet = packets[i];
4742
+ const lastPacket = i === packets.length - 1;
4743
+ this.writer.write(packet).then(() => {
4744
+ if (lastPacket) {
4745
+ nextTick(() => {
4746
+ this.writable = true;
4747
+ this.emitReserved("drain");
4748
+ }, this.setTimeoutFn);
4749
+ }
4750
+ });
4751
+ }
4752
+ }
4753
+ doClose() {
4754
+ var _a;
4755
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4756
+ }
4757
+ }
4758
+
4546
4759
  const transports = {
4547
4760
  websocket: WS,
4548
- polling: Polling
4761
+ webtransport: WT,
4762
+ polling: Polling,
4549
4763
  };
4550
4764
 
4551
4765
  // imported from https://github.com/galkn/parseuri
4552
4766
  /**
4553
- * Parses an URI
4767
+ * Parses a URI
4768
+ *
4769
+ * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
4770
+ *
4771
+ * See:
4772
+ * - https://developer.mozilla.org/en-US/docs/Web/API/URL
4773
+ * - https://caniuse.com/url
4774
+ * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
4775
+ *
4776
+ * History of the parse() method:
4777
+ * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
4778
+ * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
4779
+ * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
4554
4780
  *
4555
4781
  * @author Steven Levithan <stevenlevithan.com> (MIT license)
4556
4782
  * @api private
4557
4783
  */
4558
- const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4784
+ const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4559
4785
  const parts = [
4560
4786
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4561
4787
  ];
4562
4788
  function parse$2(str) {
4789
+ if (str.length > 2000) {
4790
+ throw "URI too long";
4791
+ }
4563
4792
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
4564
4793
  if (b != -1 && e != -1) {
4565
4794
  str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
@@ -4602,12 +4831,13 @@ class Socket$1 extends Emitter_1 {
4602
4831
  /**
4603
4832
  * Socket constructor.
4604
4833
  *
4605
- * @param {String|Object} uri or options
4834
+ * @param {String|Object} uri - uri or options
4606
4835
  * @param {Object} opts - options
4607
- * @api public
4608
4836
  */
4609
4837
  constructor(uri, opts = {}) {
4610
4838
  super();
4839
+ this.binaryType = defaultBinaryType;
4840
+ this.writeBuffer = [];
4611
4841
  if (uri && "object" === typeof uri) {
4612
4842
  opts = uri;
4613
4843
  uri = null;
@@ -4642,8 +4872,11 @@ class Socket$1 extends Emitter_1 {
4642
4872
  : this.secure
4643
4873
  ? "443"
4644
4874
  : "80");
4645
- this.transports = opts.transports || ["polling", "websocket"];
4646
- this.readyState = "";
4875
+ this.transports = opts.transports || [
4876
+ "polling",
4877
+ "websocket",
4878
+ "webtransport",
4879
+ ];
4647
4880
  this.writeBuffer = [];
4648
4881
  this.prevBufferLen = 0;
4649
4882
  this.opts = Object.assign({
@@ -4653,14 +4886,17 @@ class Socket$1 extends Emitter_1 {
4653
4886
  upgrade: true,
4654
4887
  timestampParam: "t",
4655
4888
  rememberUpgrade: false,
4889
+ addTrailingSlash: true,
4656
4890
  rejectUnauthorized: true,
4657
4891
  perMessageDeflate: {
4658
- threshold: 1024
4892
+ threshold: 1024,
4659
4893
  },
4660
4894
  transportOptions: {},
4661
- closeOnBeforeunload: true
4895
+ closeOnBeforeunload: false,
4662
4896
  }, opts);
4663
- this.opts.path = this.opts.path.replace(/\/$/, "") + "/";
4897
+ this.opts.path =
4898
+ this.opts.path.replace(/\/$/, "") +
4899
+ (this.opts.addTrailingSlash ? "/" : "");
4664
4900
  if (typeof this.opts.query === "string") {
4665
4901
  this.opts.query = decode(this.opts.query);
4666
4902
  }
@@ -4688,7 +4924,7 @@ class Socket$1 extends Emitter_1 {
4688
4924
  if (this.hostname !== "localhost") {
4689
4925
  this.offlineEventListener = () => {
4690
4926
  this.onClose("transport close", {
4691
- description: "network connection lost"
4927
+ description: "network connection lost",
4692
4928
  });
4693
4929
  };
4694
4930
  addEventListener("offline", this.offlineEventListener, false);
@@ -4699,9 +4935,9 @@ class Socket$1 extends Emitter_1 {
4699
4935
  /**
4700
4936
  * Creates transport of the given type.
4701
4937
  *
4702
- * @param {String} transport name
4938
+ * @param {String} name - transport name
4703
4939
  * @return {Transport}
4704
- * @api private
4940
+ * @private
4705
4941
  */
4706
4942
  createTransport(name) {
4707
4943
  const query = Object.assign({}, this.opts.query);
@@ -4712,19 +4948,19 @@ class Socket$1 extends Emitter_1 {
4712
4948
  // session id if we already have one
4713
4949
  if (this.id)
4714
4950
  query.sid = this.id;
4715
- const opts = Object.assign({}, this.opts.transportOptions[name], this.opts, {
4951
+ const opts = Object.assign({}, this.opts, {
4716
4952
  query,
4717
4953
  socket: this,
4718
4954
  hostname: this.hostname,
4719
4955
  secure: this.secure,
4720
- port: this.port
4721
- });
4956
+ port: this.port,
4957
+ }, this.opts.transportOptions[name]);
4722
4958
  return new transports[name](opts);
4723
4959
  }
4724
4960
  /**
4725
4961
  * Initializes transport to use and starts probe.
4726
4962
  *
4727
- * @api private
4963
+ * @private
4728
4964
  */
4729
4965
  open() {
4730
4966
  let transport;
@@ -4759,7 +4995,7 @@ class Socket$1 extends Emitter_1 {
4759
4995
  /**
4760
4996
  * Sets the current transport. Disables the existing one (if any).
4761
4997
  *
4762
- * @api private
4998
+ * @private
4763
4999
  */
4764
5000
  setTransport(transport) {
4765
5001
  if (this.transport) {
@@ -4772,13 +5008,13 @@ class Socket$1 extends Emitter_1 {
4772
5008
  .on("drain", this.onDrain.bind(this))
4773
5009
  .on("packet", this.onPacket.bind(this))
4774
5010
  .on("error", this.onError.bind(this))
4775
- .on("close", reason => this.onClose("transport close", reason));
5011
+ .on("close", (reason) => this.onClose("transport close", reason));
4776
5012
  }
4777
5013
  /**
4778
5014
  * Probes a transport.
4779
5015
  *
4780
- * @param {String} transport name
4781
- * @api private
5016
+ * @param {String} name - transport name
5017
+ * @private
4782
5018
  */
4783
5019
  probe(name) {
4784
5020
  let transport = this.createTransport(name);
@@ -4788,7 +5024,7 @@ class Socket$1 extends Emitter_1 {
4788
5024
  if (failed)
4789
5025
  return;
4790
5026
  transport.send([{ type: "ping", data: "probe" }]);
4791
- transport.once("packet", msg => {
5027
+ transport.once("packet", (msg) => {
4792
5028
  if (failed)
4793
5029
  return;
4794
5030
  if ("pong" === msg.type && "probe" === msg.data) {
@@ -4829,7 +5065,7 @@ class Socket$1 extends Emitter_1 {
4829
5065
  transport = null;
4830
5066
  }
4831
5067
  // Handle any error that happens while probing
4832
- const onerror = err => {
5068
+ const onerror = (err) => {
4833
5069
  const error = new Error("probe error: " + err);
4834
5070
  // @ts-ignore
4835
5071
  error.transport = transport.name;
@@ -4862,12 +5098,23 @@ class Socket$1 extends Emitter_1 {
4862
5098
  transport.once("close", onTransportClose);
4863
5099
  this.once("close", onclose);
4864
5100
  this.once("upgrading", onupgrade);
4865
- transport.open();
5101
+ if (this.upgrades.indexOf("webtransport") !== -1 &&
5102
+ name !== "webtransport") {
5103
+ // favor WebTransport
5104
+ this.setTimeoutFn(() => {
5105
+ if (!failed) {
5106
+ transport.open();
5107
+ }
5108
+ }, 200);
5109
+ }
5110
+ else {
5111
+ transport.open();
5112
+ }
4866
5113
  }
4867
5114
  /**
4868
5115
  * Called when connection is deemed open.
4869
5116
  *
4870
- * @api private
5117
+ * @private
4871
5118
  */
4872
5119
  onOpen() {
4873
5120
  this.readyState = "open";
@@ -4876,9 +5123,7 @@ class Socket$1 extends Emitter_1 {
4876
5123
  this.flush();
4877
5124
  // we check for `readyState` in case an `open`
4878
5125
  // listener already closed the socket
4879
- if ("open" === this.readyState &&
4880
- this.opts.upgrade &&
4881
- this.transport.pause) {
5126
+ if ("open" === this.readyState && this.opts.upgrade) {
4882
5127
  let i = 0;
4883
5128
  const l = this.upgrades.length;
4884
5129
  for (; i < l; i++) {
@@ -4889,7 +5134,7 @@ class Socket$1 extends Emitter_1 {
4889
5134
  /**
4890
5135
  * Handles a packet.
4891
5136
  *
4892
- * @api private
5137
+ * @private
4893
5138
  */
4894
5139
  onPacket(packet) {
4895
5140
  if ("opening" === this.readyState ||
@@ -4898,12 +5143,12 @@ class Socket$1 extends Emitter_1 {
4898
5143
  this.emitReserved("packet", packet);
4899
5144
  // Socket is live - any packet counts
4900
5145
  this.emitReserved("heartbeat");
5146
+ this.resetPingTimeout();
4901
5147
  switch (packet.type) {
4902
5148
  case "open":
4903
5149
  this.onHandshake(JSON.parse(packet.data));
4904
5150
  break;
4905
5151
  case "ping":
4906
- this.resetPingTimeout();
4907
5152
  this.sendPacket("pong");
4908
5153
  this.emitReserved("ping");
4909
5154
  this.emitReserved("pong");
@@ -4925,7 +5170,7 @@ class Socket$1 extends Emitter_1 {
4925
5170
  * Called upon handshake completion.
4926
5171
  *
4927
5172
  * @param {Object} data - handshake obj
4928
- * @api private
5173
+ * @private
4929
5174
  */
4930
5175
  onHandshake(data) {
4931
5176
  this.emitReserved("handshake", data);
@@ -4944,7 +5189,7 @@ class Socket$1 extends Emitter_1 {
4944
5189
  /**
4945
5190
  * Sets and resets ping timeout timer based on server pings.
4946
5191
  *
4947
- * @api private
5192
+ * @private
4948
5193
  */
4949
5194
  resetPingTimeout() {
4950
5195
  this.clearTimeoutFn(this.pingTimeoutTimer);
@@ -4958,7 +5203,7 @@ class Socket$1 extends Emitter_1 {
4958
5203
  /**
4959
5204
  * Called on `drain` event
4960
5205
  *
4961
- * @api private
5206
+ * @private
4962
5207
  */
4963
5208
  onDrain() {
4964
5209
  this.writeBuffer.splice(0, this.prevBufferLen);
@@ -4976,7 +5221,7 @@ class Socket$1 extends Emitter_1 {
4976
5221
  /**
4977
5222
  * Flush write buffers.
4978
5223
  *
4979
- * @api private
5224
+ * @private
4980
5225
  */
4981
5226
  flush() {
4982
5227
  if ("closed" !== this.readyState &&
@@ -5020,11 +5265,10 @@ class Socket$1 extends Emitter_1 {
5020
5265
  /**
5021
5266
  * Sends a message.
5022
5267
  *
5023
- * @param {String} message.
5024
- * @param {Function} callback function.
5268
+ * @param {String} msg - message.
5025
5269
  * @param {Object} options.
5270
+ * @param {Function} callback function.
5026
5271
  * @return {Socket} for chaining.
5027
- * @api public
5028
5272
  */
5029
5273
  write(msg, options, fn) {
5030
5274
  this.sendPacket("message", msg, options, fn);
@@ -5037,11 +5281,11 @@ class Socket$1 extends Emitter_1 {
5037
5281
  /**
5038
5282
  * Sends a packet.
5039
5283
  *
5040
- * @param {String} packet type.
5284
+ * @param {String} type: packet type.
5041
5285
  * @param {String} data.
5042
5286
  * @param {Object} options.
5043
- * @param {Function} callback function.
5044
- * @api private
5287
+ * @param {Function} fn - callback function.
5288
+ * @private
5045
5289
  */
5046
5290
  sendPacket(type, data, options, fn) {
5047
5291
  if ("function" === typeof data) {
@@ -5060,7 +5304,7 @@ class Socket$1 extends Emitter_1 {
5060
5304
  const packet = {
5061
5305
  type: type,
5062
5306
  data: data,
5063
- options: options
5307
+ options: options,
5064
5308
  };
5065
5309
  this.emitReserved("packetCreate", packet);
5066
5310
  this.writeBuffer.push(packet);
@@ -5070,8 +5314,6 @@ class Socket$1 extends Emitter_1 {
5070
5314
  }
5071
5315
  /**
5072
5316
  * Closes the connection.
5073
- *
5074
- * @api public
5075
5317
  */
5076
5318
  close() {
5077
5319
  const close = () => {
@@ -5112,7 +5354,7 @@ class Socket$1 extends Emitter_1 {
5112
5354
  /**
5113
5355
  * Called upon transport error
5114
5356
  *
5115
- * @api private
5357
+ * @private
5116
5358
  */
5117
5359
  onError(err) {
5118
5360
  Socket$1.priorWebsocketSuccess = false;
@@ -5122,7 +5364,7 @@ class Socket$1 extends Emitter_1 {
5122
5364
  /**
5123
5365
  * Called upon transport close.
5124
5366
  *
5125
- * @api private
5367
+ * @private
5126
5368
  */
5127
5369
  onClose(reason, description) {
5128
5370
  if ("opening" === this.readyState ||
@@ -5155,9 +5397,8 @@ class Socket$1 extends Emitter_1 {
5155
5397
  /**
5156
5398
  * Filters upgrades, returning only those matching client transports.
5157
5399
  *
5158
- * @param {Array} server upgrades
5159
- * @api private
5160
- *
5400
+ * @param {Array} upgrades - server upgrades
5401
+ * @private
5161
5402
  */
5162
5403
  filterUpgrades(upgrades) {
5163
5404
  const filteredUpgrades = [];
@@ -5367,6 +5608,17 @@ function _reconstructPacket(data, buffers) {
5367
5608
  return data;
5368
5609
  }
5369
5610
 
5611
+ /**
5612
+ * These strings must not be used as event names, as they have a special meaning.
5613
+ */
5614
+ const RESERVED_EVENTS$1 = [
5615
+ "connect",
5616
+ "connect_error",
5617
+ "disconnect",
5618
+ "disconnecting",
5619
+ "newListener",
5620
+ "removeListener", // used by the Node.js EventEmitter
5621
+ ];
5370
5622
  /**
5371
5623
  * Protocol version.
5372
5624
  *
@@ -5455,6 +5707,10 @@ class Encoder {
5455
5707
  return buffers; // write all the buffers
5456
5708
  }
5457
5709
  }
5710
+ // see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
5711
+ function isObject(value) {
5712
+ return Object.prototype.toString.call(value) === "[object Object]";
5713
+ }
5458
5714
  /**
5459
5715
  * A socket.io Decoder instance
5460
5716
  *
@@ -5594,14 +5850,17 @@ class Decoder extends Emitter_1 {
5594
5850
  static isPayloadValid(type, payload) {
5595
5851
  switch (type) {
5596
5852
  case PacketType.CONNECT:
5597
- return typeof payload === "object";
5853
+ return isObject(payload);
5598
5854
  case PacketType.DISCONNECT:
5599
5855
  return payload === undefined;
5600
5856
  case PacketType.CONNECT_ERROR:
5601
- return typeof payload === "string" || typeof payload === "object";
5857
+ return typeof payload === "string" || isObject(payload);
5602
5858
  case PacketType.EVENT:
5603
5859
  case PacketType.BINARY_EVENT:
5604
- return Array.isArray(payload) && payload.length > 0;
5860
+ return (Array.isArray(payload) &&
5861
+ (typeof payload[0] === "number" ||
5862
+ (typeof payload[0] === "string" &&
5863
+ RESERVED_EVENTS$1.indexOf(payload[0]) === -1)));
5605
5864
  case PacketType.ACK:
5606
5865
  case PacketType.BINARY_ACK:
5607
5866
  return Array.isArray(payload);
@@ -5686,18 +5945,100 @@ const RESERVED_EVENTS = Object.freeze({
5686
5945
  newListener: 1,
5687
5946
  removeListener: 1,
5688
5947
  });
5948
+ /**
5949
+ * A Socket is the fundamental class for interacting with the server.
5950
+ *
5951
+ * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
5952
+ *
5953
+ * @example
5954
+ * const socket = io();
5955
+ *
5956
+ * socket.on("connect", () => {
5957
+ * console.log("connected");
5958
+ * });
5959
+ *
5960
+ * // send an event to the server
5961
+ * socket.emit("foo", "bar");
5962
+ *
5963
+ * socket.on("foobar", () => {
5964
+ * // an event was received from the server
5965
+ * });
5966
+ *
5967
+ * // upon disconnection
5968
+ * socket.on("disconnect", (reason) => {
5969
+ * console.log(`disconnected due to ${reason}`);
5970
+ * });
5971
+ */
5689
5972
  class Socket extends Emitter_1 {
5690
5973
  /**
5691
5974
  * `Socket` constructor.
5692
- *
5693
- * @public
5694
5975
  */
5695
5976
  constructor(io, nsp, opts) {
5696
5977
  super();
5978
+ /**
5979
+ * Whether the socket is currently connected to the server.
5980
+ *
5981
+ * @example
5982
+ * const socket = io();
5983
+ *
5984
+ * socket.on("connect", () => {
5985
+ * console.log(socket.connected); // true
5986
+ * });
5987
+ *
5988
+ * socket.on("disconnect", () => {
5989
+ * console.log(socket.connected); // false
5990
+ * });
5991
+ */
5697
5992
  this.connected = false;
5993
+ /**
5994
+ * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
5995
+ * be transmitted by the server.
5996
+ */
5997
+ this.recovered = false;
5998
+ /**
5999
+ * Buffer for packets received before the CONNECT packet
6000
+ */
5698
6001
  this.receiveBuffer = [];
6002
+ /**
6003
+ * Buffer for packets that will be sent once the socket is connected
6004
+ */
5699
6005
  this.sendBuffer = [];
6006
+ /**
6007
+ * The queue of packets to be sent with retry in case of failure.
6008
+ *
6009
+ * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
6010
+ * @private
6011
+ */
6012
+ this._queue = [];
6013
+ /**
6014
+ * A sequence to generate the ID of the {@link QueuedPacket}.
6015
+ * @private
6016
+ */
6017
+ this._queueSeq = 0;
5700
6018
  this.ids = 0;
6019
+ /**
6020
+ * A map containing acknowledgement handlers.
6021
+ *
6022
+ * The `withError` attribute is used to differentiate handlers that accept an error as first argument:
6023
+ *
6024
+ * - `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
6025
+ * - `socket.timeout(5000).emit("test", (err, value) => { ... })`
6026
+ * - `const value = await socket.emitWithAck("test")`
6027
+ *
6028
+ * From those that don't:
6029
+ *
6030
+ * - `socket.emit("test", (value) => { ... });`
6031
+ *
6032
+ * In the first case, the handlers will be called with an error when:
6033
+ *
6034
+ * - the timeout is reached
6035
+ * - the socket gets disconnected
6036
+ *
6037
+ * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive
6038
+ * an acknowledgement from the server.
6039
+ *
6040
+ * @private
6041
+ */
5701
6042
  this.acks = {};
5702
6043
  this.flags = {};
5703
6044
  this.io = io;
@@ -5705,11 +6046,23 @@ class Socket extends Emitter_1 {
5705
6046
  if (opts && opts.auth) {
5706
6047
  this.auth = opts.auth;
5707
6048
  }
6049
+ this._opts = Object.assign({}, opts);
5708
6050
  if (this.io._autoConnect)
5709
6051
  this.open();
5710
6052
  }
5711
6053
  /**
5712
6054
  * Whether the socket is currently disconnected
6055
+ *
6056
+ * @example
6057
+ * const socket = io();
6058
+ *
6059
+ * socket.on("connect", () => {
6060
+ * console.log(socket.disconnected); // false
6061
+ * });
6062
+ *
6063
+ * socket.on("disconnect", () => {
6064
+ * console.log(socket.disconnected); // true
6065
+ * });
5713
6066
  */
5714
6067
  get disconnected() {
5715
6068
  return !this.connected;
@@ -5731,7 +6084,21 @@ class Socket extends Emitter_1 {
5731
6084
  ];
5732
6085
  }
5733
6086
  /**
5734
- * Whether the Socket will try to reconnect when its Manager connects or reconnects
6087
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects.
6088
+ *
6089
+ * @example
6090
+ * const socket = io();
6091
+ *
6092
+ * console.log(socket.active); // true
6093
+ *
6094
+ * socket.on("disconnect", (reason) => {
6095
+ * if (reason === "io server disconnect") {
6096
+ * // the disconnection was initiated by the server, you need to manually reconnect
6097
+ * console.log(socket.active); // false
6098
+ * }
6099
+ * // else the socket will automatically try to reconnect
6100
+ * console.log(socket.active); // true
6101
+ * });
5735
6102
  */
5736
6103
  get active() {
5737
6104
  return !!this.subs;
@@ -5739,7 +6106,12 @@ class Socket extends Emitter_1 {
5739
6106
  /**
5740
6107
  * "Opens" the socket.
5741
6108
  *
5742
- * @public
6109
+ * @example
6110
+ * const socket = io({
6111
+ * autoConnect: false
6112
+ * });
6113
+ *
6114
+ * socket.connect();
5743
6115
  */
5744
6116
  connect() {
5745
6117
  if (this.connected)
@@ -5752,7 +6124,7 @@ class Socket extends Emitter_1 {
5752
6124
  return this;
5753
6125
  }
5754
6126
  /**
5755
- * Alias for connect()
6127
+ * Alias for {@link connect()}.
5756
6128
  */
5757
6129
  open() {
5758
6130
  return this.connect();
@@ -5760,8 +6132,17 @@ class Socket extends Emitter_1 {
5760
6132
  /**
5761
6133
  * Sends a `message` event.
5762
6134
  *
6135
+ * This method mimics the WebSocket.send() method.
6136
+ *
6137
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
6138
+ *
6139
+ * @example
6140
+ * socket.send("hello");
6141
+ *
6142
+ * // this is equivalent to
6143
+ * socket.emit("message", "hello");
6144
+ *
5763
6145
  * @return self
5764
- * @public
5765
6146
  */
5766
6147
  send(...args) {
5767
6148
  args.unshift("message");
@@ -5772,14 +6153,28 @@ class Socket extends Emitter_1 {
5772
6153
  * Override `emit`.
5773
6154
  * If the event is in `events`, it's emitted normally.
5774
6155
  *
6156
+ * @example
6157
+ * socket.emit("hello", "world");
6158
+ *
6159
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
6160
+ * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
6161
+ *
6162
+ * // with an acknowledgement from the server
6163
+ * socket.emit("hello", "world", (val) => {
6164
+ * // ...
6165
+ * });
6166
+ *
5775
6167
  * @return self
5776
- * @public
5777
6168
  */
5778
6169
  emit(ev, ...args) {
5779
6170
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
5780
- throw new Error('"' + ev + '" is a reserved event name');
6171
+ throw new Error('"' + ev.toString() + '" is a reserved event name');
5781
6172
  }
5782
6173
  args.unshift(ev);
6174
+ if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
6175
+ this._addToQueue(args);
6176
+ return this;
6177
+ }
5783
6178
  const packet = {
5784
6179
  type: PacketType.EVENT,
5785
6180
  data: args,
@@ -5812,7 +6207,8 @@ class Socket extends Emitter_1 {
5812
6207
  * @private
5813
6208
  */
5814
6209
  _registerAckCallback(id, ack) {
5815
- const timeout = this.flags.timeout;
6210
+ var _a;
6211
+ const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
5816
6212
  if (timeout === undefined) {
5817
6213
  this.acks[id] = ack;
5818
6214
  return;
@@ -5827,11 +6223,101 @@ class Socket extends Emitter_1 {
5827
6223
  }
5828
6224
  ack.call(this, new Error("operation has timed out"));
5829
6225
  }, timeout);
5830
- this.acks[id] = (...args) => {
6226
+ const fn = (...args) => {
5831
6227
  // @ts-ignore
5832
6228
  this.io.clearTimeoutFn(timer);
5833
- ack.apply(this, [null, ...args]);
6229
+ ack.apply(this, args);
6230
+ };
6231
+ fn.withError = true;
6232
+ this.acks[id] = fn;
6233
+ }
6234
+ /**
6235
+ * Emits an event and waits for an acknowledgement
6236
+ *
6237
+ * @example
6238
+ * // without timeout
6239
+ * const response = await socket.emitWithAck("hello", "world");
6240
+ *
6241
+ * // with a specific timeout
6242
+ * try {
6243
+ * const response = await socket.timeout(1000).emitWithAck("hello", "world");
6244
+ * } catch (err) {
6245
+ * // the server did not acknowledge the event in the given delay
6246
+ * }
6247
+ *
6248
+ * @return a Promise that will be fulfilled when the server acknowledges the event
6249
+ */
6250
+ emitWithAck(ev, ...args) {
6251
+ return new Promise((resolve, reject) => {
6252
+ const fn = (arg1, arg2) => {
6253
+ return arg1 ? reject(arg1) : resolve(arg2);
6254
+ };
6255
+ fn.withError = true;
6256
+ args.push(fn);
6257
+ this.emit(ev, ...args);
6258
+ });
6259
+ }
6260
+ /**
6261
+ * Add the packet to the queue.
6262
+ * @param args
6263
+ * @private
6264
+ */
6265
+ _addToQueue(args) {
6266
+ let ack;
6267
+ if (typeof args[args.length - 1] === "function") {
6268
+ ack = args.pop();
6269
+ }
6270
+ const packet = {
6271
+ id: this._queueSeq++,
6272
+ tryCount: 0,
6273
+ pending: false,
6274
+ args,
6275
+ flags: Object.assign({ fromQueue: true }, this.flags),
5834
6276
  };
6277
+ args.push((err, ...responseArgs) => {
6278
+ if (packet !== this._queue[0]) {
6279
+ // the packet has already been acknowledged
6280
+ return;
6281
+ }
6282
+ const hasError = err !== null;
6283
+ if (hasError) {
6284
+ if (packet.tryCount > this._opts.retries) {
6285
+ this._queue.shift();
6286
+ if (ack) {
6287
+ ack(err);
6288
+ }
6289
+ }
6290
+ }
6291
+ else {
6292
+ this._queue.shift();
6293
+ if (ack) {
6294
+ ack(null, ...responseArgs);
6295
+ }
6296
+ }
6297
+ packet.pending = false;
6298
+ return this._drainQueue();
6299
+ });
6300
+ this._queue.push(packet);
6301
+ this._drainQueue();
6302
+ }
6303
+ /**
6304
+ * Send the first packet of the queue, and wait for an acknowledgement from the server.
6305
+ * @param force - whether to resend a packet that has not been acknowledged yet
6306
+ *
6307
+ * @private
6308
+ */
6309
+ _drainQueue(force = false) {
6310
+ if (!this.connected || this._queue.length === 0) {
6311
+ return;
6312
+ }
6313
+ const packet = this._queue[0];
6314
+ if (packet.pending && !force) {
6315
+ return;
6316
+ }
6317
+ packet.pending = true;
6318
+ packet.tryCount++;
6319
+ this.flags = packet.flags;
6320
+ this.emit.apply(this, packet.args);
5835
6321
  }
5836
6322
  /**
5837
6323
  * Sends a packet.
@@ -5851,13 +6337,27 @@ class Socket extends Emitter_1 {
5851
6337
  onopen() {
5852
6338
  if (typeof this.auth == "function") {
5853
6339
  this.auth((data) => {
5854
- this.packet({ type: PacketType.CONNECT, data });
6340
+ this._sendConnectPacket(data);
5855
6341
  });
5856
6342
  }
5857
6343
  else {
5858
- this.packet({ type: PacketType.CONNECT, data: this.auth });
6344
+ this._sendConnectPacket(this.auth);
5859
6345
  }
5860
6346
  }
6347
+ /**
6348
+ * Sends a CONNECT packet to initiate the Socket.IO session.
6349
+ *
6350
+ * @param data
6351
+ * @private
6352
+ */
6353
+ _sendConnectPacket(data) {
6354
+ this.packet({
6355
+ type: PacketType.CONNECT,
6356
+ data: this._pid
6357
+ ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
6358
+ : data,
6359
+ });
6360
+ }
5861
6361
  /**
5862
6362
  * Called upon engine or manager `error`.
5863
6363
  *
@@ -5880,6 +6380,26 @@ class Socket extends Emitter_1 {
5880
6380
  this.connected = false;
5881
6381
  delete this.id;
5882
6382
  this.emitReserved("disconnect", reason, description);
6383
+ this._clearAcks();
6384
+ }
6385
+ /**
6386
+ * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from
6387
+ * the server.
6388
+ *
6389
+ * @private
6390
+ */
6391
+ _clearAcks() {
6392
+ Object.keys(this.acks).forEach((id) => {
6393
+ const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);
6394
+ if (!isBuffered) {
6395
+ // note: handlers that do not accept an error as first argument are ignored here
6396
+ const ack = this.acks[id];
6397
+ delete this.acks[id];
6398
+ if (ack.withError) {
6399
+ ack.call(this, new Error("socket has been disconnected"));
6400
+ }
6401
+ }
6402
+ });
5883
6403
  }
5884
6404
  /**
5885
6405
  * Called with socket packet.
@@ -5894,8 +6414,7 @@ class Socket extends Emitter_1 {
5894
6414
  switch (packet.type) {
5895
6415
  case PacketType.CONNECT:
5896
6416
  if (packet.data && packet.data.sid) {
5897
- const id = packet.data.sid;
5898
- this.onconnect(id);
6417
+ this.onconnect(packet.data.sid, packet.data.pid);
5899
6418
  }
5900
6419
  else {
5901
6420
  this.emitReserved("connect_error", new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));
@@ -5947,6 +6466,9 @@ class Socket extends Emitter_1 {
5947
6466
  }
5948
6467
  }
5949
6468
  super.emit.apply(this, args);
6469
+ if (this._pid && args.length && typeof args[args.length - 1] === "string") {
6470
+ this._lastOffset = args[args.length - 1];
6471
+ }
5950
6472
  }
5951
6473
  /**
5952
6474
  * Produces an ack callback to emit with an event.
@@ -5969,28 +6491,37 @@ class Socket extends Emitter_1 {
5969
6491
  };
5970
6492
  }
5971
6493
  /**
5972
- * Called upon a server acknowlegement.
6494
+ * Called upon a server acknowledgement.
5973
6495
  *
5974
6496
  * @param packet
5975
6497
  * @private
5976
6498
  */
5977
6499
  onack(packet) {
5978
6500
  const ack = this.acks[packet.id];
5979
- if ("function" === typeof ack) {
5980
- ack.apply(this, packet.data);
5981
- delete this.acks[packet.id];
6501
+ if (typeof ack !== "function") {
6502
+ return;
6503
+ }
6504
+ delete this.acks[packet.id];
6505
+ // @ts-ignore FIXME ack is incorrectly inferred as 'never'
6506
+ if (ack.withError) {
6507
+ packet.data.unshift(null);
5982
6508
  }
6509
+ // @ts-ignore
6510
+ ack.apply(this, packet.data);
5983
6511
  }
5984
6512
  /**
5985
6513
  * Called upon server connect.
5986
6514
  *
5987
6515
  * @private
5988
6516
  */
5989
- onconnect(id) {
6517
+ onconnect(id, pid) {
5990
6518
  this.id = id;
6519
+ this.recovered = pid && this._pid === pid;
6520
+ this._pid = pid; // defined only if connection state recovery is enabled
5991
6521
  this.connected = true;
5992
6522
  this.emitBuffered();
5993
6523
  this.emitReserved("connect");
6524
+ this._drainQueue(true);
5994
6525
  }
5995
6526
  /**
5996
6527
  * Emit buffered events (received and emitted).
@@ -6031,10 +6562,20 @@ class Socket extends Emitter_1 {
6031
6562
  this.io["_destroy"](this);
6032
6563
  }
6033
6564
  /**
6034
- * Disconnects the socket manually.
6565
+ * Disconnects the socket manually. In that case, the socket will not try to reconnect.
6566
+ *
6567
+ * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
6568
+ *
6569
+ * @example
6570
+ * const socket = io();
6571
+ *
6572
+ * socket.on("disconnect", (reason) => {
6573
+ * // console.log(reason); prints "io client disconnect"
6574
+ * });
6575
+ *
6576
+ * socket.disconnect();
6035
6577
  *
6036
6578
  * @return self
6037
- * @public
6038
6579
  */
6039
6580
  disconnect() {
6040
6581
  if (this.connected) {
@@ -6049,10 +6590,9 @@ class Socket extends Emitter_1 {
6049
6590
  return this;
6050
6591
  }
6051
6592
  /**
6052
- * Alias for disconnect()
6593
+ * Alias for {@link disconnect()}.
6053
6594
  *
6054
6595
  * @return self
6055
- * @public
6056
6596
  */
6057
6597
  close() {
6058
6598
  return this.disconnect();
@@ -6060,9 +6600,11 @@ class Socket extends Emitter_1 {
6060
6600
  /**
6061
6601
  * Sets the compress flag.
6062
6602
  *
6603
+ * @example
6604
+ * socket.compress(false).emit("hello");
6605
+ *
6063
6606
  * @param compress - if `true`, compresses the sending data
6064
6607
  * @return self
6065
- * @public
6066
6608
  */
6067
6609
  compress(compress) {
6068
6610
  this.flags.compress = compress;
@@ -6072,8 +6614,10 @@ class Socket extends Emitter_1 {
6072
6614
  * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
6073
6615
  * ready to send messages.
6074
6616
  *
6617
+ * @example
6618
+ * socket.volatile.emit("hello"); // the server may or may not receive it
6619
+ *
6075
6620
  * @returns self
6076
- * @public
6077
6621
  */
6078
6622
  get volatile() {
6079
6623
  this.flags.volatile = true;
@@ -6083,16 +6627,14 @@ class Socket extends Emitter_1 {
6083
6627
  * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
6084
6628
  * given number of milliseconds have elapsed without an acknowledgement from the server:
6085
6629
  *
6086
- * ```
6630
+ * @example
6087
6631
  * socket.timeout(5000).emit("my-event", (err) => {
6088
6632
  * if (err) {
6089
6633
  * // the server did not acknowledge the event in the given delay
6090
6634
  * }
6091
6635
  * });
6092
- * ```
6093
6636
  *
6094
6637
  * @returns self
6095
- * @public
6096
6638
  */
6097
6639
  timeout(timeout) {
6098
6640
  this.flags.timeout = timeout;
@@ -6102,8 +6644,12 @@ class Socket extends Emitter_1 {
6102
6644
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6103
6645
  * callback.
6104
6646
  *
6647
+ * @example
6648
+ * socket.onAny((event, ...args) => {
6649
+ * console.log(`got ${event}`);
6650
+ * });
6651
+ *
6105
6652
  * @param listener
6106
- * @public
6107
6653
  */
6108
6654
  onAny(listener) {
6109
6655
  this._anyListeners = this._anyListeners || [];
@@ -6114,8 +6660,12 @@ class Socket extends Emitter_1 {
6114
6660
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6115
6661
  * callback. The listener is added to the beginning of the listeners array.
6116
6662
  *
6663
+ * @example
6664
+ * socket.prependAny((event, ...args) => {
6665
+ * console.log(`got event ${event}`);
6666
+ * });
6667
+ *
6117
6668
  * @param listener
6118
- * @public
6119
6669
  */
6120
6670
  prependAny(listener) {
6121
6671
  this._anyListeners = this._anyListeners || [];
@@ -6125,8 +6675,20 @@ class Socket extends Emitter_1 {
6125
6675
  /**
6126
6676
  * Removes the listener that will be fired when any event is emitted.
6127
6677
  *
6678
+ * @example
6679
+ * const catchAllListener = (event, ...args) => {
6680
+ * console.log(`got event ${event}`);
6681
+ * }
6682
+ *
6683
+ * socket.onAny(catchAllListener);
6684
+ *
6685
+ * // remove a specific listener
6686
+ * socket.offAny(catchAllListener);
6687
+ *
6688
+ * // or remove all listeners
6689
+ * socket.offAny();
6690
+ *
6128
6691
  * @param listener
6129
- * @public
6130
6692
  */
6131
6693
  offAny(listener) {
6132
6694
  if (!this._anyListeners) {
@@ -6149,8 +6711,6 @@ class Socket extends Emitter_1 {
6149
6711
  /**
6150
6712
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6151
6713
  * e.g. to remove listeners.
6152
- *
6153
- * @public
6154
6714
  */
6155
6715
  listenersAny() {
6156
6716
  return this._anyListeners || [];
@@ -6159,17 +6719,14 @@ class Socket extends Emitter_1 {
6159
6719
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6160
6720
  * callback.
6161
6721
  *
6162
- * @param listener
6163
- *
6164
- * <pre><code>
6722
+ * Note: acknowledgements sent to the server are not included.
6165
6723
  *
6724
+ * @example
6166
6725
  * socket.onAnyOutgoing((event, ...args) => {
6167
- * console.log(event);
6726
+ * console.log(`sent event ${event}`);
6168
6727
  * });
6169
6728
  *
6170
- * </pre></code>
6171
- *
6172
- * @public
6729
+ * @param listener
6173
6730
  */
6174
6731
  onAnyOutgoing(listener) {
6175
6732
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6180,17 +6737,14 @@ class Socket extends Emitter_1 {
6180
6737
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6181
6738
  * callback. The listener is added to the beginning of the listeners array.
6182
6739
  *
6183
- * @param listener
6184
- *
6185
- * <pre><code>
6740
+ * Note: acknowledgements sent to the server are not included.
6186
6741
  *
6742
+ * @example
6187
6743
  * socket.prependAnyOutgoing((event, ...args) => {
6188
- * console.log(event);
6744
+ * console.log(`sent event ${event}`);
6189
6745
  * });
6190
6746
  *
6191
- * </pre></code>
6192
- *
6193
- * @public
6747
+ * @param listener
6194
6748
  */
6195
6749
  prependAnyOutgoing(listener) {
6196
6750
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6200,22 +6754,20 @@ class Socket extends Emitter_1 {
6200
6754
  /**
6201
6755
  * Removes the listener that will be fired when any event is emitted.
6202
6756
  *
6203
- * @param listener
6204
- *
6205
- * <pre><code>
6206
- *
6207
- * const handler = (event, ...args) => {
6208
- * console.log(event);
6757
+ * @example
6758
+ * const catchAllListener = (event, ...args) => {
6759
+ * console.log(`sent event ${event}`);
6209
6760
  * }
6210
6761
  *
6211
- * socket.onAnyOutgoing(handler);
6762
+ * socket.onAnyOutgoing(catchAllListener);
6212
6763
  *
6213
- * // then later
6214
- * socket.offAnyOutgoing(handler);
6764
+ * // remove a specific listener
6765
+ * socket.offAnyOutgoing(catchAllListener);
6215
6766
  *
6216
- * </pre></code>
6767
+ * // or remove all listeners
6768
+ * socket.offAnyOutgoing();
6217
6769
  *
6218
- * @public
6770
+ * @param [listener] - the catch-all listener (optional)
6219
6771
  */
6220
6772
  offAnyOutgoing(listener) {
6221
6773
  if (!this._anyOutgoingListeners) {
@@ -6238,8 +6790,6 @@ class Socket extends Emitter_1 {
6238
6790
  /**
6239
6791
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6240
6792
  * e.g. to remove listeners.
6241
- *
6242
- * @public
6243
6793
  */
6244
6794
  listenersAnyOutgoing() {
6245
6795
  return this._anyOutgoingListeners || [];
@@ -6439,36 +6989,33 @@ class Manager extends Emitter_1 {
6439
6989
  self.onopen();
6440
6990
  fn && fn();
6441
6991
  });
6442
- // emit `error`
6443
- const errorSub = on(socket, "error", (err) => {
6444
- self.cleanup();
6445
- self._readyState = "closed";
6992
+ const onError = (err) => {
6993
+ this.cleanup();
6994
+ this._readyState = "closed";
6446
6995
  this.emitReserved("error", err);
6447
6996
  if (fn) {
6448
6997
  fn(err);
6449
6998
  }
6450
6999
  else {
6451
7000
  // Only do this if there is no fn to handle the error
6452
- self.maybeReconnectOnOpen();
7001
+ this.maybeReconnectOnOpen();
6453
7002
  }
6454
- });
7003
+ };
7004
+ // emit `error`
7005
+ const errorSub = on(socket, "error", onError);
6455
7006
  if (false !== this._timeout) {
6456
7007
  const timeout = this._timeout;
6457
- if (timeout === 0) {
6458
- openSubDestroy(); // prevents a race condition with the 'open' event
6459
- }
6460
7008
  // set timer
6461
7009
  const timer = this.setTimeoutFn(() => {
6462
7010
  openSubDestroy();
7011
+ onError(new Error("timeout"));
6463
7012
  socket.close();
6464
- // @ts-ignore
6465
- socket.emit("error", new Error("timeout"));
6466
7013
  }, timeout);
6467
7014
  if (this.opts.autoUnref) {
6468
7015
  timer.unref();
6469
7016
  }
6470
- this.subs.push(function subDestroy() {
6471
- clearTimeout(timer);
7017
+ this.subs.push(() => {
7018
+ this.clearTimeoutFn(timer);
6472
7019
  });
6473
7020
  }
6474
7021
  this.subs.push(openSubDestroy);
@@ -6513,7 +7060,12 @@ class Manager extends Emitter_1 {
6513
7060
  * @private
6514
7061
  */
6515
7062
  ondata(data) {
6516
- this.decoder.add(data);
7063
+ try {
7064
+ this.decoder.add(data);
7065
+ }
7066
+ catch (e) {
7067
+ this.onclose("parse error", e);
7068
+ }
6517
7069
  }
6518
7070
  /**
6519
7071
  * Called when parser fully decodes a packet.
@@ -6521,7 +7073,10 @@ class Manager extends Emitter_1 {
6521
7073
  * @private
6522
7074
  */
6523
7075
  ondecoded(packet) {
6524
- this.emitReserved("packet", packet);
7076
+ // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a "parse error"
7077
+ nextTick(() => {
7078
+ this.emitReserved("packet", packet);
7079
+ }, this.setTimeoutFn);
6525
7080
  }
6526
7081
  /**
6527
7082
  * Called upon socket error.
@@ -6543,6 +7098,9 @@ class Manager extends Emitter_1 {
6543
7098
  socket = new Socket(this, nsp, opts);
6544
7099
  this.nsps[nsp] = socket;
6545
7100
  }
7101
+ else if (this._autoConnect && !socket.active) {
7102
+ socket.connect();
7103
+ }
6546
7104
  return socket;
6547
7105
  }
6548
7106
  /**
@@ -6655,8 +7213,8 @@ class Manager extends Emitter_1 {
6655
7213
  if (this.opts.autoUnref) {
6656
7214
  timer.unref();
6657
7215
  }
6658
- this.subs.push(function subDestroy() {
6659
- clearTimeout(timer);
7216
+ this.subs.push(() => {
7217
+ this.clearTimeoutFn(timer);
6660
7218
  });
6661
7219
  }
6662
7220
  }