@xapp/chat-widget 1.69.0 → 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.js CHANGED
@@ -2304,9 +2304,9 @@ var StentorDirectChat = /** @class */ (function () {
2304
2304
  return __assign(__assign({}, user), { nick: user.nick || bot.nick || "Bot", displayName: user.displayName || bot.displayName || "Bot", avatarPath: user.avatarPath || bot.avatarPath });
2305
2305
  };
2306
2306
  StentorDirectChat.prototype.sendChatMsgRequest = function (serviceRequest, cb) {
2307
- var _a;
2308
2307
  return __awaiter$1(this, void 0, void 0, function () {
2309
2308
  var agentResponse;
2309
+ var _a;
2310
2310
  return __generator$1(this, function (_b) {
2311
2311
  switch (_b.label) {
2312
2312
  case 0: return [4 /*yield*/, this.postMessage(serviceRequest)];
@@ -2362,10 +2362,10 @@ var StentorDirectChat = /** @class */ (function () {
2362
2362
  StentorDirectChat.prototype.wakeup = function () {
2363
2363
  };
2364
2364
  StentorDirectChat.prototype.postMessage = function (message) {
2365
- var _a, _b, _c, _d, _e;
2366
2365
  return __awaiter$1(this, void 0, void 0, function () {
2367
2366
  var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
2368
2367
  var _this = this;
2368
+ var _a, _b, _c, _d, _e;
2369
2369
  return __generator$1(this, function (_f) {
2370
2370
  switch (_f.label) {
2371
2371
  case 0:
@@ -3375,7 +3375,7 @@ PACKET_TYPES["message"] = "4";
3375
3375
  PACKET_TYPES["upgrade"] = "5";
3376
3376
  PACKET_TYPES["noop"] = "6";
3377
3377
  const PACKET_TYPES_REVERSE = Object.create(null);
3378
- Object.keys(PACKET_TYPES).forEach(key => {
3378
+ Object.keys(PACKET_TYPES).forEach((key) => {
3379
3379
  PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
3380
3380
  });
3381
3381
  const ERROR_PACKET = { type: "error", data: "parser error" };
@@ -3385,7 +3385,7 @@ const withNativeBlob$1 = typeof Blob === "function" ||
3385
3385
  Object.prototype.toString.call(Blob) === "[object BlobConstructor]");
3386
3386
  const withNativeArrayBuffer$2 = typeof ArrayBuffer === "function";
3387
3387
  // ArrayBuffer.isView method is not defined in IE10
3388
- const isView$1 = obj => {
3388
+ const isView$1 = (obj) => {
3389
3389
  return typeof ArrayBuffer.isView === "function"
3390
3390
  ? ArrayBuffer.isView(obj)
3391
3391
  : obj && obj.buffer instanceof ArrayBuffer;
@@ -3419,6 +3419,33 @@ const encodeBlobAsBase64 = (data, callback) => {
3419
3419
  };
3420
3420
  return fileReader.readAsDataURL(data);
3421
3421
  };
3422
+ function toArray(data) {
3423
+ if (data instanceof Uint8Array) {
3424
+ return data;
3425
+ }
3426
+ else if (data instanceof ArrayBuffer) {
3427
+ return new Uint8Array(data);
3428
+ }
3429
+ else {
3430
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
3431
+ }
3432
+ }
3433
+ let TEXT_ENCODER;
3434
+ function encodePacketToBinary(packet, callback) {
3435
+ if (withNativeBlob$1 && packet.data instanceof Blob) {
3436
+ return packet.data.arrayBuffer().then(toArray).then(callback);
3437
+ }
3438
+ else if (withNativeArrayBuffer$2 &&
3439
+ (packet.data instanceof ArrayBuffer || isView$1(packet.data))) {
3440
+ return callback(toArray(packet.data));
3441
+ }
3442
+ encodePacket(packet, false, (encoded) => {
3443
+ if (!TEXT_ENCODER) {
3444
+ TEXT_ENCODER = new TextEncoder();
3445
+ }
3446
+ callback(TEXT_ENCODER.encode(encoded));
3447
+ });
3448
+ }
3422
3449
 
3423
3450
  // imported from https://github.com/socketio/base64-arraybuffer
3424
3451
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -3453,14 +3480,14 @@ const decodePacket = (encodedPacket, binaryType) => {
3453
3480
  if (typeof encodedPacket !== "string") {
3454
3481
  return {
3455
3482
  type: "message",
3456
- data: mapBinary(encodedPacket, binaryType)
3483
+ data: mapBinary(encodedPacket, binaryType),
3457
3484
  };
3458
3485
  }
3459
3486
  const type = encodedPacket.charAt(0);
3460
3487
  if (type === "b") {
3461
3488
  return {
3462
3489
  type: "message",
3463
- data: decodeBase64Packet(encodedPacket.substring(1), binaryType)
3490
+ data: decodeBase64Packet(encodedPacket.substring(1), binaryType),
3464
3491
  };
3465
3492
  }
3466
3493
  const packetType = PACKET_TYPES_REVERSE[type];
@@ -3470,10 +3497,10 @@ const decodePacket = (encodedPacket, binaryType) => {
3470
3497
  return encodedPacket.length > 1
3471
3498
  ? {
3472
3499
  type: PACKET_TYPES_REVERSE[type],
3473
- data: encodedPacket.substring(1)
3500
+ data: encodedPacket.substring(1),
3474
3501
  }
3475
3502
  : {
3476
- type: PACKET_TYPES_REVERSE[type]
3503
+ type: PACKET_TYPES_REVERSE[type],
3477
3504
  };
3478
3505
  };
3479
3506
  const decodeBase64Packet = (data, binaryType) => {
@@ -3488,10 +3515,24 @@ const decodeBase64Packet = (data, binaryType) => {
3488
3515
  const mapBinary = (data, binaryType) => {
3489
3516
  switch (binaryType) {
3490
3517
  case "blob":
3491
- return data instanceof ArrayBuffer ? new Blob([data]) : data;
3518
+ if (data instanceof Blob) {
3519
+ // from WebSocket + binaryType "blob"
3520
+ return data;
3521
+ }
3522
+ else {
3523
+ // from HTTP long-polling or WebTransport
3524
+ return new Blob([data]);
3525
+ }
3492
3526
  case "arraybuffer":
3493
3527
  default:
3494
- return data; // assuming the data is already an ArrayBuffer
3528
+ if (data instanceof ArrayBuffer) {
3529
+ // from HTTP long-polling (base64) or WebSocket + binaryType "arraybuffer"
3530
+ return data;
3531
+ }
3532
+ else {
3533
+ // from WebTransport (Uint8Array)
3534
+ return data.buffer;
3535
+ }
3495
3536
  }
3496
3537
  };
3497
3538
 
@@ -3503,7 +3544,7 @@ const encodePayload = (packets, callback) => {
3503
3544
  let count = 0;
3504
3545
  packets.forEach((packet, i) => {
3505
3546
  // force base64 encoding for binary packets
3506
- encodePacket(packet, false, encodedPacket => {
3547
+ encodePacket(packet, false, (encodedPacket) => {
3507
3548
  encodedPackets[i] = encodedPacket;
3508
3549
  if (++count === length) {
3509
3550
  callback(encodedPackets.join(SEPARATOR));
@@ -3523,6 +3564,131 @@ const decodePayload = (encodedPayload, binaryType) => {
3523
3564
  }
3524
3565
  return packets;
3525
3566
  };
3567
+ function createPacketEncoderStream() {
3568
+ // @ts-expect-error
3569
+ return new TransformStream({
3570
+ transform(packet, controller) {
3571
+ encodePacketToBinary(packet, (encodedPacket) => {
3572
+ const payloadLength = encodedPacket.length;
3573
+ let header;
3574
+ // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
3575
+ if (payloadLength < 126) {
3576
+ header = new Uint8Array(1);
3577
+ new DataView(header.buffer).setUint8(0, payloadLength);
3578
+ }
3579
+ else if (payloadLength < 65536) {
3580
+ header = new Uint8Array(3);
3581
+ const view = new DataView(header.buffer);
3582
+ view.setUint8(0, 126);
3583
+ view.setUint16(1, payloadLength);
3584
+ }
3585
+ else {
3586
+ header = new Uint8Array(9);
3587
+ const view = new DataView(header.buffer);
3588
+ view.setUint8(0, 127);
3589
+ view.setBigUint64(1, BigInt(payloadLength));
3590
+ }
3591
+ // first bit indicates whether the payload is plain text (0) or binary (1)
3592
+ if (packet.data && typeof packet.data !== "string") {
3593
+ header[0] |= 0x80;
3594
+ }
3595
+ controller.enqueue(header);
3596
+ controller.enqueue(encodedPacket);
3597
+ });
3598
+ },
3599
+ });
3600
+ }
3601
+ let TEXT_DECODER;
3602
+ function totalLength(chunks) {
3603
+ return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
3604
+ }
3605
+ function concatChunks(chunks, size) {
3606
+ if (chunks[0].length === size) {
3607
+ return chunks.shift();
3608
+ }
3609
+ const buffer = new Uint8Array(size);
3610
+ let j = 0;
3611
+ for (let i = 0; i < size; i++) {
3612
+ buffer[i] = chunks[0][j++];
3613
+ if (j === chunks[0].length) {
3614
+ chunks.shift();
3615
+ j = 0;
3616
+ }
3617
+ }
3618
+ if (chunks.length && j < chunks[0].length) {
3619
+ chunks[0] = chunks[0].slice(j);
3620
+ }
3621
+ return buffer;
3622
+ }
3623
+ function createPacketDecoderStream(maxPayload, binaryType) {
3624
+ if (!TEXT_DECODER) {
3625
+ TEXT_DECODER = new TextDecoder();
3626
+ }
3627
+ const chunks = [];
3628
+ let state = 0 /* READ_HEADER */;
3629
+ let expectedLength = -1;
3630
+ let isBinary = false;
3631
+ // @ts-expect-error
3632
+ return new TransformStream({
3633
+ transform(chunk, controller) {
3634
+ chunks.push(chunk);
3635
+ while (true) {
3636
+ if (state === 0 /* READ_HEADER */) {
3637
+ if (totalLength(chunks) < 1) {
3638
+ break;
3639
+ }
3640
+ const header = concatChunks(chunks, 1);
3641
+ isBinary = (header[0] & 0x80) === 0x80;
3642
+ expectedLength = header[0] & 0x7f;
3643
+ if (expectedLength < 126) {
3644
+ state = 3 /* READ_PAYLOAD */;
3645
+ }
3646
+ else if (expectedLength === 126) {
3647
+ state = 1 /* READ_EXTENDED_LENGTH_16 */;
3648
+ }
3649
+ else {
3650
+ state = 2 /* READ_EXTENDED_LENGTH_64 */;
3651
+ }
3652
+ }
3653
+ else if (state === 1 /* READ_EXTENDED_LENGTH_16 */) {
3654
+ if (totalLength(chunks) < 2) {
3655
+ break;
3656
+ }
3657
+ const headerArray = concatChunks(chunks, 2);
3658
+ expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
3659
+ state = 3 /* READ_PAYLOAD */;
3660
+ }
3661
+ else if (state === 2 /* READ_EXTENDED_LENGTH_64 */) {
3662
+ if (totalLength(chunks) < 8) {
3663
+ break;
3664
+ }
3665
+ const headerArray = concatChunks(chunks, 8);
3666
+ const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
3667
+ const n = view.getUint32(0);
3668
+ if (n > Math.pow(2, 53 - 32) - 1) {
3669
+ // the maximum safe integer in JavaScript is 2^53 - 1
3670
+ controller.enqueue(ERROR_PACKET);
3671
+ break;
3672
+ }
3673
+ expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
3674
+ state = 3 /* READ_PAYLOAD */;
3675
+ }
3676
+ else {
3677
+ if (totalLength(chunks) < expectedLength) {
3678
+ break;
3679
+ }
3680
+ const data = concatChunks(chunks, expectedLength);
3681
+ controller.enqueue(decodePacket(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
3682
+ state = 0 /* READ_HEADER */;
3683
+ }
3684
+ if (expectedLength === 0 || expectedLength > maxPayload) {
3685
+ controller.enqueue(ERROR_PACKET);
3686
+ break;
3687
+ }
3688
+ }
3689
+ },
3690
+ });
3691
+ }
3526
3692
  const protocol$1 = 4;
3527
3693
 
3528
3694
  /**
@@ -3722,16 +3888,16 @@ function pick(obj, ...attr) {
3722
3888
  }, {});
3723
3889
  }
3724
3890
  // Keep a reference to the real timeout functions so they can be used when overridden
3725
- const NATIVE_SET_TIMEOUT = setTimeout;
3726
- const NATIVE_CLEAR_TIMEOUT = clearTimeout;
3891
+ const NATIVE_SET_TIMEOUT = globalThisShim.setTimeout;
3892
+ const NATIVE_CLEAR_TIMEOUT = globalThisShim.clearTimeout;
3727
3893
  function installTimerFunctions(obj, opts) {
3728
3894
  if (opts.useNativeTimers) {
3729
3895
  obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThisShim);
3730
3896
  obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThisShim);
3731
3897
  }
3732
3898
  else {
3733
- obj.setTimeoutFn = setTimeout.bind(globalThisShim);
3734
- obj.clearTimeoutFn = clearTimeout.bind(globalThisShim);
3899
+ obj.setTimeoutFn = globalThisShim.setTimeout.bind(globalThisShim);
3900
+ obj.clearTimeoutFn = globalThisShim.clearTimeout.bind(globalThisShim);
3735
3901
  }
3736
3902
  }
3737
3903
  // base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
@@ -3765,6 +3931,41 @@ function utf8Length(str) {
3765
3931
  return length;
3766
3932
  }
3767
3933
 
3934
+ // imported from https://github.com/galkn/querystring
3935
+ /**
3936
+ * Compiles a querystring
3937
+ * Returns string representation of the object
3938
+ *
3939
+ * @param {Object}
3940
+ * @api private
3941
+ */
3942
+ function encode$1(obj) {
3943
+ let str = '';
3944
+ for (let i in obj) {
3945
+ if (obj.hasOwnProperty(i)) {
3946
+ if (str.length)
3947
+ str += '&';
3948
+ str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3949
+ }
3950
+ }
3951
+ return str;
3952
+ }
3953
+ /**
3954
+ * Parses a simple querystring into an object
3955
+ *
3956
+ * @param {String} qs
3957
+ * @api private
3958
+ */
3959
+ function decode(qs) {
3960
+ let qry = {};
3961
+ let pairs = qs.split('&');
3962
+ for (let i = 0, l = pairs.length; i < l; i++) {
3963
+ let pair = pairs[i].split('=');
3964
+ qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3965
+ }
3966
+ return qry;
3967
+ }
3968
+
3768
3969
  class TransportError extends Error {
3769
3970
  constructor(reason, description, context) {
3770
3971
  super(reason);
@@ -3777,8 +3978,8 @@ class Transport extends Emitter_1 {
3777
3978
  /**
3778
3979
  * Transport abstract constructor.
3779
3980
  *
3780
- * @param {Object} options.
3781
- * @api private
3981
+ * @param {Object} opts - options
3982
+ * @protected
3782
3983
  */
3783
3984
  constructor(opts) {
3784
3985
  super();
@@ -3786,7 +3987,6 @@ class Transport extends Emitter_1 {
3786
3987
  installTimerFunctions(this, opts);
3787
3988
  this.opts = opts;
3788
3989
  this.query = opts.query;
3789
- this.readyState = "";
3790
3990
  this.socket = opts.socket;
3791
3991
  }
3792
3992
  /**
@@ -3796,7 +3996,7 @@ class Transport extends Emitter_1 {
3796
3996
  * @param description
3797
3997
  * @param context - the error context
3798
3998
  * @return {Transport} for chaining
3799
- * @api protected
3999
+ * @protected
3800
4000
  */
3801
4001
  onError(reason, description, context) {
3802
4002
  super.emitReserved("error", new TransportError(reason, description, context));
@@ -3804,23 +4004,17 @@ class Transport extends Emitter_1 {
3804
4004
  }
3805
4005
  /**
3806
4006
  * Opens the transport.
3807
- *
3808
- * @api public
3809
4007
  */
3810
4008
  open() {
3811
- if ("closed" === this.readyState || "" === this.readyState) {
3812
- this.readyState = "opening";
3813
- this.doOpen();
3814
- }
4009
+ this.readyState = "opening";
4010
+ this.doOpen();
3815
4011
  return this;
3816
4012
  }
3817
4013
  /**
3818
4014
  * Closes the transport.
3819
- *
3820
- * @api public
3821
4015
  */
3822
4016
  close() {
3823
- if ("opening" === this.readyState || "open" === this.readyState) {
4017
+ if (this.readyState === "opening" || this.readyState === "open") {
3824
4018
  this.doClose();
3825
4019
  this.onClose();
3826
4020
  }
@@ -3830,17 +4024,16 @@ class Transport extends Emitter_1 {
3830
4024
  * Sends multiple packets.
3831
4025
  *
3832
4026
  * @param {Array} packets
3833
- * @api public
3834
4027
  */
3835
4028
  send(packets) {
3836
- if ("open" === this.readyState) {
4029
+ if (this.readyState === "open") {
3837
4030
  this.write(packets);
3838
4031
  }
3839
4032
  }
3840
4033
  /**
3841
4034
  * Called upon open
3842
4035
  *
3843
- * @api protected
4036
+ * @protected
3844
4037
  */
3845
4038
  onOpen() {
3846
4039
  this.readyState = "open";
@@ -3851,7 +4044,7 @@ class Transport extends Emitter_1 {
3851
4044
  * Called with data.
3852
4045
  *
3853
4046
  * @param {String} data
3854
- * @api protected
4047
+ * @protected
3855
4048
  */
3856
4049
  onData(data) {
3857
4050
  const packet = decodePacket(data, this.socket.binaryType);
@@ -3860,7 +4053,7 @@ class Transport extends Emitter_1 {
3860
4053
  /**
3861
4054
  * Called with a decoded packet.
3862
4055
  *
3863
- * @api protected
4056
+ * @protected
3864
4057
  */
3865
4058
  onPacket(packet) {
3866
4059
  super.emitReserved("packet", packet);
@@ -3868,12 +4061,44 @@ class Transport extends Emitter_1 {
3868
4061
  /**
3869
4062
  * Called upon close.
3870
4063
  *
3871
- * @api protected
4064
+ * @protected
3872
4065
  */
3873
4066
  onClose(details) {
3874
4067
  this.readyState = "closed";
3875
4068
  super.emitReserved("close", details);
3876
4069
  }
4070
+ /**
4071
+ * Pauses the transport, in order not to lose packets during an upgrade.
4072
+ *
4073
+ * @param onPause
4074
+ */
4075
+ pause(onPause) { }
4076
+ createUri(schema, query = {}) {
4077
+ return (schema +
4078
+ "://" +
4079
+ this._hostname() +
4080
+ this._port() +
4081
+ this.opts.path +
4082
+ this._query(query));
4083
+ }
4084
+ _hostname() {
4085
+ const hostname = this.opts.hostname;
4086
+ return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
4087
+ }
4088
+ _port() {
4089
+ if (this.opts.port &&
4090
+ ((this.opts.secure && Number(this.opts.port !== 443)) ||
4091
+ (!this.opts.secure && Number(this.opts.port) !== 80))) {
4092
+ return ":" + this.opts.port;
4093
+ }
4094
+ else {
4095
+ return "";
4096
+ }
4097
+ }
4098
+ _query(query) {
4099
+ const encodedQuery = encode$1(query);
4100
+ return encodedQuery.length ? "?" + encodedQuery : "";
4101
+ }
3877
4102
  }
3878
4103
 
3879
4104
  // imported from https://github.com/unshiftio/yeast
@@ -3886,7 +4111,7 @@ let seed = 0, i = 0, prev;
3886
4111
  * @returns {String} The string representation of the number.
3887
4112
  * @api public
3888
4113
  */
3889
- function encode$1(num) {
4114
+ function encode(num) {
3890
4115
  let encoded = '';
3891
4116
  do {
3892
4117
  encoded = alphabet[num % length] + encoded;
@@ -3901,10 +4126,10 @@ function encode$1(num) {
3901
4126
  * @api public
3902
4127
  */
3903
4128
  function yeast() {
3904
- const now = encode$1(+new Date());
4129
+ const now = encode(+new Date());
3905
4130
  if (now !== prev)
3906
4131
  return seed = 0, prev = now;
3907
- return now + '.' + encode$1(seed++);
4132
+ return now + '.' + encode(seed++);
3908
4133
  }
3909
4134
  //
3910
4135
  // Map each character to its index.
@@ -3912,41 +4137,6 @@ function yeast() {
3912
4137
  for (; i < length; i++)
3913
4138
  map[alphabet[i]] = i;
3914
4139
 
3915
- // imported from https://github.com/galkn/querystring
3916
- /**
3917
- * Compiles a querystring
3918
- * Returns string representation of the object
3919
- *
3920
- * @param {Object}
3921
- * @api private
3922
- */
3923
- function encode(obj) {
3924
- let str = '';
3925
- for (let i in obj) {
3926
- if (obj.hasOwnProperty(i)) {
3927
- if (str.length)
3928
- str += '&';
3929
- str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
3930
- }
3931
- }
3932
- return str;
3933
- }
3934
- /**
3935
- * Parses a simple querystring into an object
3936
- *
3937
- * @param {String} qs
3938
- * @api private
3939
- */
3940
- function decode(qs) {
3941
- let qry = {};
3942
- let pairs = qs.split('&');
3943
- for (let i = 0, l = pairs.length; i < l; i++) {
3944
- let pair = pairs[i].split('=');
3945
- qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
3946
- }
3947
- return qry;
3948
- }
3949
-
3950
4140
  // imported from https://github.com/component/has-cors
3951
4141
  let value = false;
3952
4142
  try {
@@ -3976,11 +4166,12 @@ function XHR(opts) {
3976
4166
  catch (e) { }
3977
4167
  }
3978
4168
  }
4169
+ function createCookieJar() { }
3979
4170
 
3980
4171
  function empty$2() { }
3981
4172
  const hasXHR2 = (function () {
3982
4173
  const xhr = new XHR({
3983
- xdomain: false
4174
+ xdomain: false,
3984
4175
  });
3985
4176
  return null != xhr.responseType;
3986
4177
  })();
@@ -3989,7 +4180,7 @@ class Polling extends Transport {
3989
4180
  * XHR Polling constructor.
3990
4181
  *
3991
4182
  * @param {Object} opts
3992
- * @api public
4183
+ * @package
3993
4184
  */
3994
4185
  constructor(opts) {
3995
4186
  super(opts);
@@ -4005,17 +4196,16 @@ class Polling extends Transport {
4005
4196
  (typeof location !== "undefined" &&
4006
4197
  opts.hostname !== location.hostname) ||
4007
4198
  port !== opts.port;
4008
- this.xs = opts.secure !== isSSL;
4009
4199
  }
4010
4200
  /**
4011
4201
  * XHR supports binary
4012
4202
  */
4013
4203
  const forceBase64 = opts && opts.forceBase64;
4014
4204
  this.supportsBinary = hasXHR2 && !forceBase64;
4205
+ if (this.opts.withCredentials) {
4206
+ this.cookieJar = createCookieJar();
4207
+ }
4015
4208
  }
4016
- /**
4017
- * Transport name.
4018
- */
4019
4209
  get name() {
4020
4210
  return "polling";
4021
4211
  }
@@ -4023,7 +4213,7 @@ class Polling extends Transport {
4023
4213
  * Opens the socket (triggers polling). We write a PING message to determine
4024
4214
  * when the transport is open.
4025
4215
  *
4026
- * @api private
4216
+ * @protected
4027
4217
  */
4028
4218
  doOpen() {
4029
4219
  this.poll();
@@ -4031,8 +4221,8 @@ class Polling extends Transport {
4031
4221
  /**
4032
4222
  * Pauses polling.
4033
4223
  *
4034
- * @param {Function} callback upon buffers are flushed and transport is paused
4035
- * @api private
4224
+ * @param {Function} onPause - callback upon buffers are flushed and transport is paused
4225
+ * @package
4036
4226
  */
4037
4227
  pause(onPause) {
4038
4228
  this.readyState = "pausing";
@@ -4062,7 +4252,7 @@ class Polling extends Transport {
4062
4252
  /**
4063
4253
  * Starts polling cycle.
4064
4254
  *
4065
- * @api public
4255
+ * @private
4066
4256
  */
4067
4257
  poll() {
4068
4258
  this.polling = true;
@@ -4072,10 +4262,10 @@ class Polling extends Transport {
4072
4262
  /**
4073
4263
  * Overloads onData to detect payloads.
4074
4264
  *
4075
- * @api private
4265
+ * @protected
4076
4266
  */
4077
4267
  onData(data) {
4078
- const callback = packet => {
4268
+ const callback = (packet) => {
4079
4269
  // if its the first message we consider the transport open
4080
4270
  if ("opening" === this.readyState && packet.type === "open") {
4081
4271
  this.onOpen();
@@ -4103,7 +4293,7 @@ class Polling extends Transport {
4103
4293
  /**
4104
4294
  * For polling, send a close packet.
4105
4295
  *
4106
- * @api private
4296
+ * @protected
4107
4297
  */
4108
4298
  doClose() {
4109
4299
  const close = () => {
@@ -4121,13 +4311,12 @@ class Polling extends Transport {
4121
4311
  /**
4122
4312
  * Writes a packets payload.
4123
4313
  *
4124
- * @param {Array} data packets
4125
- * @param {Function} drain callback
4126
- * @api private
4314
+ * @param {Array} packets - data packets
4315
+ * @protected
4127
4316
  */
4128
4317
  write(packets) {
4129
4318
  this.writable = false;
4130
- encodePayload(packets, data => {
4319
+ encodePayload(packets, (data) => {
4131
4320
  this.doWrite(data, () => {
4132
4321
  this.writable = true;
4133
4322
  this.emitReserved("drain");
@@ -4137,12 +4326,11 @@ class Polling extends Transport {
4137
4326
  /**
4138
4327
  * Generates uri for connection.
4139
4328
  *
4140
- * @api private
4329
+ * @private
4141
4330
  */
4142
4331
  uri() {
4143
- let query = this.query || {};
4144
4332
  const schema = this.opts.secure ? "https" : "http";
4145
- let port = "";
4333
+ const query = this.query || {};
4146
4334
  // cache busting is forced
4147
4335
  if (false !== this.opts.timestampRequests) {
4148
4336
  query[this.opts.timestampParam] = yeast();
@@ -4150,29 +4338,16 @@ class Polling extends Transport {
4150
4338
  if (!this.supportsBinary && !query.sid) {
4151
4339
  query.b64 = 1;
4152
4340
  }
4153
- // avoid port if default for schema
4154
- if (this.opts.port &&
4155
- (("https" === schema && Number(this.opts.port) !== 443) ||
4156
- ("http" === schema && Number(this.opts.port) !== 80))) {
4157
- port = ":" + this.opts.port;
4158
- }
4159
- const encodedQuery = encode(query);
4160
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4161
- return (schema +
4162
- "://" +
4163
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4164
- port +
4165
- this.opts.path +
4166
- (encodedQuery.length ? "?" + encodedQuery : ""));
4341
+ return this.createUri(schema, query);
4167
4342
  }
4168
4343
  /**
4169
4344
  * Creates a request.
4170
4345
  *
4171
4346
  * @param {String} method
4172
- * @api private
4347
+ * @private
4173
4348
  */
4174
4349
  request(opts = {}) {
4175
- Object.assign(opts, { xd: this.xd, xs: this.xs }, this.opts);
4350
+ Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4176
4351
  return new Request(this.uri(), opts);
4177
4352
  }
4178
4353
  /**
@@ -4180,12 +4355,12 @@ class Polling extends Transport {
4180
4355
  *
4181
4356
  * @param {String} data to send.
4182
4357
  * @param {Function} called upon flush.
4183
- * @api private
4358
+ * @private
4184
4359
  */
4185
4360
  doWrite(data, fn) {
4186
4361
  const req = this.request({
4187
4362
  method: "POST",
4188
- data: data
4363
+ data: data,
4189
4364
  });
4190
4365
  req.on("success", fn);
4191
4366
  req.on("error", (xhrStatus, context) => {
@@ -4195,7 +4370,7 @@ class Polling extends Transport {
4195
4370
  /**
4196
4371
  * Starts a poll cycle.
4197
4372
  *
4198
- * @api private
4373
+ * @private
4199
4374
  */
4200
4375
  doPoll() {
4201
4376
  const req = this.request();
@@ -4211,7 +4386,7 @@ class Request extends Emitter_1 {
4211
4386
  * Request constructor
4212
4387
  *
4213
4388
  * @param {Object} options
4214
- * @api public
4389
+ * @package
4215
4390
  */
4216
4391
  constructor(uri, opts) {
4217
4392
  super();
@@ -4219,22 +4394,21 @@ class Request extends Emitter_1 {
4219
4394
  this.opts = opts;
4220
4395
  this.method = opts.method || "GET";
4221
4396
  this.uri = uri;
4222
- this.async = false !== opts.async;
4223
4397
  this.data = undefined !== opts.data ? opts.data : null;
4224
4398
  this.create();
4225
4399
  }
4226
4400
  /**
4227
4401
  * Creates the XHR object and sends the request.
4228
4402
  *
4229
- * @api private
4403
+ * @private
4230
4404
  */
4231
4405
  create() {
4406
+ var _a;
4232
4407
  const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4233
4408
  opts.xdomain = !!this.opts.xd;
4234
- opts.xscheme = !!this.opts.xs;
4235
4409
  const xhr = (this.xhr = new XHR(opts));
4236
4410
  try {
4237
- xhr.open(this.method, this.uri, this.async);
4411
+ xhr.open(this.method, this.uri, true);
4238
4412
  try {
4239
4413
  if (this.opts.extraHeaders) {
4240
4414
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
@@ -4256,6 +4430,7 @@ class Request extends Emitter_1 {
4256
4430
  xhr.setRequestHeader("Accept", "*/*");
4257
4431
  }
4258
4432
  catch (e) { }
4433
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4259
4434
  // ie6 check
4260
4435
  if ("withCredentials" in xhr) {
4261
4436
  xhr.withCredentials = this.opts.withCredentials;
@@ -4264,6 +4439,10 @@ class Request extends Emitter_1 {
4264
4439
  xhr.timeout = this.opts.requestTimeout;
4265
4440
  }
4266
4441
  xhr.onreadystatechange = () => {
4442
+ var _a;
4443
+ if (xhr.readyState === 3) {
4444
+ (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4445
+ }
4267
4446
  if (4 !== xhr.readyState)
4268
4447
  return;
4269
4448
  if (200 === xhr.status || 1223 === xhr.status) {
@@ -4296,7 +4475,7 @@ class Request extends Emitter_1 {
4296
4475
  /**
4297
4476
  * Called upon error.
4298
4477
  *
4299
- * @api private
4478
+ * @private
4300
4479
  */
4301
4480
  onError(err) {
4302
4481
  this.emitReserved("error", err, this.xhr);
@@ -4305,7 +4484,7 @@ class Request extends Emitter_1 {
4305
4484
  /**
4306
4485
  * Cleans up house.
4307
4486
  *
4308
- * @api private
4487
+ * @private
4309
4488
  */
4310
4489
  cleanup(fromError) {
4311
4490
  if ("undefined" === typeof this.xhr || null === this.xhr) {
@@ -4326,7 +4505,7 @@ class Request extends Emitter_1 {
4326
4505
  /**
4327
4506
  * Called upon load.
4328
4507
  *
4329
- * @api private
4508
+ * @private
4330
4509
  */
4331
4510
  onLoad() {
4332
4511
  const data = this.xhr.responseText;
@@ -4339,7 +4518,7 @@ class Request extends Emitter_1 {
4339
4518
  /**
4340
4519
  * Aborts the request.
4341
4520
  *
4342
- * @api public
4521
+ * @package
4343
4522
  */
4344
4523
  abort() {
4345
4524
  this.cleanup();
@@ -4374,7 +4553,7 @@ function unloadHandler() {
4374
4553
  const nextTick = (() => {
4375
4554
  const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4376
4555
  if (isPromiseAvailable) {
4377
- return cb => Promise.resolve().then(cb);
4556
+ return (cb) => Promise.resolve().then(cb);
4378
4557
  }
4379
4558
  else {
4380
4559
  return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
@@ -4392,26 +4571,16 @@ class WS extends Transport {
4392
4571
  /**
4393
4572
  * WebSocket transport constructor.
4394
4573
  *
4395
- * @api {Object} connection options
4396
- * @api public
4574
+ * @param {Object} opts - connection options
4575
+ * @protected
4397
4576
  */
4398
4577
  constructor(opts) {
4399
4578
  super(opts);
4400
4579
  this.supportsBinary = !opts.forceBase64;
4401
4580
  }
4402
- /**
4403
- * Transport name.
4404
- *
4405
- * @api public
4406
- */
4407
4581
  get name() {
4408
4582
  return "websocket";
4409
4583
  }
4410
- /**
4411
- * Opens socket.
4412
- *
4413
- * @api private
4414
- */
4415
4584
  doOpen() {
4416
4585
  if (!this.check()) {
4417
4586
  // let probe timeout
@@ -4437,13 +4606,13 @@ class WS extends Transport {
4437
4606
  catch (err) {
4438
4607
  return this.emitReserved("error", err);
4439
4608
  }
4440
- this.ws.binaryType = this.socket.binaryType || defaultBinaryType;
4609
+ this.ws.binaryType = this.socket.binaryType;
4441
4610
  this.addEventListeners();
4442
4611
  }
4443
4612
  /**
4444
4613
  * Adds event listeners to the socket
4445
4614
  *
4446
- * @api private
4615
+ * @private
4447
4616
  */
4448
4617
  addEventListeners() {
4449
4618
  this.ws.onopen = () => {
@@ -4452,19 +4621,13 @@ class WS extends Transport {
4452
4621
  }
4453
4622
  this.onOpen();
4454
4623
  };
4455
- this.ws.onclose = closeEvent => this.onClose({
4624
+ this.ws.onclose = (closeEvent) => this.onClose({
4456
4625
  description: "websocket connection closed",
4457
- context: closeEvent
4626
+ context: closeEvent,
4458
4627
  });
4459
- this.ws.onmessage = ev => this.onData(ev.data);
4460
- this.ws.onerror = e => this.onError("websocket error", e);
4628
+ this.ws.onmessage = (ev) => this.onData(ev.data);
4629
+ this.ws.onerror = (e) => this.onError("websocket error", e);
4461
4630
  }
4462
- /**
4463
- * Writes data to socket.
4464
- *
4465
- * @param {Array} array of packets.
4466
- * @api private
4467
- */
4468
4631
  write(packets) {
4469
4632
  this.writable = false;
4470
4633
  // encodePacket efficient as it uses WS framing
@@ -4472,7 +4635,7 @@ class WS extends Transport {
4472
4635
  for (let i = 0; i < packets.length; i++) {
4473
4636
  const packet = packets[i];
4474
4637
  const lastPacket = i === packets.length - 1;
4475
- encodePacket(packet, this.supportsBinary, data => {
4638
+ encodePacket(packet, this.supportsBinary, (data) => {
4476
4639
  // always create a new object (GH-437)
4477
4640
  const opts = {};
4478
4641
  // Sometimes the websocket has already been closed but the browser didn't
@@ -4497,11 +4660,6 @@ class WS extends Transport {
4497
4660
  });
4498
4661
  }
4499
4662
  }
4500
- /**
4501
- * Closes socket.
4502
- *
4503
- * @api private
4504
- */
4505
4663
  doClose() {
4506
4664
  if (typeof this.ws !== "undefined") {
4507
4665
  this.ws.close();
@@ -4511,18 +4669,11 @@ class WS extends Transport {
4511
4669
  /**
4512
4670
  * Generates uri for connection.
4513
4671
  *
4514
- * @api private
4672
+ * @private
4515
4673
  */
4516
4674
  uri() {
4517
- let query = this.query || {};
4518
4675
  const schema = this.opts.secure ? "wss" : "ws";
4519
- let port = "";
4520
- // avoid port if default for schema
4521
- if (this.opts.port &&
4522
- (("wss" === schema && Number(this.opts.port) !== 443) ||
4523
- ("ws" === schema && Number(this.opts.port) !== 80))) {
4524
- port = ":" + this.opts.port;
4525
- }
4676
+ const query = this.query || {};
4526
4677
  // append timestamp to URI
4527
4678
  if (this.opts.timestampRequests) {
4528
4679
  query[this.opts.timestampParam] = yeast();
@@ -4531,43 +4682,121 @@ class WS extends Transport {
4531
4682
  if (!this.supportsBinary) {
4532
4683
  query.b64 = 1;
4533
4684
  }
4534
- const encodedQuery = encode(query);
4535
- const ipv6 = this.opts.hostname.indexOf(":") !== -1;
4536
- return (schema +
4537
- "://" +
4538
- (ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
4539
- port +
4540
- this.opts.path +
4541
- (encodedQuery.length ? "?" + encodedQuery : ""));
4685
+ return this.createUri(schema, query);
4542
4686
  }
4543
4687
  /**
4544
4688
  * Feature detection for WebSocket.
4545
4689
  *
4546
4690
  * @return {Boolean} whether this transport is available.
4547
- * @api public
4691
+ * @private
4548
4692
  */
4549
4693
  check() {
4550
4694
  return !!WebSocket$1;
4551
4695
  }
4552
4696
  }
4553
4697
 
4698
+ class WT extends Transport {
4699
+ get name() {
4700
+ return "webtransport";
4701
+ }
4702
+ doOpen() {
4703
+ // @ts-ignore
4704
+ if (typeof WebTransport !== "function") {
4705
+ return;
4706
+ }
4707
+ // @ts-ignore
4708
+ this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4709
+ this.transport.closed
4710
+ .then(() => {
4711
+ this.onClose();
4712
+ })
4713
+ .catch((err) => {
4714
+ this.onError("webtransport error", err);
4715
+ });
4716
+ // note: we could have used async/await, but that would require some additional polyfills
4717
+ this.transport.ready.then(() => {
4718
+ this.transport.createBidirectionalStream().then((stream) => {
4719
+ const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4720
+ const reader = stream.readable.pipeThrough(decoderStream).getReader();
4721
+ const encoderStream = createPacketEncoderStream();
4722
+ encoderStream.readable.pipeTo(stream.writable);
4723
+ this.writer = encoderStream.writable.getWriter();
4724
+ const read = () => {
4725
+ reader
4726
+ .read()
4727
+ .then(({ done, value }) => {
4728
+ if (done) {
4729
+ return;
4730
+ }
4731
+ this.onPacket(value);
4732
+ read();
4733
+ })
4734
+ .catch((err) => {
4735
+ });
4736
+ };
4737
+ read();
4738
+ const packet = { type: "open" };
4739
+ if (this.query.sid) {
4740
+ packet.data = `{"sid":"${this.query.sid}"}`;
4741
+ }
4742
+ this.writer.write(packet).then(() => this.onOpen());
4743
+ });
4744
+ });
4745
+ }
4746
+ write(packets) {
4747
+ this.writable = false;
4748
+ for (let i = 0; i < packets.length; i++) {
4749
+ const packet = packets[i];
4750
+ const lastPacket = i === packets.length - 1;
4751
+ this.writer.write(packet).then(() => {
4752
+ if (lastPacket) {
4753
+ nextTick(() => {
4754
+ this.writable = true;
4755
+ this.emitReserved("drain");
4756
+ }, this.setTimeoutFn);
4757
+ }
4758
+ });
4759
+ }
4760
+ }
4761
+ doClose() {
4762
+ var _a;
4763
+ (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4764
+ }
4765
+ }
4766
+
4554
4767
  const transports = {
4555
4768
  websocket: WS,
4556
- polling: Polling
4769
+ webtransport: WT,
4770
+ polling: Polling,
4557
4771
  };
4558
4772
 
4559
4773
  // imported from https://github.com/galkn/parseuri
4560
4774
  /**
4561
- * Parses an URI
4775
+ * Parses a URI
4776
+ *
4777
+ * Note: we could also have used the built-in URL object, but it isn't supported on all platforms.
4778
+ *
4779
+ * See:
4780
+ * - https://developer.mozilla.org/en-US/docs/Web/API/URL
4781
+ * - https://caniuse.com/url
4782
+ * - https://www.rfc-editor.org/rfc/rfc3986#appendix-B
4783
+ *
4784
+ * History of the parse() method:
4785
+ * - first commit: https://github.com/socketio/socket.io-client/commit/4ee1d5d94b3906a9c052b459f1a818b15f38f91c
4786
+ * - export into its own module: https://github.com/socketio/engine.io-client/commit/de2c561e4564efeb78f1bdb1ba39ef81b2822cb3
4787
+ * - reimport: https://github.com/socketio/engine.io-client/commit/df32277c3f6d622eec5ed09f493cae3f3391d242
4562
4788
  *
4563
4789
  * @author Steven Levithan <stevenlevithan.com> (MIT license)
4564
4790
  * @api private
4565
4791
  */
4566
- const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4792
+ const re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
4567
4793
  const parts = [
4568
4794
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4569
4795
  ];
4570
4796
  function parse$2(str) {
4797
+ if (str.length > 2000) {
4798
+ throw "URI too long";
4799
+ }
4571
4800
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
4572
4801
  if (b != -1 && e != -1) {
4573
4802
  str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
@@ -4610,12 +4839,13 @@ class Socket$1 extends Emitter_1 {
4610
4839
  /**
4611
4840
  * Socket constructor.
4612
4841
  *
4613
- * @param {String|Object} uri or options
4842
+ * @param {String|Object} uri - uri or options
4614
4843
  * @param {Object} opts - options
4615
- * @api public
4616
4844
  */
4617
4845
  constructor(uri, opts = {}) {
4618
4846
  super();
4847
+ this.binaryType = defaultBinaryType;
4848
+ this.writeBuffer = [];
4619
4849
  if (uri && "object" === typeof uri) {
4620
4850
  opts = uri;
4621
4851
  uri = null;
@@ -4650,8 +4880,11 @@ class Socket$1 extends Emitter_1 {
4650
4880
  : this.secure
4651
4881
  ? "443"
4652
4882
  : "80");
4653
- this.transports = opts.transports || ["polling", "websocket"];
4654
- this.readyState = "";
4883
+ this.transports = opts.transports || [
4884
+ "polling",
4885
+ "websocket",
4886
+ "webtransport",
4887
+ ];
4655
4888
  this.writeBuffer = [];
4656
4889
  this.prevBufferLen = 0;
4657
4890
  this.opts = Object.assign({
@@ -4661,14 +4894,17 @@ class Socket$1 extends Emitter_1 {
4661
4894
  upgrade: true,
4662
4895
  timestampParam: "t",
4663
4896
  rememberUpgrade: false,
4897
+ addTrailingSlash: true,
4664
4898
  rejectUnauthorized: true,
4665
4899
  perMessageDeflate: {
4666
- threshold: 1024
4900
+ threshold: 1024,
4667
4901
  },
4668
4902
  transportOptions: {},
4669
- closeOnBeforeunload: true
4903
+ closeOnBeforeunload: false,
4670
4904
  }, opts);
4671
- this.opts.path = this.opts.path.replace(/\/$/, "") + "/";
4905
+ this.opts.path =
4906
+ this.opts.path.replace(/\/$/, "") +
4907
+ (this.opts.addTrailingSlash ? "/" : "");
4672
4908
  if (typeof this.opts.query === "string") {
4673
4909
  this.opts.query = decode(this.opts.query);
4674
4910
  }
@@ -4696,7 +4932,7 @@ class Socket$1 extends Emitter_1 {
4696
4932
  if (this.hostname !== "localhost") {
4697
4933
  this.offlineEventListener = () => {
4698
4934
  this.onClose("transport close", {
4699
- description: "network connection lost"
4935
+ description: "network connection lost",
4700
4936
  });
4701
4937
  };
4702
4938
  addEventListener("offline", this.offlineEventListener, false);
@@ -4707,9 +4943,9 @@ class Socket$1 extends Emitter_1 {
4707
4943
  /**
4708
4944
  * Creates transport of the given type.
4709
4945
  *
4710
- * @param {String} transport name
4946
+ * @param {String} name - transport name
4711
4947
  * @return {Transport}
4712
- * @api private
4948
+ * @private
4713
4949
  */
4714
4950
  createTransport(name) {
4715
4951
  const query = Object.assign({}, this.opts.query);
@@ -4720,19 +4956,19 @@ class Socket$1 extends Emitter_1 {
4720
4956
  // session id if we already have one
4721
4957
  if (this.id)
4722
4958
  query.sid = this.id;
4723
- const opts = Object.assign({}, this.opts.transportOptions[name], this.opts, {
4959
+ const opts = Object.assign({}, this.opts, {
4724
4960
  query,
4725
4961
  socket: this,
4726
4962
  hostname: this.hostname,
4727
4963
  secure: this.secure,
4728
- port: this.port
4729
- });
4964
+ port: this.port,
4965
+ }, this.opts.transportOptions[name]);
4730
4966
  return new transports[name](opts);
4731
4967
  }
4732
4968
  /**
4733
4969
  * Initializes transport to use and starts probe.
4734
4970
  *
4735
- * @api private
4971
+ * @private
4736
4972
  */
4737
4973
  open() {
4738
4974
  let transport;
@@ -4767,7 +5003,7 @@ class Socket$1 extends Emitter_1 {
4767
5003
  /**
4768
5004
  * Sets the current transport. Disables the existing one (if any).
4769
5005
  *
4770
- * @api private
5006
+ * @private
4771
5007
  */
4772
5008
  setTransport(transport) {
4773
5009
  if (this.transport) {
@@ -4780,13 +5016,13 @@ class Socket$1 extends Emitter_1 {
4780
5016
  .on("drain", this.onDrain.bind(this))
4781
5017
  .on("packet", this.onPacket.bind(this))
4782
5018
  .on("error", this.onError.bind(this))
4783
- .on("close", reason => this.onClose("transport close", reason));
5019
+ .on("close", (reason) => this.onClose("transport close", reason));
4784
5020
  }
4785
5021
  /**
4786
5022
  * Probes a transport.
4787
5023
  *
4788
- * @param {String} transport name
4789
- * @api private
5024
+ * @param {String} name - transport name
5025
+ * @private
4790
5026
  */
4791
5027
  probe(name) {
4792
5028
  let transport = this.createTransport(name);
@@ -4796,7 +5032,7 @@ class Socket$1 extends Emitter_1 {
4796
5032
  if (failed)
4797
5033
  return;
4798
5034
  transport.send([{ type: "ping", data: "probe" }]);
4799
- transport.once("packet", msg => {
5035
+ transport.once("packet", (msg) => {
4800
5036
  if (failed)
4801
5037
  return;
4802
5038
  if ("pong" === msg.type && "probe" === msg.data) {
@@ -4837,7 +5073,7 @@ class Socket$1 extends Emitter_1 {
4837
5073
  transport = null;
4838
5074
  }
4839
5075
  // Handle any error that happens while probing
4840
- const onerror = err => {
5076
+ const onerror = (err) => {
4841
5077
  const error = new Error("probe error: " + err);
4842
5078
  // @ts-ignore
4843
5079
  error.transport = transport.name;
@@ -4870,12 +5106,23 @@ class Socket$1 extends Emitter_1 {
4870
5106
  transport.once("close", onTransportClose);
4871
5107
  this.once("close", onclose);
4872
5108
  this.once("upgrading", onupgrade);
4873
- transport.open();
5109
+ if (this.upgrades.indexOf("webtransport") !== -1 &&
5110
+ name !== "webtransport") {
5111
+ // favor WebTransport
5112
+ this.setTimeoutFn(() => {
5113
+ if (!failed) {
5114
+ transport.open();
5115
+ }
5116
+ }, 200);
5117
+ }
5118
+ else {
5119
+ transport.open();
5120
+ }
4874
5121
  }
4875
5122
  /**
4876
5123
  * Called when connection is deemed open.
4877
5124
  *
4878
- * @api private
5125
+ * @private
4879
5126
  */
4880
5127
  onOpen() {
4881
5128
  this.readyState = "open";
@@ -4884,9 +5131,7 @@ class Socket$1 extends Emitter_1 {
4884
5131
  this.flush();
4885
5132
  // we check for `readyState` in case an `open`
4886
5133
  // listener already closed the socket
4887
- if ("open" === this.readyState &&
4888
- this.opts.upgrade &&
4889
- this.transport.pause) {
5134
+ if ("open" === this.readyState && this.opts.upgrade) {
4890
5135
  let i = 0;
4891
5136
  const l = this.upgrades.length;
4892
5137
  for (; i < l; i++) {
@@ -4897,7 +5142,7 @@ class Socket$1 extends Emitter_1 {
4897
5142
  /**
4898
5143
  * Handles a packet.
4899
5144
  *
4900
- * @api private
5145
+ * @private
4901
5146
  */
4902
5147
  onPacket(packet) {
4903
5148
  if ("opening" === this.readyState ||
@@ -4906,12 +5151,12 @@ class Socket$1 extends Emitter_1 {
4906
5151
  this.emitReserved("packet", packet);
4907
5152
  // Socket is live - any packet counts
4908
5153
  this.emitReserved("heartbeat");
5154
+ this.resetPingTimeout();
4909
5155
  switch (packet.type) {
4910
5156
  case "open":
4911
5157
  this.onHandshake(JSON.parse(packet.data));
4912
5158
  break;
4913
5159
  case "ping":
4914
- this.resetPingTimeout();
4915
5160
  this.sendPacket("pong");
4916
5161
  this.emitReserved("ping");
4917
5162
  this.emitReserved("pong");
@@ -4933,7 +5178,7 @@ class Socket$1 extends Emitter_1 {
4933
5178
  * Called upon handshake completion.
4934
5179
  *
4935
5180
  * @param {Object} data - handshake obj
4936
- * @api private
5181
+ * @private
4937
5182
  */
4938
5183
  onHandshake(data) {
4939
5184
  this.emitReserved("handshake", data);
@@ -4952,7 +5197,7 @@ class Socket$1 extends Emitter_1 {
4952
5197
  /**
4953
5198
  * Sets and resets ping timeout timer based on server pings.
4954
5199
  *
4955
- * @api private
5200
+ * @private
4956
5201
  */
4957
5202
  resetPingTimeout() {
4958
5203
  this.clearTimeoutFn(this.pingTimeoutTimer);
@@ -4966,7 +5211,7 @@ class Socket$1 extends Emitter_1 {
4966
5211
  /**
4967
5212
  * Called on `drain` event
4968
5213
  *
4969
- * @api private
5214
+ * @private
4970
5215
  */
4971
5216
  onDrain() {
4972
5217
  this.writeBuffer.splice(0, this.prevBufferLen);
@@ -4984,7 +5229,7 @@ class Socket$1 extends Emitter_1 {
4984
5229
  /**
4985
5230
  * Flush write buffers.
4986
5231
  *
4987
- * @api private
5232
+ * @private
4988
5233
  */
4989
5234
  flush() {
4990
5235
  if ("closed" !== this.readyState &&
@@ -5028,11 +5273,10 @@ class Socket$1 extends Emitter_1 {
5028
5273
  /**
5029
5274
  * Sends a message.
5030
5275
  *
5031
- * @param {String} message.
5032
- * @param {Function} callback function.
5276
+ * @param {String} msg - message.
5033
5277
  * @param {Object} options.
5278
+ * @param {Function} callback function.
5034
5279
  * @return {Socket} for chaining.
5035
- * @api public
5036
5280
  */
5037
5281
  write(msg, options, fn) {
5038
5282
  this.sendPacket("message", msg, options, fn);
@@ -5045,11 +5289,11 @@ class Socket$1 extends Emitter_1 {
5045
5289
  /**
5046
5290
  * Sends a packet.
5047
5291
  *
5048
- * @param {String} packet type.
5292
+ * @param {String} type: packet type.
5049
5293
  * @param {String} data.
5050
5294
  * @param {Object} options.
5051
- * @param {Function} callback function.
5052
- * @api private
5295
+ * @param {Function} fn - callback function.
5296
+ * @private
5053
5297
  */
5054
5298
  sendPacket(type, data, options, fn) {
5055
5299
  if ("function" === typeof data) {
@@ -5068,7 +5312,7 @@ class Socket$1 extends Emitter_1 {
5068
5312
  const packet = {
5069
5313
  type: type,
5070
5314
  data: data,
5071
- options: options
5315
+ options: options,
5072
5316
  };
5073
5317
  this.emitReserved("packetCreate", packet);
5074
5318
  this.writeBuffer.push(packet);
@@ -5078,8 +5322,6 @@ class Socket$1 extends Emitter_1 {
5078
5322
  }
5079
5323
  /**
5080
5324
  * Closes the connection.
5081
- *
5082
- * @api public
5083
5325
  */
5084
5326
  close() {
5085
5327
  const close = () => {
@@ -5120,7 +5362,7 @@ class Socket$1 extends Emitter_1 {
5120
5362
  /**
5121
5363
  * Called upon transport error
5122
5364
  *
5123
- * @api private
5365
+ * @private
5124
5366
  */
5125
5367
  onError(err) {
5126
5368
  Socket$1.priorWebsocketSuccess = false;
@@ -5130,7 +5372,7 @@ class Socket$1 extends Emitter_1 {
5130
5372
  /**
5131
5373
  * Called upon transport close.
5132
5374
  *
5133
- * @api private
5375
+ * @private
5134
5376
  */
5135
5377
  onClose(reason, description) {
5136
5378
  if ("opening" === this.readyState ||
@@ -5163,9 +5405,8 @@ class Socket$1 extends Emitter_1 {
5163
5405
  /**
5164
5406
  * Filters upgrades, returning only those matching client transports.
5165
5407
  *
5166
- * @param {Array} server upgrades
5167
- * @api private
5168
- *
5408
+ * @param {Array} upgrades - server upgrades
5409
+ * @private
5169
5410
  */
5170
5411
  filterUpgrades(upgrades) {
5171
5412
  const filteredUpgrades = [];
@@ -5375,6 +5616,17 @@ function _reconstructPacket(data, buffers) {
5375
5616
  return data;
5376
5617
  }
5377
5618
 
5619
+ /**
5620
+ * These strings must not be used as event names, as they have a special meaning.
5621
+ */
5622
+ const RESERVED_EVENTS$1 = [
5623
+ "connect",
5624
+ "connect_error",
5625
+ "disconnect",
5626
+ "disconnecting",
5627
+ "newListener",
5628
+ "removeListener", // used by the Node.js EventEmitter
5629
+ ];
5378
5630
  /**
5379
5631
  * Protocol version.
5380
5632
  *
@@ -5463,6 +5715,10 @@ class Encoder {
5463
5715
  return buffers; // write all the buffers
5464
5716
  }
5465
5717
  }
5718
+ // see https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
5719
+ function isObject(value) {
5720
+ return Object.prototype.toString.call(value) === "[object Object]";
5721
+ }
5466
5722
  /**
5467
5723
  * A socket.io Decoder instance
5468
5724
  *
@@ -5602,14 +5858,17 @@ class Decoder extends Emitter_1 {
5602
5858
  static isPayloadValid(type, payload) {
5603
5859
  switch (type) {
5604
5860
  case PacketType.CONNECT:
5605
- return typeof payload === "object";
5861
+ return isObject(payload);
5606
5862
  case PacketType.DISCONNECT:
5607
5863
  return payload === undefined;
5608
5864
  case PacketType.CONNECT_ERROR:
5609
- return typeof payload === "string" || typeof payload === "object";
5865
+ return typeof payload === "string" || isObject(payload);
5610
5866
  case PacketType.EVENT:
5611
5867
  case PacketType.BINARY_EVENT:
5612
- return Array.isArray(payload) && payload.length > 0;
5868
+ return (Array.isArray(payload) &&
5869
+ (typeof payload[0] === "number" ||
5870
+ (typeof payload[0] === "string" &&
5871
+ RESERVED_EVENTS$1.indexOf(payload[0]) === -1)));
5613
5872
  case PacketType.ACK:
5614
5873
  case PacketType.BINARY_ACK:
5615
5874
  return Array.isArray(payload);
@@ -5694,18 +5953,100 @@ const RESERVED_EVENTS = Object.freeze({
5694
5953
  newListener: 1,
5695
5954
  removeListener: 1,
5696
5955
  });
5956
+ /**
5957
+ * A Socket is the fundamental class for interacting with the server.
5958
+ *
5959
+ * A Socket belongs to a certain Namespace (by default /) and uses an underlying {@link Manager} to communicate.
5960
+ *
5961
+ * @example
5962
+ * const socket = io();
5963
+ *
5964
+ * socket.on("connect", () => {
5965
+ * console.log("connected");
5966
+ * });
5967
+ *
5968
+ * // send an event to the server
5969
+ * socket.emit("foo", "bar");
5970
+ *
5971
+ * socket.on("foobar", () => {
5972
+ * // an event was received from the server
5973
+ * });
5974
+ *
5975
+ * // upon disconnection
5976
+ * socket.on("disconnect", (reason) => {
5977
+ * console.log(`disconnected due to ${reason}`);
5978
+ * });
5979
+ */
5697
5980
  class Socket extends Emitter_1 {
5698
5981
  /**
5699
5982
  * `Socket` constructor.
5700
- *
5701
- * @public
5702
5983
  */
5703
5984
  constructor(io, nsp, opts) {
5704
5985
  super();
5986
+ /**
5987
+ * Whether the socket is currently connected to the server.
5988
+ *
5989
+ * @example
5990
+ * const socket = io();
5991
+ *
5992
+ * socket.on("connect", () => {
5993
+ * console.log(socket.connected); // true
5994
+ * });
5995
+ *
5996
+ * socket.on("disconnect", () => {
5997
+ * console.log(socket.connected); // false
5998
+ * });
5999
+ */
5705
6000
  this.connected = false;
6001
+ /**
6002
+ * Whether the connection state was recovered after a temporary disconnection. In that case, any missed packets will
6003
+ * be transmitted by the server.
6004
+ */
6005
+ this.recovered = false;
6006
+ /**
6007
+ * Buffer for packets received before the CONNECT packet
6008
+ */
5706
6009
  this.receiveBuffer = [];
6010
+ /**
6011
+ * Buffer for packets that will be sent once the socket is connected
6012
+ */
5707
6013
  this.sendBuffer = [];
6014
+ /**
6015
+ * The queue of packets to be sent with retry in case of failure.
6016
+ *
6017
+ * Packets are sent one by one, each waiting for the server acknowledgement, in order to guarantee the delivery order.
6018
+ * @private
6019
+ */
6020
+ this._queue = [];
6021
+ /**
6022
+ * A sequence to generate the ID of the {@link QueuedPacket}.
6023
+ * @private
6024
+ */
6025
+ this._queueSeq = 0;
5708
6026
  this.ids = 0;
6027
+ /**
6028
+ * A map containing acknowledgement handlers.
6029
+ *
6030
+ * The `withError` attribute is used to differentiate handlers that accept an error as first argument:
6031
+ *
6032
+ * - `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
6033
+ * - `socket.timeout(5000).emit("test", (err, value) => { ... })`
6034
+ * - `const value = await socket.emitWithAck("test")`
6035
+ *
6036
+ * From those that don't:
6037
+ *
6038
+ * - `socket.emit("test", (value) => { ... });`
6039
+ *
6040
+ * In the first case, the handlers will be called with an error when:
6041
+ *
6042
+ * - the timeout is reached
6043
+ * - the socket gets disconnected
6044
+ *
6045
+ * In the second case, the handlers will be simply discarded upon disconnection, since the client will never receive
6046
+ * an acknowledgement from the server.
6047
+ *
6048
+ * @private
6049
+ */
5709
6050
  this.acks = {};
5710
6051
  this.flags = {};
5711
6052
  this.io = io;
@@ -5713,11 +6054,23 @@ class Socket extends Emitter_1 {
5713
6054
  if (opts && opts.auth) {
5714
6055
  this.auth = opts.auth;
5715
6056
  }
6057
+ this._opts = Object.assign({}, opts);
5716
6058
  if (this.io._autoConnect)
5717
6059
  this.open();
5718
6060
  }
5719
6061
  /**
5720
6062
  * Whether the socket is currently disconnected
6063
+ *
6064
+ * @example
6065
+ * const socket = io();
6066
+ *
6067
+ * socket.on("connect", () => {
6068
+ * console.log(socket.disconnected); // false
6069
+ * });
6070
+ *
6071
+ * socket.on("disconnect", () => {
6072
+ * console.log(socket.disconnected); // true
6073
+ * });
5721
6074
  */
5722
6075
  get disconnected() {
5723
6076
  return !this.connected;
@@ -5739,7 +6092,21 @@ class Socket extends Emitter_1 {
5739
6092
  ];
5740
6093
  }
5741
6094
  /**
5742
- * Whether the Socket will try to reconnect when its Manager connects or reconnects
6095
+ * Whether the Socket will try to reconnect when its Manager connects or reconnects.
6096
+ *
6097
+ * @example
6098
+ * const socket = io();
6099
+ *
6100
+ * console.log(socket.active); // true
6101
+ *
6102
+ * socket.on("disconnect", (reason) => {
6103
+ * if (reason === "io server disconnect") {
6104
+ * // the disconnection was initiated by the server, you need to manually reconnect
6105
+ * console.log(socket.active); // false
6106
+ * }
6107
+ * // else the socket will automatically try to reconnect
6108
+ * console.log(socket.active); // true
6109
+ * });
5743
6110
  */
5744
6111
  get active() {
5745
6112
  return !!this.subs;
@@ -5747,7 +6114,12 @@ class Socket extends Emitter_1 {
5747
6114
  /**
5748
6115
  * "Opens" the socket.
5749
6116
  *
5750
- * @public
6117
+ * @example
6118
+ * const socket = io({
6119
+ * autoConnect: false
6120
+ * });
6121
+ *
6122
+ * socket.connect();
5751
6123
  */
5752
6124
  connect() {
5753
6125
  if (this.connected)
@@ -5760,7 +6132,7 @@ class Socket extends Emitter_1 {
5760
6132
  return this;
5761
6133
  }
5762
6134
  /**
5763
- * Alias for connect()
6135
+ * Alias for {@link connect()}.
5764
6136
  */
5765
6137
  open() {
5766
6138
  return this.connect();
@@ -5768,8 +6140,17 @@ class Socket extends Emitter_1 {
5768
6140
  /**
5769
6141
  * Sends a `message` event.
5770
6142
  *
6143
+ * This method mimics the WebSocket.send() method.
6144
+ *
6145
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
6146
+ *
6147
+ * @example
6148
+ * socket.send("hello");
6149
+ *
6150
+ * // this is equivalent to
6151
+ * socket.emit("message", "hello");
6152
+ *
5771
6153
  * @return self
5772
- * @public
5773
6154
  */
5774
6155
  send(...args) {
5775
6156
  args.unshift("message");
@@ -5780,14 +6161,28 @@ class Socket extends Emitter_1 {
5780
6161
  * Override `emit`.
5781
6162
  * If the event is in `events`, it's emitted normally.
5782
6163
  *
6164
+ * @example
6165
+ * socket.emit("hello", "world");
6166
+ *
6167
+ * // all serializable datastructures are supported (no need to call JSON.stringify)
6168
+ * socket.emit("hello", 1, "2", { 3: ["4"], 5: Uint8Array.from([6]) });
6169
+ *
6170
+ * // with an acknowledgement from the server
6171
+ * socket.emit("hello", "world", (val) => {
6172
+ * // ...
6173
+ * });
6174
+ *
5783
6175
  * @return self
5784
- * @public
5785
6176
  */
5786
6177
  emit(ev, ...args) {
5787
6178
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
5788
- throw new Error('"' + ev + '" is a reserved event name');
6179
+ throw new Error('"' + ev.toString() + '" is a reserved event name');
5789
6180
  }
5790
6181
  args.unshift(ev);
6182
+ if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {
6183
+ this._addToQueue(args);
6184
+ return this;
6185
+ }
5791
6186
  const packet = {
5792
6187
  type: PacketType.EVENT,
5793
6188
  data: args,
@@ -5820,7 +6215,8 @@ class Socket extends Emitter_1 {
5820
6215
  * @private
5821
6216
  */
5822
6217
  _registerAckCallback(id, ack) {
5823
- const timeout = this.flags.timeout;
6218
+ var _a;
6219
+ const timeout = (_a = this.flags.timeout) !== null && _a !== void 0 ? _a : this._opts.ackTimeout;
5824
6220
  if (timeout === undefined) {
5825
6221
  this.acks[id] = ack;
5826
6222
  return;
@@ -5835,11 +6231,101 @@ class Socket extends Emitter_1 {
5835
6231
  }
5836
6232
  ack.call(this, new Error("operation has timed out"));
5837
6233
  }, timeout);
5838
- this.acks[id] = (...args) => {
6234
+ const fn = (...args) => {
5839
6235
  // @ts-ignore
5840
6236
  this.io.clearTimeoutFn(timer);
5841
- ack.apply(this, [null, ...args]);
6237
+ ack.apply(this, args);
6238
+ };
6239
+ fn.withError = true;
6240
+ this.acks[id] = fn;
6241
+ }
6242
+ /**
6243
+ * Emits an event and waits for an acknowledgement
6244
+ *
6245
+ * @example
6246
+ * // without timeout
6247
+ * const response = await socket.emitWithAck("hello", "world");
6248
+ *
6249
+ * // with a specific timeout
6250
+ * try {
6251
+ * const response = await socket.timeout(1000).emitWithAck("hello", "world");
6252
+ * } catch (err) {
6253
+ * // the server did not acknowledge the event in the given delay
6254
+ * }
6255
+ *
6256
+ * @return a Promise that will be fulfilled when the server acknowledges the event
6257
+ */
6258
+ emitWithAck(ev, ...args) {
6259
+ return new Promise((resolve, reject) => {
6260
+ const fn = (arg1, arg2) => {
6261
+ return arg1 ? reject(arg1) : resolve(arg2);
6262
+ };
6263
+ fn.withError = true;
6264
+ args.push(fn);
6265
+ this.emit(ev, ...args);
6266
+ });
6267
+ }
6268
+ /**
6269
+ * Add the packet to the queue.
6270
+ * @param args
6271
+ * @private
6272
+ */
6273
+ _addToQueue(args) {
6274
+ let ack;
6275
+ if (typeof args[args.length - 1] === "function") {
6276
+ ack = args.pop();
6277
+ }
6278
+ const packet = {
6279
+ id: this._queueSeq++,
6280
+ tryCount: 0,
6281
+ pending: false,
6282
+ args,
6283
+ flags: Object.assign({ fromQueue: true }, this.flags),
5842
6284
  };
6285
+ args.push((err, ...responseArgs) => {
6286
+ if (packet !== this._queue[0]) {
6287
+ // the packet has already been acknowledged
6288
+ return;
6289
+ }
6290
+ const hasError = err !== null;
6291
+ if (hasError) {
6292
+ if (packet.tryCount > this._opts.retries) {
6293
+ this._queue.shift();
6294
+ if (ack) {
6295
+ ack(err);
6296
+ }
6297
+ }
6298
+ }
6299
+ else {
6300
+ this._queue.shift();
6301
+ if (ack) {
6302
+ ack(null, ...responseArgs);
6303
+ }
6304
+ }
6305
+ packet.pending = false;
6306
+ return this._drainQueue();
6307
+ });
6308
+ this._queue.push(packet);
6309
+ this._drainQueue();
6310
+ }
6311
+ /**
6312
+ * Send the first packet of the queue, and wait for an acknowledgement from the server.
6313
+ * @param force - whether to resend a packet that has not been acknowledged yet
6314
+ *
6315
+ * @private
6316
+ */
6317
+ _drainQueue(force = false) {
6318
+ if (!this.connected || this._queue.length === 0) {
6319
+ return;
6320
+ }
6321
+ const packet = this._queue[0];
6322
+ if (packet.pending && !force) {
6323
+ return;
6324
+ }
6325
+ packet.pending = true;
6326
+ packet.tryCount++;
6327
+ this.flags = packet.flags;
6328
+ this.emit.apply(this, packet.args);
5843
6329
  }
5844
6330
  /**
5845
6331
  * Sends a packet.
@@ -5859,13 +6345,27 @@ class Socket extends Emitter_1 {
5859
6345
  onopen() {
5860
6346
  if (typeof this.auth == "function") {
5861
6347
  this.auth((data) => {
5862
- this.packet({ type: PacketType.CONNECT, data });
6348
+ this._sendConnectPacket(data);
5863
6349
  });
5864
6350
  }
5865
6351
  else {
5866
- this.packet({ type: PacketType.CONNECT, data: this.auth });
6352
+ this._sendConnectPacket(this.auth);
5867
6353
  }
5868
6354
  }
6355
+ /**
6356
+ * Sends a CONNECT packet to initiate the Socket.IO session.
6357
+ *
6358
+ * @param data
6359
+ * @private
6360
+ */
6361
+ _sendConnectPacket(data) {
6362
+ this.packet({
6363
+ type: PacketType.CONNECT,
6364
+ data: this._pid
6365
+ ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data)
6366
+ : data,
6367
+ });
6368
+ }
5869
6369
  /**
5870
6370
  * Called upon engine or manager `error`.
5871
6371
  *
@@ -5888,6 +6388,26 @@ class Socket extends Emitter_1 {
5888
6388
  this.connected = false;
5889
6389
  delete this.id;
5890
6390
  this.emitReserved("disconnect", reason, description);
6391
+ this._clearAcks();
6392
+ }
6393
+ /**
6394
+ * Clears the acknowledgement handlers upon disconnection, since the client will never receive an acknowledgement from
6395
+ * the server.
6396
+ *
6397
+ * @private
6398
+ */
6399
+ _clearAcks() {
6400
+ Object.keys(this.acks).forEach((id) => {
6401
+ const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id);
6402
+ if (!isBuffered) {
6403
+ // note: handlers that do not accept an error as first argument are ignored here
6404
+ const ack = this.acks[id];
6405
+ delete this.acks[id];
6406
+ if (ack.withError) {
6407
+ ack.call(this, new Error("socket has been disconnected"));
6408
+ }
6409
+ }
6410
+ });
5891
6411
  }
5892
6412
  /**
5893
6413
  * Called with socket packet.
@@ -5902,8 +6422,7 @@ class Socket extends Emitter_1 {
5902
6422
  switch (packet.type) {
5903
6423
  case PacketType.CONNECT:
5904
6424
  if (packet.data && packet.data.sid) {
5905
- const id = packet.data.sid;
5906
- this.onconnect(id);
6425
+ this.onconnect(packet.data.sid, packet.data.pid);
5907
6426
  }
5908
6427
  else {
5909
6428
  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/)"));
@@ -5955,6 +6474,9 @@ class Socket extends Emitter_1 {
5955
6474
  }
5956
6475
  }
5957
6476
  super.emit.apply(this, args);
6477
+ if (this._pid && args.length && typeof args[args.length - 1] === "string") {
6478
+ this._lastOffset = args[args.length - 1];
6479
+ }
5958
6480
  }
5959
6481
  /**
5960
6482
  * Produces an ack callback to emit with an event.
@@ -5977,28 +6499,37 @@ class Socket extends Emitter_1 {
5977
6499
  };
5978
6500
  }
5979
6501
  /**
5980
- * Called upon a server acknowlegement.
6502
+ * Called upon a server acknowledgement.
5981
6503
  *
5982
6504
  * @param packet
5983
6505
  * @private
5984
6506
  */
5985
6507
  onack(packet) {
5986
6508
  const ack = this.acks[packet.id];
5987
- if ("function" === typeof ack) {
5988
- ack.apply(this, packet.data);
5989
- delete this.acks[packet.id];
6509
+ if (typeof ack !== "function") {
6510
+ return;
6511
+ }
6512
+ delete this.acks[packet.id];
6513
+ // @ts-ignore FIXME ack is incorrectly inferred as 'never'
6514
+ if (ack.withError) {
6515
+ packet.data.unshift(null);
5990
6516
  }
6517
+ // @ts-ignore
6518
+ ack.apply(this, packet.data);
5991
6519
  }
5992
6520
  /**
5993
6521
  * Called upon server connect.
5994
6522
  *
5995
6523
  * @private
5996
6524
  */
5997
- onconnect(id) {
6525
+ onconnect(id, pid) {
5998
6526
  this.id = id;
6527
+ this.recovered = pid && this._pid === pid;
6528
+ this._pid = pid; // defined only if connection state recovery is enabled
5999
6529
  this.connected = true;
6000
6530
  this.emitBuffered();
6001
6531
  this.emitReserved("connect");
6532
+ this._drainQueue(true);
6002
6533
  }
6003
6534
  /**
6004
6535
  * Emit buffered events (received and emitted).
@@ -6039,10 +6570,20 @@ class Socket extends Emitter_1 {
6039
6570
  this.io["_destroy"](this);
6040
6571
  }
6041
6572
  /**
6042
- * Disconnects the socket manually.
6573
+ * Disconnects the socket manually. In that case, the socket will not try to reconnect.
6574
+ *
6575
+ * If this is the last active Socket instance of the {@link Manager}, the low-level connection will be closed.
6576
+ *
6577
+ * @example
6578
+ * const socket = io();
6579
+ *
6580
+ * socket.on("disconnect", (reason) => {
6581
+ * // console.log(reason); prints "io client disconnect"
6582
+ * });
6583
+ *
6584
+ * socket.disconnect();
6043
6585
  *
6044
6586
  * @return self
6045
- * @public
6046
6587
  */
6047
6588
  disconnect() {
6048
6589
  if (this.connected) {
@@ -6057,10 +6598,9 @@ class Socket extends Emitter_1 {
6057
6598
  return this;
6058
6599
  }
6059
6600
  /**
6060
- * Alias for disconnect()
6601
+ * Alias for {@link disconnect()}.
6061
6602
  *
6062
6603
  * @return self
6063
- * @public
6064
6604
  */
6065
6605
  close() {
6066
6606
  return this.disconnect();
@@ -6068,9 +6608,11 @@ class Socket extends Emitter_1 {
6068
6608
  /**
6069
6609
  * Sets the compress flag.
6070
6610
  *
6611
+ * @example
6612
+ * socket.compress(false).emit("hello");
6613
+ *
6071
6614
  * @param compress - if `true`, compresses the sending data
6072
6615
  * @return self
6073
- * @public
6074
6616
  */
6075
6617
  compress(compress) {
6076
6618
  this.flags.compress = compress;
@@ -6080,8 +6622,10 @@ class Socket extends Emitter_1 {
6080
6622
  * Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
6081
6623
  * ready to send messages.
6082
6624
  *
6625
+ * @example
6626
+ * socket.volatile.emit("hello"); // the server may or may not receive it
6627
+ *
6083
6628
  * @returns self
6084
- * @public
6085
6629
  */
6086
6630
  get volatile() {
6087
6631
  this.flags.volatile = true;
@@ -6091,16 +6635,14 @@ class Socket extends Emitter_1 {
6091
6635
  * Sets a modifier for a subsequent event emission that the callback will be called with an error when the
6092
6636
  * given number of milliseconds have elapsed without an acknowledgement from the server:
6093
6637
  *
6094
- * ```
6638
+ * @example
6095
6639
  * socket.timeout(5000).emit("my-event", (err) => {
6096
6640
  * if (err) {
6097
6641
  * // the server did not acknowledge the event in the given delay
6098
6642
  * }
6099
6643
  * });
6100
- * ```
6101
6644
  *
6102
6645
  * @returns self
6103
- * @public
6104
6646
  */
6105
6647
  timeout(timeout) {
6106
6648
  this.flags.timeout = timeout;
@@ -6110,8 +6652,12 @@ class Socket extends Emitter_1 {
6110
6652
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6111
6653
  * callback.
6112
6654
  *
6655
+ * @example
6656
+ * socket.onAny((event, ...args) => {
6657
+ * console.log(`got ${event}`);
6658
+ * });
6659
+ *
6113
6660
  * @param listener
6114
- * @public
6115
6661
  */
6116
6662
  onAny(listener) {
6117
6663
  this._anyListeners = this._anyListeners || [];
@@ -6122,8 +6668,12 @@ class Socket extends Emitter_1 {
6122
6668
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6123
6669
  * callback. The listener is added to the beginning of the listeners array.
6124
6670
  *
6671
+ * @example
6672
+ * socket.prependAny((event, ...args) => {
6673
+ * console.log(`got event ${event}`);
6674
+ * });
6675
+ *
6125
6676
  * @param listener
6126
- * @public
6127
6677
  */
6128
6678
  prependAny(listener) {
6129
6679
  this._anyListeners = this._anyListeners || [];
@@ -6133,8 +6683,20 @@ class Socket extends Emitter_1 {
6133
6683
  /**
6134
6684
  * Removes the listener that will be fired when any event is emitted.
6135
6685
  *
6686
+ * @example
6687
+ * const catchAllListener = (event, ...args) => {
6688
+ * console.log(`got event ${event}`);
6689
+ * }
6690
+ *
6691
+ * socket.onAny(catchAllListener);
6692
+ *
6693
+ * // remove a specific listener
6694
+ * socket.offAny(catchAllListener);
6695
+ *
6696
+ * // or remove all listeners
6697
+ * socket.offAny();
6698
+ *
6136
6699
  * @param listener
6137
- * @public
6138
6700
  */
6139
6701
  offAny(listener) {
6140
6702
  if (!this._anyListeners) {
@@ -6157,8 +6719,6 @@ class Socket extends Emitter_1 {
6157
6719
  /**
6158
6720
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6159
6721
  * e.g. to remove listeners.
6160
- *
6161
- * @public
6162
6722
  */
6163
6723
  listenersAny() {
6164
6724
  return this._anyListeners || [];
@@ -6167,17 +6727,14 @@ class Socket extends Emitter_1 {
6167
6727
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6168
6728
  * callback.
6169
6729
  *
6170
- * @param listener
6171
- *
6172
- * <pre><code>
6730
+ * Note: acknowledgements sent to the server are not included.
6173
6731
  *
6732
+ * @example
6174
6733
  * socket.onAnyOutgoing((event, ...args) => {
6175
- * console.log(event);
6734
+ * console.log(`sent event ${event}`);
6176
6735
  * });
6177
6736
  *
6178
- * </pre></code>
6179
- *
6180
- * @public
6737
+ * @param listener
6181
6738
  */
6182
6739
  onAnyOutgoing(listener) {
6183
6740
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6188,17 +6745,14 @@ class Socket extends Emitter_1 {
6188
6745
  * Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
6189
6746
  * callback. The listener is added to the beginning of the listeners array.
6190
6747
  *
6191
- * @param listener
6192
- *
6193
- * <pre><code>
6748
+ * Note: acknowledgements sent to the server are not included.
6194
6749
  *
6750
+ * @example
6195
6751
  * socket.prependAnyOutgoing((event, ...args) => {
6196
- * console.log(event);
6752
+ * console.log(`sent event ${event}`);
6197
6753
  * });
6198
6754
  *
6199
- * </pre></code>
6200
- *
6201
- * @public
6755
+ * @param listener
6202
6756
  */
6203
6757
  prependAnyOutgoing(listener) {
6204
6758
  this._anyOutgoingListeners = this._anyOutgoingListeners || [];
@@ -6208,22 +6762,20 @@ class Socket extends Emitter_1 {
6208
6762
  /**
6209
6763
  * Removes the listener that will be fired when any event is emitted.
6210
6764
  *
6211
- * @param listener
6212
- *
6213
- * <pre><code>
6214
- *
6215
- * const handler = (event, ...args) => {
6216
- * console.log(event);
6765
+ * @example
6766
+ * const catchAllListener = (event, ...args) => {
6767
+ * console.log(`sent event ${event}`);
6217
6768
  * }
6218
6769
  *
6219
- * socket.onAnyOutgoing(handler);
6770
+ * socket.onAnyOutgoing(catchAllListener);
6220
6771
  *
6221
- * // then later
6222
- * socket.offAnyOutgoing(handler);
6772
+ * // remove a specific listener
6773
+ * socket.offAnyOutgoing(catchAllListener);
6223
6774
  *
6224
- * </pre></code>
6775
+ * // or remove all listeners
6776
+ * socket.offAnyOutgoing();
6225
6777
  *
6226
- * @public
6778
+ * @param [listener] - the catch-all listener (optional)
6227
6779
  */
6228
6780
  offAnyOutgoing(listener) {
6229
6781
  if (!this._anyOutgoingListeners) {
@@ -6246,8 +6798,6 @@ class Socket extends Emitter_1 {
6246
6798
  /**
6247
6799
  * Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
6248
6800
  * e.g. to remove listeners.
6249
- *
6250
- * @public
6251
6801
  */
6252
6802
  listenersAnyOutgoing() {
6253
6803
  return this._anyOutgoingListeners || [];
@@ -6447,36 +6997,33 @@ class Manager extends Emitter_1 {
6447
6997
  self.onopen();
6448
6998
  fn && fn();
6449
6999
  });
6450
- // emit `error`
6451
- const errorSub = on(socket, "error", (err) => {
6452
- self.cleanup();
6453
- self._readyState = "closed";
7000
+ const onError = (err) => {
7001
+ this.cleanup();
7002
+ this._readyState = "closed";
6454
7003
  this.emitReserved("error", err);
6455
7004
  if (fn) {
6456
7005
  fn(err);
6457
7006
  }
6458
7007
  else {
6459
7008
  // Only do this if there is no fn to handle the error
6460
- self.maybeReconnectOnOpen();
7009
+ this.maybeReconnectOnOpen();
6461
7010
  }
6462
- });
7011
+ };
7012
+ // emit `error`
7013
+ const errorSub = on(socket, "error", onError);
6463
7014
  if (false !== this._timeout) {
6464
7015
  const timeout = this._timeout;
6465
- if (timeout === 0) {
6466
- openSubDestroy(); // prevents a race condition with the 'open' event
6467
- }
6468
7016
  // set timer
6469
7017
  const timer = this.setTimeoutFn(() => {
6470
7018
  openSubDestroy();
7019
+ onError(new Error("timeout"));
6471
7020
  socket.close();
6472
- // @ts-ignore
6473
- socket.emit("error", new Error("timeout"));
6474
7021
  }, timeout);
6475
7022
  if (this.opts.autoUnref) {
6476
7023
  timer.unref();
6477
7024
  }
6478
- this.subs.push(function subDestroy() {
6479
- clearTimeout(timer);
7025
+ this.subs.push(() => {
7026
+ this.clearTimeoutFn(timer);
6480
7027
  });
6481
7028
  }
6482
7029
  this.subs.push(openSubDestroy);
@@ -6521,7 +7068,12 @@ class Manager extends Emitter_1 {
6521
7068
  * @private
6522
7069
  */
6523
7070
  ondata(data) {
6524
- this.decoder.add(data);
7071
+ try {
7072
+ this.decoder.add(data);
7073
+ }
7074
+ catch (e) {
7075
+ this.onclose("parse error", e);
7076
+ }
6525
7077
  }
6526
7078
  /**
6527
7079
  * Called when parser fully decodes a packet.
@@ -6529,7 +7081,10 @@ class Manager extends Emitter_1 {
6529
7081
  * @private
6530
7082
  */
6531
7083
  ondecoded(packet) {
6532
- this.emitReserved("packet", packet);
7084
+ // the nextTick call prevents an exception in a user-provided event listener from triggering a disconnection due to a "parse error"
7085
+ nextTick(() => {
7086
+ this.emitReserved("packet", packet);
7087
+ }, this.setTimeoutFn);
6533
7088
  }
6534
7089
  /**
6535
7090
  * Called upon socket error.
@@ -6551,6 +7106,9 @@ class Manager extends Emitter_1 {
6551
7106
  socket = new Socket(this, nsp, opts);
6552
7107
  this.nsps[nsp] = socket;
6553
7108
  }
7109
+ else if (this._autoConnect && !socket.active) {
7110
+ socket.connect();
7111
+ }
6554
7112
  return socket;
6555
7113
  }
6556
7114
  /**
@@ -6663,8 +7221,8 @@ class Manager extends Emitter_1 {
6663
7221
  if (this.opts.autoUnref) {
6664
7222
  timer.unref();
6665
7223
  }
6666
- this.subs.push(function subDestroy() {
6667
- clearTimeout(timer);
7224
+ this.subs.push(() => {
7225
+ this.clearTimeoutFn(timer);
6668
7226
  });
6669
7227
  }
6670
7228
  }