@xapp/chat-widget 1.75.0 → 1.76.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
@@ -3902,6 +3902,15 @@ Emitter.prototype.hasListeners = function(event){
3902
3902
  return !! this.listeners(event).length;
3903
3903
  };
3904
3904
 
3905
+ const nextTick = (() => {
3906
+ const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
3907
+ if (isPromiseAvailable) {
3908
+ return (cb) => Promise.resolve().then(cb);
3909
+ }
3910
+ else {
3911
+ return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
3912
+ }
3913
+ })();
3905
3914
  const globalThisShim = (() => {
3906
3915
  if (typeof self !== "undefined") {
3907
3916
  return self;
@@ -3913,6 +3922,8 @@ const globalThisShim = (() => {
3913
3922
  return Function("return this")();
3914
3923
  }
3915
3924
  })();
3925
+ const defaultBinaryType = "arraybuffer";
3926
+ function createCookieJar() { }
3916
3927
 
3917
3928
  function pick(obj, ...attr) {
3918
3929
  return attr.reduce((acc, k) => {
@@ -3965,6 +3976,13 @@ function utf8Length(str) {
3965
3976
  }
3966
3977
  return length;
3967
3978
  }
3979
+ /**
3980
+ * Generates a random 8-characters string.
3981
+ */
3982
+ function randomString$1() {
3983
+ return (Date.now().toString(36).substring(3) +
3984
+ Math.random().toString(36).substring(2, 5));
3985
+ }
3968
3986
 
3969
3987
  // imported from https://github.com/galkn/querystring
3970
3988
  /**
@@ -3974,7 +3992,7 @@ function utf8Length(str) {
3974
3992
  * @param {Object}
3975
3993
  * @api private
3976
3994
  */
3977
- function encode$1(obj) {
3995
+ function encode(obj) {
3978
3996
  let str = '';
3979
3997
  for (let i in obj) {
3980
3998
  if (obj.hasOwnProperty(i)) {
@@ -4023,6 +4041,7 @@ class Transport extends Emitter_1 {
4023
4041
  this.opts = opts;
4024
4042
  this.query = opts.query;
4025
4043
  this.socket = opts.socket;
4044
+ this.supportsBinary = !opts.forceBase64;
4026
4045
  }
4027
4046
  /**
4028
4047
  * Emits an error.
@@ -4131,115 +4150,15 @@ class Transport extends Emitter_1 {
4131
4150
  }
4132
4151
  }
4133
4152
  _query(query) {
4134
- const encodedQuery = encode$1(query);
4153
+ const encodedQuery = encode(query);
4135
4154
  return encodedQuery.length ? "?" + encodedQuery : "";
4136
4155
  }
4137
4156
  }
4138
4157
 
4139
- // imported from https://github.com/unshiftio/yeast
4140
- const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split(''), length = 64, map = {};
4141
- let seed = 0, i = 0, prev;
4142
- /**
4143
- * Return a string representing the specified number.
4144
- *
4145
- * @param {Number} num The number to convert.
4146
- * @returns {String} The string representation of the number.
4147
- * @api public
4148
- */
4149
- function encode(num) {
4150
- let encoded = '';
4151
- do {
4152
- encoded = alphabet[num % length] + encoded;
4153
- num = Math.floor(num / length);
4154
- } while (num > 0);
4155
- return encoded;
4156
- }
4157
- /**
4158
- * Yeast: A tiny growing id generator.
4159
- *
4160
- * @returns {String} A unique id.
4161
- * @api public
4162
- */
4163
- function yeast() {
4164
- const now = encode(+new Date());
4165
- if (now !== prev)
4166
- return seed = 0, prev = now;
4167
- return now + '.' + encode(seed++);
4168
- }
4169
- //
4170
- // Map each character to its index.
4171
- //
4172
- for (; i < length; i++)
4173
- map[alphabet[i]] = i;
4174
-
4175
- // imported from https://github.com/component/has-cors
4176
- let value = false;
4177
- try {
4178
- value = typeof XMLHttpRequest !== 'undefined' &&
4179
- 'withCredentials' in new XMLHttpRequest();
4180
- }
4181
- catch (err) {
4182
- // if XMLHttp support is disabled in IE then it will throw
4183
- // when trying to create
4184
- }
4185
- const hasCORS = value;
4186
-
4187
- // browser shim for xmlhttprequest module
4188
- function XHR(opts) {
4189
- const xdomain = opts.xdomain;
4190
- // XMLHttpRequest can be disabled on IE
4191
- try {
4192
- if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
4193
- return new XMLHttpRequest();
4194
- }
4195
- }
4196
- catch (e) { }
4197
- if (!xdomain) {
4198
- try {
4199
- return new globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
4200
- }
4201
- catch (e) { }
4202
- }
4203
- }
4204
- function createCookieJar() { }
4205
-
4206
- function empty$2() { }
4207
- const hasXHR2 = (function () {
4208
- const xhr = new XHR({
4209
- xdomain: false,
4210
- });
4211
- return null != xhr.responseType;
4212
- })();
4213
4158
  class Polling extends Transport {
4214
- /**
4215
- * XHR Polling constructor.
4216
- *
4217
- * @param {Object} opts
4218
- * @package
4219
- */
4220
- constructor(opts) {
4221
- super(opts);
4222
- this.polling = false;
4223
- if (typeof location !== "undefined") {
4224
- const isSSL = "https:" === location.protocol;
4225
- let port = location.port;
4226
- // some user agents have empty `location.port`
4227
- if (!port) {
4228
- port = isSSL ? "443" : "80";
4229
- }
4230
- this.xd =
4231
- (typeof location !== "undefined" &&
4232
- opts.hostname !== location.hostname) ||
4233
- port !== opts.port;
4234
- }
4235
- /**
4236
- * XHR supports binary
4237
- */
4238
- const forceBase64 = opts && opts.forceBase64;
4239
- this.supportsBinary = hasXHR2 && !forceBase64;
4240
- if (this.opts.withCredentials) {
4241
- this.cookieJar = createCookieJar();
4242
- }
4159
+ constructor() {
4160
+ super(...arguments);
4161
+ this._polling = false;
4243
4162
  }
4244
4163
  get name() {
4245
4164
  return "polling";
@@ -4251,7 +4170,7 @@ class Polling extends Transport {
4251
4170
  * @protected
4252
4171
  */
4253
4172
  doOpen() {
4254
- this.poll();
4173
+ this._poll();
4255
4174
  }
4256
4175
  /**
4257
4176
  * Pauses polling.
@@ -4265,9 +4184,9 @@ class Polling extends Transport {
4265
4184
  this.readyState = "paused";
4266
4185
  onPause();
4267
4186
  };
4268
- if (this.polling || !this.writable) {
4187
+ if (this._polling || !this.writable) {
4269
4188
  let total = 0;
4270
- if (this.polling) {
4189
+ if (this._polling) {
4271
4190
  total++;
4272
4191
  this.once("pollComplete", function () {
4273
4192
  --total || pause();
@@ -4289,8 +4208,8 @@ class Polling extends Transport {
4289
4208
  *
4290
4209
  * @private
4291
4210
  */
4292
- poll() {
4293
- this.polling = true;
4211
+ _poll() {
4212
+ this._polling = true;
4294
4213
  this.doPoll();
4295
4214
  this.emitReserved("poll");
4296
4215
  }
@@ -4318,10 +4237,10 @@ class Polling extends Transport {
4318
4237
  // if an event did not trigger closing
4319
4238
  if ("closed" !== this.readyState) {
4320
4239
  // if we got data we're not polling
4321
- this.polling = false;
4240
+ this._polling = false;
4322
4241
  this.emitReserved("pollComplete");
4323
4242
  if ("open" === this.readyState) {
4324
- this.poll();
4243
+ this._poll();
4325
4244
  }
4326
4245
  }
4327
4246
  }
@@ -4368,22 +4287,49 @@ class Polling extends Transport {
4368
4287
  const query = this.query || {};
4369
4288
  // cache busting is forced
4370
4289
  if (false !== this.opts.timestampRequests) {
4371
- query[this.opts.timestampParam] = yeast();
4290
+ query[this.opts.timestampParam] = randomString$1();
4372
4291
  }
4373
4292
  if (!this.supportsBinary && !query.sid) {
4374
4293
  query.b64 = 1;
4375
4294
  }
4376
4295
  return this.createUri(schema, query);
4377
4296
  }
4297
+ }
4298
+
4299
+ // imported from https://github.com/component/has-cors
4300
+ let value = false;
4301
+ try {
4302
+ value = typeof XMLHttpRequest !== 'undefined' &&
4303
+ 'withCredentials' in new XMLHttpRequest();
4304
+ }
4305
+ catch (err) {
4306
+ // if XMLHttp support is disabled in IE then it will throw
4307
+ // when trying to create
4308
+ }
4309
+ const hasCORS = value;
4310
+
4311
+ function empty$2() { }
4312
+ class BaseXHR extends Polling {
4378
4313
  /**
4379
- * Creates a request.
4314
+ * XHR Polling constructor.
4380
4315
  *
4381
- * @param {String} method
4382
- * @private
4316
+ * @param {Object} opts
4317
+ * @package
4383
4318
  */
4384
- request(opts = {}) {
4385
- Object.assign(opts, { xd: this.xd, cookieJar: this.cookieJar }, this.opts);
4386
- return new Request(this.uri(), opts);
4319
+ constructor(opts) {
4320
+ super(opts);
4321
+ if (typeof location !== "undefined") {
4322
+ const isSSL = "https:" === location.protocol;
4323
+ let port = location.port;
4324
+ // some user agents have empty `location.port`
4325
+ if (!port) {
4326
+ port = isSSL ? "443" : "80";
4327
+ }
4328
+ this.xd =
4329
+ (typeof location !== "undefined" &&
4330
+ opts.hostname !== location.hostname) ||
4331
+ port !== opts.port;
4332
+ }
4387
4333
  }
4388
4334
  /**
4389
4335
  * Sends data.
@@ -4423,39 +4369,41 @@ class Request extends Emitter_1 {
4423
4369
  * @param {Object} options
4424
4370
  * @package
4425
4371
  */
4426
- constructor(uri, opts) {
4372
+ constructor(createRequest, uri, opts) {
4427
4373
  super();
4374
+ this.createRequest = createRequest;
4428
4375
  installTimerFunctions(this, opts);
4429
- this.opts = opts;
4430
- this.method = opts.method || "GET";
4431
- this.uri = uri;
4432
- this.data = undefined !== opts.data ? opts.data : null;
4433
- this.create();
4376
+ this._opts = opts;
4377
+ this._method = opts.method || "GET";
4378
+ this._uri = uri;
4379
+ this._data = undefined !== opts.data ? opts.data : null;
4380
+ this._create();
4434
4381
  }
4435
4382
  /**
4436
4383
  * Creates the XHR object and sends the request.
4437
4384
  *
4438
4385
  * @private
4439
4386
  */
4440
- create() {
4387
+ _create() {
4441
4388
  var _a;
4442
- const opts = pick(this.opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4443
- opts.xdomain = !!this.opts.xd;
4444
- const xhr = (this.xhr = new XHR(opts));
4389
+ const opts = pick(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref");
4390
+ opts.xdomain = !!this._opts.xd;
4391
+ const xhr = (this._xhr = this.createRequest(opts));
4445
4392
  try {
4446
- xhr.open(this.method, this.uri, true);
4393
+ xhr.open(this._method, this._uri, true);
4447
4394
  try {
4448
- if (this.opts.extraHeaders) {
4395
+ if (this._opts.extraHeaders) {
4396
+ // @ts-ignore
4449
4397
  xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
4450
- for (let i in this.opts.extraHeaders) {
4451
- if (this.opts.extraHeaders.hasOwnProperty(i)) {
4452
- xhr.setRequestHeader(i, this.opts.extraHeaders[i]);
4398
+ for (let i in this._opts.extraHeaders) {
4399
+ if (this._opts.extraHeaders.hasOwnProperty(i)) {
4400
+ xhr.setRequestHeader(i, this._opts.extraHeaders[i]);
4453
4401
  }
4454
4402
  }
4455
4403
  }
4456
4404
  }
4457
4405
  catch (e) { }
4458
- if ("POST" === this.method) {
4406
+ if ("POST" === this._method) {
4459
4407
  try {
4460
4408
  xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
4461
4409
  }
@@ -4465,46 +4413,48 @@ class Request extends Emitter_1 {
4465
4413
  xhr.setRequestHeader("Accept", "*/*");
4466
4414
  }
4467
4415
  catch (e) { }
4468
- (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4416
+ (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.addCookies(xhr);
4469
4417
  // ie6 check
4470
4418
  if ("withCredentials" in xhr) {
4471
- xhr.withCredentials = this.opts.withCredentials;
4419
+ xhr.withCredentials = this._opts.withCredentials;
4472
4420
  }
4473
- if (this.opts.requestTimeout) {
4474
- xhr.timeout = this.opts.requestTimeout;
4421
+ if (this._opts.requestTimeout) {
4422
+ xhr.timeout = this._opts.requestTimeout;
4475
4423
  }
4476
4424
  xhr.onreadystatechange = () => {
4477
4425
  var _a;
4478
4426
  if (xhr.readyState === 3) {
4479
- (_a = this.opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(xhr);
4427
+ (_a = this._opts.cookieJar) === null || _a === void 0 ? void 0 : _a.parseCookies(
4428
+ // @ts-ignore
4429
+ xhr.getResponseHeader("set-cookie"));
4480
4430
  }
4481
4431
  if (4 !== xhr.readyState)
4482
4432
  return;
4483
4433
  if (200 === xhr.status || 1223 === xhr.status) {
4484
- this.onLoad();
4434
+ this._onLoad();
4485
4435
  }
4486
4436
  else {
4487
4437
  // make sure the `error` event handler that's user-set
4488
4438
  // does not throw in the same tick and gets caught here
4489
4439
  this.setTimeoutFn(() => {
4490
- this.onError(typeof xhr.status === "number" ? xhr.status : 0);
4440
+ this._onError(typeof xhr.status === "number" ? xhr.status : 0);
4491
4441
  }, 0);
4492
4442
  }
4493
4443
  };
4494
- xhr.send(this.data);
4444
+ xhr.send(this._data);
4495
4445
  }
4496
4446
  catch (e) {
4497
4447
  // Need to defer since .create() is called directly from the constructor
4498
4448
  // and thus the 'error' event can only be only bound *after* this exception
4499
4449
  // occurs. Therefore, also, we cannot throw here at all.
4500
4450
  this.setTimeoutFn(() => {
4501
- this.onError(e);
4451
+ this._onError(e);
4502
4452
  }, 0);
4503
4453
  return;
4504
4454
  }
4505
4455
  if (typeof document !== "undefined") {
4506
- this.index = Request.requestsCount++;
4507
- Request.requests[this.index] = this;
4456
+ this._index = Request.requestsCount++;
4457
+ Request.requests[this._index] = this;
4508
4458
  }
4509
4459
  }
4510
4460
  /**
@@ -4512,42 +4462,42 @@ class Request extends Emitter_1 {
4512
4462
  *
4513
4463
  * @private
4514
4464
  */
4515
- onError(err) {
4516
- this.emitReserved("error", err, this.xhr);
4517
- this.cleanup(true);
4465
+ _onError(err) {
4466
+ this.emitReserved("error", err, this._xhr);
4467
+ this._cleanup(true);
4518
4468
  }
4519
4469
  /**
4520
4470
  * Cleans up house.
4521
4471
  *
4522
4472
  * @private
4523
4473
  */
4524
- cleanup(fromError) {
4525
- if ("undefined" === typeof this.xhr || null === this.xhr) {
4474
+ _cleanup(fromError) {
4475
+ if ("undefined" === typeof this._xhr || null === this._xhr) {
4526
4476
  return;
4527
4477
  }
4528
- this.xhr.onreadystatechange = empty$2;
4478
+ this._xhr.onreadystatechange = empty$2;
4529
4479
  if (fromError) {
4530
4480
  try {
4531
- this.xhr.abort();
4481
+ this._xhr.abort();
4532
4482
  }
4533
4483
  catch (e) { }
4534
4484
  }
4535
4485
  if (typeof document !== "undefined") {
4536
- delete Request.requests[this.index];
4486
+ delete Request.requests[this._index];
4537
4487
  }
4538
- this.xhr = null;
4488
+ this._xhr = null;
4539
4489
  }
4540
4490
  /**
4541
4491
  * Called upon load.
4542
4492
  *
4543
4493
  * @private
4544
4494
  */
4545
- onLoad() {
4546
- const data = this.xhr.responseText;
4495
+ _onLoad() {
4496
+ const data = this._xhr.responseText;
4547
4497
  if (data !== null) {
4548
4498
  this.emitReserved("data", data);
4549
4499
  this.emitReserved("success");
4550
- this.cleanup();
4500
+ this._cleanup();
4551
4501
  }
4552
4502
  }
4553
4503
  /**
@@ -4556,7 +4506,7 @@ class Request extends Emitter_1 {
4556
4506
  * @package
4557
4507
  */
4558
4508
  abort() {
4559
- this.cleanup();
4509
+ this._cleanup();
4560
4510
  }
4561
4511
  }
4562
4512
  Request.requestsCount = 0;
@@ -4584,43 +4534,56 @@ function unloadHandler() {
4584
4534
  }
4585
4535
  }
4586
4536
  }
4587
-
4588
- const nextTick = (() => {
4589
- const isPromiseAvailable = typeof Promise === "function" && typeof Promise.resolve === "function";
4590
- if (isPromiseAvailable) {
4591
- return (cb) => Promise.resolve().then(cb);
4537
+ const hasXHR2 = (function () {
4538
+ const xhr = newRequest({
4539
+ xdomain: false,
4540
+ });
4541
+ return xhr && xhr.responseType !== null;
4542
+ })();
4543
+ /**
4544
+ * HTTP long-polling based on the built-in `XMLHttpRequest` object.
4545
+ *
4546
+ * Usage: browser
4547
+ *
4548
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
4549
+ */
4550
+ class XHR extends BaseXHR {
4551
+ constructor(opts) {
4552
+ super(opts);
4553
+ const forceBase64 = opts && opts.forceBase64;
4554
+ this.supportsBinary = hasXHR2 && !forceBase64;
4592
4555
  }
4593
- else {
4594
- return (cb, setTimeoutFn) => setTimeoutFn(cb, 0);
4556
+ request(opts = {}) {
4557
+ Object.assign(opts, { xd: this.xd }, this.opts);
4558
+ return new Request(newRequest, this.uri(), opts);
4595
4559
  }
4596
- })();
4597
- const WebSocket$1 = globalThisShim.WebSocket || globalThisShim.MozWebSocket;
4598
- const usingBrowserWebSocket = true;
4599
- const defaultBinaryType = "arraybuffer";
4560
+ }
4561
+ function newRequest(opts) {
4562
+ const xdomain = opts.xdomain;
4563
+ // XMLHttpRequest can be disabled on IE
4564
+ try {
4565
+ if ("undefined" !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
4566
+ return new XMLHttpRequest();
4567
+ }
4568
+ }
4569
+ catch (e) { }
4570
+ if (!xdomain) {
4571
+ try {
4572
+ return new globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP");
4573
+ }
4574
+ catch (e) { }
4575
+ }
4576
+ }
4600
4577
 
4601
4578
  // detect ReactNative environment
4602
4579
  const isReactNative = typeof navigator !== "undefined" &&
4603
4580
  typeof navigator.product === "string" &&
4604
4581
  navigator.product.toLowerCase() === "reactnative";
4605
- class WS extends Transport {
4606
- /**
4607
- * WebSocket transport constructor.
4608
- *
4609
- * @param {Object} opts - connection options
4610
- * @protected
4611
- */
4612
- constructor(opts) {
4613
- super(opts);
4614
- this.supportsBinary = !opts.forceBase64;
4615
- }
4582
+ class BaseWS extends Transport {
4616
4583
  get name() {
4617
4584
  return "websocket";
4618
4585
  }
4619
4586
  doOpen() {
4620
- if (!this.check()) {
4621
- // let probe timeout
4622
- return;
4623
- }
4624
4587
  const uri = this.uri();
4625
4588
  const protocols = this.opts.protocols;
4626
4589
  // React Native only supports the 'headers' option, and will print a warning if anything else is passed
@@ -4631,12 +4594,7 @@ class WS extends Transport {
4631
4594
  opts.headers = this.opts.extraHeaders;
4632
4595
  }
4633
4596
  try {
4634
- this.ws =
4635
- usingBrowserWebSocket && !isReactNative
4636
- ? protocols
4637
- ? new WebSocket$1(uri, protocols)
4638
- : new WebSocket$1(uri)
4639
- : new WebSocket$1(uri, protocols, opts);
4597
+ this.ws = this.createSocket(uri, protocols, opts);
4640
4598
  }
4641
4599
  catch (err) {
4642
4600
  return this.emitReserved("error", err);
@@ -4671,16 +4629,11 @@ class WS extends Transport {
4671
4629
  const packet = packets[i];
4672
4630
  const lastPacket = i === packets.length - 1;
4673
4631
  encodePacket(packet, this.supportsBinary, (data) => {
4674
- // always create a new object (GH-437)
4675
- const opts = {};
4676
4632
  // Sometimes the websocket has already been closed but the browser didn't
4677
4633
  // have a chance of informing us about it yet, in that case send will
4678
4634
  // throw an error
4679
4635
  try {
4680
- if (usingBrowserWebSocket) {
4681
- // TypeError is thrown when passing the second argument on Safari
4682
- this.ws.send(data);
4683
- }
4636
+ this.doWrite(packet, data);
4684
4637
  }
4685
4638
  catch (e) {
4686
4639
  }
@@ -4697,6 +4650,7 @@ class WS extends Transport {
4697
4650
  }
4698
4651
  doClose() {
4699
4652
  if (typeof this.ws !== "undefined") {
4653
+ this.ws.onerror = () => { };
4700
4654
  this.ws.close();
4701
4655
  this.ws = null;
4702
4656
  }
@@ -4711,7 +4665,7 @@ class WS extends Transport {
4711
4665
  const query = this.query || {};
4712
4666
  // append timestamp to URI
4713
4667
  if (this.opts.timestampRequests) {
4714
- query[this.opts.timestampParam] = yeast();
4668
+ query[this.opts.timestampParam] = randomString$1();
4715
4669
  }
4716
4670
  // communicate binary support capabilities
4717
4671
  if (!this.supportsBinary) {
@@ -4719,29 +4673,51 @@ class WS extends Transport {
4719
4673
  }
4720
4674
  return this.createUri(schema, query);
4721
4675
  }
4722
- /**
4723
- * Feature detection for WebSocket.
4724
- *
4725
- * @return {Boolean} whether this transport is available.
4726
- * @private
4727
- */
4728
- check() {
4729
- return !!WebSocket$1;
4676
+ }
4677
+ const WebSocketCtor = globalThisShim.WebSocket || globalThisShim.MozWebSocket;
4678
+ /**
4679
+ * WebSocket transport based on the built-in `WebSocket` object.
4680
+ *
4681
+ * Usage: browser, Node.js (since v21), Deno, Bun
4682
+ *
4683
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
4684
+ * @see https://caniuse.com/mdn-api_websocket
4685
+ * @see https://nodejs.org/api/globals.html#websocket
4686
+ */
4687
+ class WS extends BaseWS {
4688
+ createSocket(uri, protocols, opts) {
4689
+ return !isReactNative
4690
+ ? protocols
4691
+ ? new WebSocketCtor(uri, protocols)
4692
+ : new WebSocketCtor(uri)
4693
+ : new WebSocketCtor(uri, protocols, opts);
4694
+ }
4695
+ doWrite(_packet, data) {
4696
+ this.ws.send(data);
4730
4697
  }
4731
4698
  }
4732
4699
 
4700
+ /**
4701
+ * WebTransport transport based on the built-in `WebTransport` object.
4702
+ *
4703
+ * Usage: browser, Node.js (with the `@fails-components/webtransport` package)
4704
+ *
4705
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
4706
+ * @see https://caniuse.com/webtransport
4707
+ */
4733
4708
  class WT extends Transport {
4734
4709
  get name() {
4735
4710
  return "webtransport";
4736
4711
  }
4737
4712
  doOpen() {
4738
- // @ts-ignore
4739
- if (typeof WebTransport !== "function") {
4740
- return;
4713
+ try {
4714
+ // @ts-ignore
4715
+ this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4741
4716
  }
4742
- // @ts-ignore
4743
- this.transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]);
4744
- this.transport.closed
4717
+ catch (err) {
4718
+ return this.emitReserved("error", err);
4719
+ }
4720
+ this._transport.closed
4745
4721
  .then(() => {
4746
4722
  this.onClose();
4747
4723
  })
@@ -4749,13 +4725,13 @@ class WT extends Transport {
4749
4725
  this.onError("webtransport error", err);
4750
4726
  });
4751
4727
  // note: we could have used async/await, but that would require some additional polyfills
4752
- this.transport.ready.then(() => {
4753
- this.transport.createBidirectionalStream().then((stream) => {
4728
+ this._transport.ready.then(() => {
4729
+ this._transport.createBidirectionalStream().then((stream) => {
4754
4730
  const decoderStream = createPacketDecoderStream(Number.MAX_SAFE_INTEGER, this.socket.binaryType);
4755
4731
  const reader = stream.readable.pipeThrough(decoderStream).getReader();
4756
4732
  const encoderStream = createPacketEncoderStream();
4757
4733
  encoderStream.readable.pipeTo(stream.writable);
4758
- this.writer = encoderStream.writable.getWriter();
4734
+ this._writer = encoderStream.writable.getWriter();
4759
4735
  const read = () => {
4760
4736
  reader
4761
4737
  .read()
@@ -4774,7 +4750,7 @@ class WT extends Transport {
4774
4750
  if (this.query.sid) {
4775
4751
  packet.data = `{"sid":"${this.query.sid}"}`;
4776
4752
  }
4777
- this.writer.write(packet).then(() => this.onOpen());
4753
+ this._writer.write(packet).then(() => this.onOpen());
4778
4754
  });
4779
4755
  });
4780
4756
  }
@@ -4783,7 +4759,7 @@ class WT extends Transport {
4783
4759
  for (let i = 0; i < packets.length; i++) {
4784
4760
  const packet = packets[i];
4785
4761
  const lastPacket = i === packets.length - 1;
4786
- this.writer.write(packet).then(() => {
4762
+ this._writer.write(packet).then(() => {
4787
4763
  if (lastPacket) {
4788
4764
  nextTick(() => {
4789
4765
  this.writable = true;
@@ -4795,14 +4771,14 @@ class WT extends Transport {
4795
4771
  }
4796
4772
  doClose() {
4797
4773
  var _a;
4798
- (_a = this.transport) === null || _a === void 0 ? void 0 : _a.close();
4774
+ (_a = this._transport) === null || _a === void 0 ? void 0 : _a.close();
4799
4775
  }
4800
4776
  }
4801
4777
 
4802
4778
  const transports = {
4803
4779
  websocket: WS,
4804
4780
  webtransport: WT,
4805
- polling: Polling,
4781
+ polling: XHR,
4806
4782
  };
4807
4783
 
4808
4784
  // imported from https://github.com/galkn/parseuri
@@ -4829,7 +4805,7 @@ const parts = [
4829
4805
  'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
4830
4806
  ];
4831
4807
  function parse$2(str) {
4832
- if (str.length > 2000) {
4808
+ if (str.length > 8000) {
4833
4809
  throw "URI too long";
4834
4810
  }
4835
4811
  const src = str, b = str.indexOf('['), e = str.indexOf(']');
@@ -4870,28 +4846,71 @@ function queryKey(uri, query) {
4870
4846
  return data;
4871
4847
  }
4872
4848
 
4873
- let Socket$1 = class Socket extends Emitter_1 {
4849
+ const withEventListeners = typeof addEventListener === "function" &&
4850
+ typeof removeEventListener === "function";
4851
+ const OFFLINE_EVENT_LISTENERS = [];
4852
+ if (withEventListeners) {
4853
+ // within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
4854
+ // script, so we create one single event listener here which will forward the event to the socket instances
4855
+ addEventListener("offline", () => {
4856
+ OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
4857
+ }, false);
4858
+ }
4859
+ /**
4860
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
4861
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
4862
+ *
4863
+ * This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
4864
+ * successfully establishes the connection.
4865
+ *
4866
+ * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
4867
+ *
4868
+ * @example
4869
+ * import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
4870
+ *
4871
+ * const socket = new SocketWithoutUpgrade({
4872
+ * transports: [WebSocket]
4873
+ * });
4874
+ *
4875
+ * socket.on("open", () => {
4876
+ * socket.send("hello");
4877
+ * });
4878
+ *
4879
+ * @see SocketWithUpgrade
4880
+ * @see Socket
4881
+ */
4882
+ class SocketWithoutUpgrade extends Emitter_1 {
4874
4883
  /**
4875
4884
  * Socket constructor.
4876
4885
  *
4877
4886
  * @param {String|Object} uri - uri or options
4878
4887
  * @param {Object} opts - options
4879
4888
  */
4880
- constructor(uri, opts = {}) {
4889
+ constructor(uri, opts) {
4881
4890
  super();
4882
4891
  this.binaryType = defaultBinaryType;
4883
4892
  this.writeBuffer = [];
4893
+ this._prevBufferLen = 0;
4894
+ this._pingInterval = -1;
4895
+ this._pingTimeout = -1;
4896
+ this._maxPayload = -1;
4897
+ /**
4898
+ * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
4899
+ * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
4900
+ */
4901
+ this._pingTimeoutTime = Infinity;
4884
4902
  if (uri && "object" === typeof uri) {
4885
4903
  opts = uri;
4886
4904
  uri = null;
4887
4905
  }
4888
4906
  if (uri) {
4889
- uri = parse$2(uri);
4890
- opts.hostname = uri.host;
4891
- opts.secure = uri.protocol === "https" || uri.protocol === "wss";
4892
- opts.port = uri.port;
4893
- if (uri.query)
4894
- opts.query = uri.query;
4907
+ const parsedUri = parse$2(uri);
4908
+ opts.hostname = parsedUri.host;
4909
+ opts.secure =
4910
+ parsedUri.protocol === "https" || parsedUri.protocol === "wss";
4911
+ opts.port = parsedUri.port;
4912
+ if (parsedUri.query)
4913
+ opts.query = parsedUri.query;
4895
4914
  }
4896
4915
  else if (opts.host) {
4897
4916
  opts.hostname = parse$2(opts.host).host;
@@ -4915,13 +4934,13 @@ let Socket$1 = class Socket extends Emitter_1 {
4915
4934
  : this.secure
4916
4935
  ? "443"
4917
4936
  : "80");
4918
- this.transports = opts.transports || [
4919
- "polling",
4920
- "websocket",
4921
- "webtransport",
4922
- ];
4923
- this.writeBuffer = [];
4924
- this.prevBufferLen = 0;
4937
+ this.transports = [];
4938
+ this._transportsByName = {};
4939
+ opts.transports.forEach((t) => {
4940
+ const transportName = t.prototype.name;
4941
+ this.transports.push(transportName);
4942
+ this._transportsByName[transportName] = t;
4943
+ });
4925
4944
  this.opts = Object.assign({
4926
4945
  path: "/engine.io",
4927
4946
  agent: false,
@@ -4943,37 +4962,33 @@ let Socket$1 = class Socket extends Emitter_1 {
4943
4962
  if (typeof this.opts.query === "string") {
4944
4963
  this.opts.query = decode(this.opts.query);
4945
4964
  }
4946
- // set on handshake
4947
- this.id = null;
4948
- this.upgrades = null;
4949
- this.pingInterval = null;
4950
- this.pingTimeout = null;
4951
- // set on heartbeat
4952
- this.pingTimeoutTimer = null;
4953
- if (typeof addEventListener === "function") {
4965
+ if (withEventListeners) {
4954
4966
  if (this.opts.closeOnBeforeunload) {
4955
4967
  // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
4956
4968
  // ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
4957
4969
  // closed/reloaded)
4958
- this.beforeunloadEventListener = () => {
4970
+ this._beforeunloadEventListener = () => {
4959
4971
  if (this.transport) {
4960
4972
  // silently close the transport
4961
4973
  this.transport.removeAllListeners();
4962
4974
  this.transport.close();
4963
4975
  }
4964
4976
  };
4965
- addEventListener("beforeunload", this.beforeunloadEventListener, false);
4977
+ addEventListener("beforeunload", this._beforeunloadEventListener, false);
4966
4978
  }
4967
4979
  if (this.hostname !== "localhost") {
4968
- this.offlineEventListener = () => {
4969
- this.onClose("transport close", {
4980
+ this._offlineEventListener = () => {
4981
+ this._onClose("transport close", {
4970
4982
  description: "network connection lost",
4971
4983
  });
4972
4984
  };
4973
- addEventListener("offline", this.offlineEventListener, false);
4985
+ OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
4974
4986
  }
4975
4987
  }
4976
- this.open();
4988
+ if (this.opts.withCredentials) {
4989
+ this._cookieJar = createCookieJar();
4990
+ }
4991
+ this._open();
4977
4992
  }
4978
4993
  /**
4979
4994
  * Creates transport of the given type.
@@ -4998,40 +5013,28 @@ let Socket$1 = class Socket extends Emitter_1 {
4998
5013
  secure: this.secure,
4999
5014
  port: this.port,
5000
5015
  }, this.opts.transportOptions[name]);
5001
- return new transports[name](opts);
5016
+ return new this._transportsByName[name](opts);
5002
5017
  }
5003
5018
  /**
5004
5019
  * Initializes transport to use and starts probe.
5005
5020
  *
5006
5021
  * @private
5007
5022
  */
5008
- open() {
5009
- let transport;
5010
- if (this.opts.rememberUpgrade &&
5011
- Socket.priorWebsocketSuccess &&
5012
- this.transports.indexOf("websocket") !== -1) {
5013
- transport = "websocket";
5014
- }
5015
- else if (0 === this.transports.length) {
5023
+ _open() {
5024
+ if (this.transports.length === 0) {
5016
5025
  // Emit error on next tick so it can be listened to
5017
5026
  this.setTimeoutFn(() => {
5018
5027
  this.emitReserved("error", "No transports available");
5019
5028
  }, 0);
5020
5029
  return;
5021
5030
  }
5022
- else {
5023
- transport = this.transports[0];
5024
- }
5031
+ const transportName = this.opts.rememberUpgrade &&
5032
+ SocketWithoutUpgrade.priorWebsocketSuccess &&
5033
+ this.transports.indexOf("websocket") !== -1
5034
+ ? "websocket"
5035
+ : this.transports[0];
5025
5036
  this.readyState = "opening";
5026
- // Retry with the next transport if the transport is disabled (jsonp: false)
5027
- try {
5028
- transport = this.createTransport(transport);
5029
- }
5030
- catch (e) {
5031
- this.transports.shift();
5032
- this.open();
5033
- return;
5034
- }
5037
+ const transport = this.createTransport(transportName);
5035
5038
  transport.open();
5036
5039
  this.setTransport(transport);
5037
5040
  }
@@ -5048,111 +5051,10 @@ let Socket$1 = class Socket extends Emitter_1 {
5048
5051
  this.transport = transport;
5049
5052
  // set up transport listeners
5050
5053
  transport
5051
- .on("drain", this.onDrain.bind(this))
5052
- .on("packet", this.onPacket.bind(this))
5053
- .on("error", this.onError.bind(this))
5054
- .on("close", (reason) => this.onClose("transport close", reason));
5055
- }
5056
- /**
5057
- * Probes a transport.
5058
- *
5059
- * @param {String} name - transport name
5060
- * @private
5061
- */
5062
- probe(name) {
5063
- let transport = this.createTransport(name);
5064
- let failed = false;
5065
- Socket.priorWebsocketSuccess = false;
5066
- const onTransportOpen = () => {
5067
- if (failed)
5068
- return;
5069
- transport.send([{ type: "ping", data: "probe" }]);
5070
- transport.once("packet", (msg) => {
5071
- if (failed)
5072
- return;
5073
- if ("pong" === msg.type && "probe" === msg.data) {
5074
- this.upgrading = true;
5075
- this.emitReserved("upgrading", transport);
5076
- if (!transport)
5077
- return;
5078
- Socket.priorWebsocketSuccess = "websocket" === transport.name;
5079
- this.transport.pause(() => {
5080
- if (failed)
5081
- return;
5082
- if ("closed" === this.readyState)
5083
- return;
5084
- cleanup();
5085
- this.setTransport(transport);
5086
- transport.send([{ type: "upgrade" }]);
5087
- this.emitReserved("upgrade", transport);
5088
- transport = null;
5089
- this.upgrading = false;
5090
- this.flush();
5091
- });
5092
- }
5093
- else {
5094
- const err = new Error("probe error");
5095
- // @ts-ignore
5096
- err.transport = transport.name;
5097
- this.emitReserved("upgradeError", err);
5098
- }
5099
- });
5100
- };
5101
- function freezeTransport() {
5102
- if (failed)
5103
- return;
5104
- // Any callback called by transport should be ignored since now
5105
- failed = true;
5106
- cleanup();
5107
- transport.close();
5108
- transport = null;
5109
- }
5110
- // Handle any error that happens while probing
5111
- const onerror = (err) => {
5112
- const error = new Error("probe error: " + err);
5113
- // @ts-ignore
5114
- error.transport = transport.name;
5115
- freezeTransport();
5116
- this.emitReserved("upgradeError", error);
5117
- };
5118
- function onTransportClose() {
5119
- onerror("transport closed");
5120
- }
5121
- // When the socket is closed while we're probing
5122
- function onclose() {
5123
- onerror("socket closed");
5124
- }
5125
- // When the socket is upgraded while we're probing
5126
- function onupgrade(to) {
5127
- if (transport && to.name !== transport.name) {
5128
- freezeTransport();
5129
- }
5130
- }
5131
- // Remove all listeners on the transport and on self
5132
- const cleanup = () => {
5133
- transport.removeListener("open", onTransportOpen);
5134
- transport.removeListener("error", onerror);
5135
- transport.removeListener("close", onTransportClose);
5136
- this.off("close", onclose);
5137
- this.off("upgrading", onupgrade);
5138
- };
5139
- transport.once("open", onTransportOpen);
5140
- transport.once("error", onerror);
5141
- transport.once("close", onTransportClose);
5142
- this.once("close", onclose);
5143
- this.once("upgrading", onupgrade);
5144
- if (this.upgrades.indexOf("webtransport") !== -1 &&
5145
- name !== "webtransport") {
5146
- // favor WebTransport
5147
- this.setTimeoutFn(() => {
5148
- if (!failed) {
5149
- transport.open();
5150
- }
5151
- }, 200);
5152
- }
5153
- else {
5154
- transport.open();
5155
- }
5054
+ .on("drain", this._onDrain.bind(this))
5055
+ .on("packet", this._onPacket.bind(this))
5056
+ .on("error", this._onError.bind(this))
5057
+ .on("close", (reason) => this._onClose("transport close", reason));
5156
5058
  }
5157
5059
  /**
5158
5060
  * Called when connection is deemed open.
@@ -5161,46 +5063,38 @@ let Socket$1 = class Socket extends Emitter_1 {
5161
5063
  */
5162
5064
  onOpen() {
5163
5065
  this.readyState = "open";
5164
- Socket.priorWebsocketSuccess = "websocket" === this.transport.name;
5066
+ SocketWithoutUpgrade.priorWebsocketSuccess =
5067
+ "websocket" === this.transport.name;
5165
5068
  this.emitReserved("open");
5166
5069
  this.flush();
5167
- // we check for `readyState` in case an `open`
5168
- // listener already closed the socket
5169
- if ("open" === this.readyState && this.opts.upgrade) {
5170
- let i = 0;
5171
- const l = this.upgrades.length;
5172
- for (; i < l; i++) {
5173
- this.probe(this.upgrades[i]);
5174
- }
5175
- }
5176
5070
  }
5177
5071
  /**
5178
5072
  * Handles a packet.
5179
5073
  *
5180
5074
  * @private
5181
5075
  */
5182
- onPacket(packet) {
5076
+ _onPacket(packet) {
5183
5077
  if ("opening" === this.readyState ||
5184
5078
  "open" === this.readyState ||
5185
5079
  "closing" === this.readyState) {
5186
5080
  this.emitReserved("packet", packet);
5187
5081
  // Socket is live - any packet counts
5188
5082
  this.emitReserved("heartbeat");
5189
- this.resetPingTimeout();
5190
5083
  switch (packet.type) {
5191
5084
  case "open":
5192
5085
  this.onHandshake(JSON.parse(packet.data));
5193
5086
  break;
5194
5087
  case "ping":
5195
- this.sendPacket("pong");
5088
+ this._sendPacket("pong");
5196
5089
  this.emitReserved("ping");
5197
5090
  this.emitReserved("pong");
5091
+ this._resetPingTimeout();
5198
5092
  break;
5199
5093
  case "error":
5200
5094
  const err = new Error("server error");
5201
5095
  // @ts-ignore
5202
5096
  err.code = packet.data;
5203
- this.onError(err);
5097
+ this._onError(err);
5204
5098
  break;
5205
5099
  case "message":
5206
5100
  this.emitReserved("data", packet.data);
@@ -5219,28 +5113,29 @@ let Socket$1 = class Socket extends Emitter_1 {
5219
5113
  this.emitReserved("handshake", data);
5220
5114
  this.id = data.sid;
5221
5115
  this.transport.query.sid = data.sid;
5222
- this.upgrades = this.filterUpgrades(data.upgrades);
5223
- this.pingInterval = data.pingInterval;
5224
- this.pingTimeout = data.pingTimeout;
5225
- this.maxPayload = data.maxPayload;
5116
+ this._pingInterval = data.pingInterval;
5117
+ this._pingTimeout = data.pingTimeout;
5118
+ this._maxPayload = data.maxPayload;
5226
5119
  this.onOpen();
5227
5120
  // In case open handler closes socket
5228
5121
  if ("closed" === this.readyState)
5229
5122
  return;
5230
- this.resetPingTimeout();
5123
+ this._resetPingTimeout();
5231
5124
  }
5232
5125
  /**
5233
5126
  * Sets and resets ping timeout timer based on server pings.
5234
5127
  *
5235
5128
  * @private
5236
5129
  */
5237
- resetPingTimeout() {
5238
- this.clearTimeoutFn(this.pingTimeoutTimer);
5239
- this.pingTimeoutTimer = this.setTimeoutFn(() => {
5240
- this.onClose("ping timeout");
5241
- }, this.pingInterval + this.pingTimeout);
5130
+ _resetPingTimeout() {
5131
+ this.clearTimeoutFn(this._pingTimeoutTimer);
5132
+ const delay = this._pingInterval + this._pingTimeout;
5133
+ this._pingTimeoutTime = Date.now() + delay;
5134
+ this._pingTimeoutTimer = this.setTimeoutFn(() => {
5135
+ this._onClose("ping timeout");
5136
+ }, delay);
5242
5137
  if (this.opts.autoUnref) {
5243
- this.pingTimeoutTimer.unref();
5138
+ this._pingTimeoutTimer.unref();
5244
5139
  }
5245
5140
  }
5246
5141
  /**
@@ -5248,12 +5143,12 @@ let Socket$1 = class Socket extends Emitter_1 {
5248
5143
  *
5249
5144
  * @private
5250
5145
  */
5251
- onDrain() {
5252
- this.writeBuffer.splice(0, this.prevBufferLen);
5146
+ _onDrain() {
5147
+ this.writeBuffer.splice(0, this._prevBufferLen);
5253
5148
  // setting prevBufferLen = 0 is very important
5254
5149
  // for example, when upgrading, upgrade packet is sent over,
5255
5150
  // and a nonzero prevBufferLen could cause problems on `drain`
5256
- this.prevBufferLen = 0;
5151
+ this._prevBufferLen = 0;
5257
5152
  if (0 === this.writeBuffer.length) {
5258
5153
  this.emitReserved("drain");
5259
5154
  }
@@ -5271,11 +5166,11 @@ let Socket$1 = class Socket extends Emitter_1 {
5271
5166
  this.transport.writable &&
5272
5167
  !this.upgrading &&
5273
5168
  this.writeBuffer.length) {
5274
- const packets = this.getWritablePackets();
5169
+ const packets = this._getWritablePackets();
5275
5170
  this.transport.send(packets);
5276
5171
  // keep track of current length of writeBuffer
5277
5172
  // splice writeBuffer and callbackBuffer on `drain`
5278
- this.prevBufferLen = packets.length;
5173
+ this._prevBufferLen = packets.length;
5279
5174
  this.emitReserved("flush");
5280
5175
  }
5281
5176
  }
@@ -5285,8 +5180,8 @@ let Socket$1 = class Socket extends Emitter_1 {
5285
5180
  *
5286
5181
  * @private
5287
5182
  */
5288
- getWritablePackets() {
5289
- const shouldCheckPayloadSize = this.maxPayload &&
5183
+ _getWritablePackets() {
5184
+ const shouldCheckPayloadSize = this._maxPayload &&
5290
5185
  this.transport.name === "polling" &&
5291
5186
  this.writeBuffer.length > 1;
5292
5187
  if (!shouldCheckPayloadSize) {
@@ -5298,27 +5193,56 @@ let Socket$1 = class Socket extends Emitter_1 {
5298
5193
  if (data) {
5299
5194
  payloadSize += byteLength(data);
5300
5195
  }
5301
- if (i > 0 && payloadSize > this.maxPayload) {
5196
+ if (i > 0 && payloadSize > this._maxPayload) {
5302
5197
  return this.writeBuffer.slice(0, i);
5303
5198
  }
5304
5199
  payloadSize += 2; // separator + packet type
5305
5200
  }
5306
5201
  return this.writeBuffer;
5307
5202
  }
5203
+ /**
5204
+ * Checks whether the heartbeat timer has expired but the socket has not yet been notified.
5205
+ *
5206
+ * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
5207
+ * `write()` method then the message would not be buffered by the Socket.IO client.
5208
+ *
5209
+ * @return {boolean}
5210
+ * @private
5211
+ */
5212
+ /* private */ _hasPingExpired() {
5213
+ if (!this._pingTimeoutTime)
5214
+ return true;
5215
+ const hasExpired = Date.now() > this._pingTimeoutTime;
5216
+ if (hasExpired) {
5217
+ this._pingTimeoutTime = 0;
5218
+ nextTick(() => {
5219
+ this._onClose("ping timeout");
5220
+ }, this.setTimeoutFn);
5221
+ }
5222
+ return hasExpired;
5223
+ }
5308
5224
  /**
5309
5225
  * Sends a message.
5310
5226
  *
5311
5227
  * @param {String} msg - message.
5312
5228
  * @param {Object} options.
5313
- * @param {Function} callback function.
5229
+ * @param {Function} fn - callback function.
5314
5230
  * @return {Socket} for chaining.
5315
5231
  */
5316
5232
  write(msg, options, fn) {
5317
- this.sendPacket("message", msg, options, fn);
5233
+ this._sendPacket("message", msg, options, fn);
5318
5234
  return this;
5319
5235
  }
5236
+ /**
5237
+ * Sends a message. Alias of {@link Socket#write}.
5238
+ *
5239
+ * @param {String} msg - message.
5240
+ * @param {Object} options.
5241
+ * @param {Function} fn - callback function.
5242
+ * @return {Socket} for chaining.
5243
+ */
5320
5244
  send(msg, options, fn) {
5321
- this.sendPacket("message", msg, options, fn);
5245
+ this._sendPacket("message", msg, options, fn);
5322
5246
  return this;
5323
5247
  }
5324
5248
  /**
@@ -5330,7 +5254,7 @@ let Socket$1 = class Socket extends Emitter_1 {
5330
5254
  * @param {Function} fn - callback function.
5331
5255
  * @private
5332
5256
  */
5333
- sendPacket(type, data, options, fn) {
5257
+ _sendPacket(type, data, options, fn) {
5334
5258
  if ("function" === typeof data) {
5335
5259
  fn = data;
5336
5260
  data = undefined;
@@ -5360,7 +5284,7 @@ let Socket$1 = class Socket extends Emitter_1 {
5360
5284
  */
5361
5285
  close() {
5362
5286
  const close = () => {
5363
- this.onClose("forced close");
5287
+ this._onClose("forced close");
5364
5288
  this.transport.close();
5365
5289
  };
5366
5290
  const cleanupAndClose = () => {
@@ -5399,31 +5323,44 @@ let Socket$1 = class Socket extends Emitter_1 {
5399
5323
  *
5400
5324
  * @private
5401
5325
  */
5402
- onError(err) {
5403
- Socket.priorWebsocketSuccess = false;
5326
+ _onError(err) {
5327
+ SocketWithoutUpgrade.priorWebsocketSuccess = false;
5328
+ if (this.opts.tryAllTransports &&
5329
+ this.transports.length > 1 &&
5330
+ this.readyState === "opening") {
5331
+ this.transports.shift();
5332
+ return this._open();
5333
+ }
5404
5334
  this.emitReserved("error", err);
5405
- this.onClose("transport error", err);
5335
+ this._onClose("transport error", err);
5406
5336
  }
5407
5337
  /**
5408
5338
  * Called upon transport close.
5409
5339
  *
5410
5340
  * @private
5411
5341
  */
5412
- onClose(reason, description) {
5342
+ _onClose(reason, description) {
5413
5343
  if ("opening" === this.readyState ||
5414
5344
  "open" === this.readyState ||
5415
5345
  "closing" === this.readyState) {
5416
5346
  // clear timers
5417
- this.clearTimeoutFn(this.pingTimeoutTimer);
5347
+ this.clearTimeoutFn(this._pingTimeoutTimer);
5418
5348
  // stop event from firing again for transport
5419
5349
  this.transport.removeAllListeners("close");
5420
5350
  // ensure transport won't stay open
5421
5351
  this.transport.close();
5422
5352
  // ignore further transport communication
5423
5353
  this.transport.removeAllListeners();
5424
- if (typeof removeEventListener === "function") {
5425
- removeEventListener("beforeunload", this.beforeunloadEventListener, false);
5426
- removeEventListener("offline", this.offlineEventListener, false);
5354
+ if (withEventListeners) {
5355
+ if (this._beforeunloadEventListener) {
5356
+ removeEventListener("beforeunload", this._beforeunloadEventListener, false);
5357
+ }
5358
+ if (this._offlineEventListener) {
5359
+ const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
5360
+ if (i !== -1) {
5361
+ OFFLINE_EVENT_LISTENERS.splice(i, 1);
5362
+ }
5363
+ }
5427
5364
  }
5428
5365
  // set ready state
5429
5366
  this.readyState = "closed";
@@ -5434,27 +5371,199 @@ let Socket$1 = class Socket extends Emitter_1 {
5434
5371
  // clean buffers after, so users can still
5435
5372
  // grab the buffers on `close` event
5436
5373
  this.writeBuffer = [];
5437
- this.prevBufferLen = 0;
5374
+ this._prevBufferLen = 0;
5375
+ }
5376
+ }
5377
+ }
5378
+ SocketWithoutUpgrade.protocol = protocol$1;
5379
+ /**
5380
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
5381
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
5382
+ *
5383
+ * This class comes with an upgrade mechanism, which means that once the connection is established with the first
5384
+ * low-level transport, it will try to upgrade to a better transport.
5385
+ *
5386
+ * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
5387
+ *
5388
+ * @example
5389
+ * import { SocketWithUpgrade, WebSocket } from "engine.io-client";
5390
+ *
5391
+ * const socket = new SocketWithUpgrade({
5392
+ * transports: [WebSocket]
5393
+ * });
5394
+ *
5395
+ * socket.on("open", () => {
5396
+ * socket.send("hello");
5397
+ * });
5398
+ *
5399
+ * @see SocketWithoutUpgrade
5400
+ * @see Socket
5401
+ */
5402
+ class SocketWithUpgrade extends SocketWithoutUpgrade {
5403
+ constructor() {
5404
+ super(...arguments);
5405
+ this._upgrades = [];
5406
+ }
5407
+ onOpen() {
5408
+ super.onOpen();
5409
+ if ("open" === this.readyState && this.opts.upgrade) {
5410
+ for (let i = 0; i < this._upgrades.length; i++) {
5411
+ this._probe(this._upgrades[i]);
5412
+ }
5438
5413
  }
5439
5414
  }
5415
+ /**
5416
+ * Probes a transport.
5417
+ *
5418
+ * @param {String} name - transport name
5419
+ * @private
5420
+ */
5421
+ _probe(name) {
5422
+ let transport = this.createTransport(name);
5423
+ let failed = false;
5424
+ SocketWithoutUpgrade.priorWebsocketSuccess = false;
5425
+ const onTransportOpen = () => {
5426
+ if (failed)
5427
+ return;
5428
+ transport.send([{ type: "ping", data: "probe" }]);
5429
+ transport.once("packet", (msg) => {
5430
+ if (failed)
5431
+ return;
5432
+ if ("pong" === msg.type && "probe" === msg.data) {
5433
+ this.upgrading = true;
5434
+ this.emitReserved("upgrading", transport);
5435
+ if (!transport)
5436
+ return;
5437
+ SocketWithoutUpgrade.priorWebsocketSuccess =
5438
+ "websocket" === transport.name;
5439
+ this.transport.pause(() => {
5440
+ if (failed)
5441
+ return;
5442
+ if ("closed" === this.readyState)
5443
+ return;
5444
+ cleanup();
5445
+ this.setTransport(transport);
5446
+ transport.send([{ type: "upgrade" }]);
5447
+ this.emitReserved("upgrade", transport);
5448
+ transport = null;
5449
+ this.upgrading = false;
5450
+ this.flush();
5451
+ });
5452
+ }
5453
+ else {
5454
+ const err = new Error("probe error");
5455
+ // @ts-ignore
5456
+ err.transport = transport.name;
5457
+ this.emitReserved("upgradeError", err);
5458
+ }
5459
+ });
5460
+ };
5461
+ function freezeTransport() {
5462
+ if (failed)
5463
+ return;
5464
+ // Any callback called by transport should be ignored since now
5465
+ failed = true;
5466
+ cleanup();
5467
+ transport.close();
5468
+ transport = null;
5469
+ }
5470
+ // Handle any error that happens while probing
5471
+ const onerror = (err) => {
5472
+ const error = new Error("probe error: " + err);
5473
+ // @ts-ignore
5474
+ error.transport = transport.name;
5475
+ freezeTransport();
5476
+ this.emitReserved("upgradeError", error);
5477
+ };
5478
+ function onTransportClose() {
5479
+ onerror("transport closed");
5480
+ }
5481
+ // When the socket is closed while we're probing
5482
+ function onclose() {
5483
+ onerror("socket closed");
5484
+ }
5485
+ // When the socket is upgraded while we're probing
5486
+ function onupgrade(to) {
5487
+ if (transport && to.name !== transport.name) {
5488
+ freezeTransport();
5489
+ }
5490
+ }
5491
+ // Remove all listeners on the transport and on self
5492
+ const cleanup = () => {
5493
+ transport.removeListener("open", onTransportOpen);
5494
+ transport.removeListener("error", onerror);
5495
+ transport.removeListener("close", onTransportClose);
5496
+ this.off("close", onclose);
5497
+ this.off("upgrading", onupgrade);
5498
+ };
5499
+ transport.once("open", onTransportOpen);
5500
+ transport.once("error", onerror);
5501
+ transport.once("close", onTransportClose);
5502
+ this.once("close", onclose);
5503
+ this.once("upgrading", onupgrade);
5504
+ if (this._upgrades.indexOf("webtransport") !== -1 &&
5505
+ name !== "webtransport") {
5506
+ // favor WebTransport
5507
+ this.setTimeoutFn(() => {
5508
+ if (!failed) {
5509
+ transport.open();
5510
+ }
5511
+ }, 200);
5512
+ }
5513
+ else {
5514
+ transport.open();
5515
+ }
5516
+ }
5517
+ onHandshake(data) {
5518
+ this._upgrades = this._filterUpgrades(data.upgrades);
5519
+ super.onHandshake(data);
5520
+ }
5440
5521
  /**
5441
5522
  * Filters upgrades, returning only those matching client transports.
5442
5523
  *
5443
5524
  * @param {Array} upgrades - server upgrades
5444
5525
  * @private
5445
5526
  */
5446
- filterUpgrades(upgrades) {
5527
+ _filterUpgrades(upgrades) {
5447
5528
  const filteredUpgrades = [];
5448
- let i = 0;
5449
- const j = upgrades.length;
5450
- for (; i < j; i++) {
5529
+ for (let i = 0; i < upgrades.length; i++) {
5451
5530
  if (~this.transports.indexOf(upgrades[i]))
5452
5531
  filteredUpgrades.push(upgrades[i]);
5453
5532
  }
5454
5533
  return filteredUpgrades;
5455
5534
  }
5535
+ }
5536
+ /**
5537
+ * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
5538
+ * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
5539
+ *
5540
+ * This class comes with an upgrade mechanism, which means that once the connection is established with the first
5541
+ * low-level transport, it will try to upgrade to a better transport.
5542
+ *
5543
+ * @example
5544
+ * import { Socket } from "engine.io-client";
5545
+ *
5546
+ * const socket = new Socket();
5547
+ *
5548
+ * socket.on("open", () => {
5549
+ * socket.send("hello");
5550
+ * });
5551
+ *
5552
+ * @see SocketWithoutUpgrade
5553
+ * @see SocketWithUpgrade
5554
+ */
5555
+ let Socket$1 = class Socket extends SocketWithUpgrade {
5556
+ constructor(uri, opts = {}) {
5557
+ const o = typeof uri === "object" ? uri : opts;
5558
+ if (!o.transports ||
5559
+ (o.transports && typeof o.transports[0] === "string")) {
5560
+ o.transports = (o.transports || ["polling", "websocket", "webtransport"])
5561
+ .map((transportName) => transports[transportName])
5562
+ .filter((t) => !!t);
5563
+ }
5564
+ super(uri, o);
5565
+ }
5456
5566
  };
5457
- Socket$1.protocol = protocol$1;
5458
5567
 
5459
5568
  Socket$1.protocol;
5460
5569
 
@@ -6210,6 +6319,7 @@ class Socket extends Emitter_1 {
6210
6319
  * @return self
6211
6320
  */
6212
6321
  emit(ev, ...args) {
6322
+ var _a, _b, _c;
6213
6323
  if (RESERVED_EVENTS.hasOwnProperty(ev)) {
6214
6324
  throw new Error('"' + ev.toString() + '" is a reserved event name');
6215
6325
  }
@@ -6231,12 +6341,11 @@ class Socket extends Emitter_1 {
6231
6341
  this._registerAckCallback(id, ack);
6232
6342
  packet.id = id;
6233
6343
  }
6234
- const isTransportWritable = this.io.engine &&
6235
- this.io.engine.transport &&
6236
- this.io.engine.transport.writable;
6237
- const discardPacket = this.flags.volatile && (!isTransportWritable || !this.connected);
6344
+ const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.writable;
6345
+ const isConnected = this.connected && !((_c = this.io.engine) === null || _c === void 0 ? void 0 : _c._hasPingExpired());
6346
+ const discardPacket = this.flags.volatile && !isTransportWritable;
6238
6347
  if (discardPacket) ;
6239
- else if (this.connected) {
6348
+ else if (isConnected) {
6240
6349
  this.notifyOutgoingListeners(packet);
6241
6350
  this.packet(packet);
6242
6351
  }
@@ -6959,6 +7068,9 @@ class Manager extends Emitter_1 {
6959
7068
  if (!arguments.length)
6960
7069
  return this._reconnection;
6961
7070
  this._reconnection = !!v;
7071
+ if (!v) {
7072
+ this.skipReconnect = true;
7073
+ }
6962
7074
  return this;
6963
7075
  }
6964
7076
  reconnectionAttempts(v) {
@@ -7087,7 +7199,9 @@ class Manager extends Emitter_1 {
7087
7199
  this.emitReserved("open");
7088
7200
  // add new subs
7089
7201
  const socket = this.engine;
7090
- this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)), on(this.decoder, "decoded", this.ondecoded.bind(this)));
7202
+ this.subs.push(on(socket, "ping", this.onping.bind(this)), on(socket, "data", this.ondata.bind(this)), on(socket, "error", this.onerror.bind(this)), on(socket, "close", this.onclose.bind(this)),
7203
+ // @ts-ignore
7204
+ on(this.decoder, "decoded", this.ondecoded.bind(this)));
7091
7205
  }
7092
7206
  /**
7093
7207
  * Called upon a ping.
@@ -7193,8 +7307,6 @@ class Manager extends Emitter_1 {
7193
7307
  this.skipReconnect = true;
7194
7308
  this._reconnecting = false;
7195
7309
  this.onclose("forced close");
7196
- if (this.engine)
7197
- this.engine.close();
7198
7310
  }
7199
7311
  /**
7200
7312
  * Alias for close()
@@ -7205,12 +7317,18 @@ class Manager extends Emitter_1 {
7205
7317
  return this._close();
7206
7318
  }
7207
7319
  /**
7208
- * Called upon engine close.
7320
+ * Called when:
7321
+ *
7322
+ * - the low-level engine is closed
7323
+ * - the parser encountered a badly formatted packet
7324
+ * - all sockets are disconnected
7209
7325
  *
7210
7326
  * @private
7211
7327
  */
7212
7328
  onclose(reason, description) {
7329
+ var _a;
7213
7330
  this.cleanup();
7331
+ (_a = this.engine) === null || _a === void 0 ? void 0 : _a.close();
7214
7332
  this.backoff.reset();
7215
7333
  this._readyState = "closed";
7216
7334
  this.emitReserved("close", reason, description);