uniapp,h5

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. import { transports as DEFAULT_TRANSPORTS } from "./transports/index.js";
  2. import { installTimerFunctions, byteLength } from "./util.js";
  3. import { decode } from "./contrib/parseqs.js";
  4. import { parse } from "./contrib/parseuri.js";
  5. import { Emitter } from "@socket.io/component-emitter";
  6. import { protocol } from "engine.io-parser";
  7. import { createCookieJar, defaultBinaryType, nextTick, } from "./globals.node.js";
  8. const withEventListeners = typeof addEventListener === "function" &&
  9. typeof removeEventListener === "function";
  10. const OFFLINE_EVENT_LISTENERS = [];
  11. if (withEventListeners) {
  12. // within a ServiceWorker, any event handler for the 'offline' event must be added on the initial evaluation of the
  13. // script, so we create one single event listener here which will forward the event to the socket instances
  14. addEventListener("offline", () => {
  15. OFFLINE_EVENT_LISTENERS.forEach((listener) => listener());
  16. }, false);
  17. }
  18. /**
  19. * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
  20. * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
  21. *
  22. * This class comes without upgrade mechanism, which means that it will keep the first low-level transport that
  23. * successfully establishes the connection.
  24. *
  25. * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
  26. *
  27. * @example
  28. * import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
  29. *
  30. * const socket = new SocketWithoutUpgrade({
  31. * transports: [WebSocket]
  32. * });
  33. *
  34. * socket.on("open", () => {
  35. * socket.send("hello");
  36. * });
  37. *
  38. * @see SocketWithUpgrade
  39. * @see Socket
  40. */
  41. export class SocketWithoutUpgrade extends Emitter {
  42. /**
  43. * Socket constructor.
  44. *
  45. * @param {String|Object} uri - uri or options
  46. * @param {Object} opts - options
  47. */
  48. constructor(uri, opts) {
  49. super();
  50. this.binaryType = defaultBinaryType;
  51. this.writeBuffer = [];
  52. this._prevBufferLen = 0;
  53. this._pingInterval = -1;
  54. this._pingTimeout = -1;
  55. this._maxPayload = -1;
  56. /**
  57. * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
  58. * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
  59. */
  60. this._pingTimeoutTime = Infinity;
  61. if (uri && "object" === typeof uri) {
  62. opts = uri;
  63. uri = null;
  64. }
  65. if (uri) {
  66. const parsedUri = parse(uri);
  67. opts.hostname = parsedUri.host;
  68. opts.secure =
  69. parsedUri.protocol === "https" || parsedUri.protocol === "wss";
  70. opts.port = parsedUri.port;
  71. if (parsedUri.query)
  72. opts.query = parsedUri.query;
  73. }
  74. else if (opts.host) {
  75. opts.hostname = parse(opts.host).host;
  76. }
  77. installTimerFunctions(this, opts);
  78. this.secure =
  79. null != opts.secure
  80. ? opts.secure
  81. : typeof location !== "undefined" && "https:" === location.protocol;
  82. if (opts.hostname && !opts.port) {
  83. // if no port is specified manually, use the protocol default
  84. opts.port = this.secure ? "443" : "80";
  85. }
  86. this.hostname =
  87. opts.hostname ||
  88. (typeof location !== "undefined" ? location.hostname : "localhost");
  89. this.port =
  90. opts.port ||
  91. (typeof location !== "undefined" && location.port
  92. ? location.port
  93. : this.secure
  94. ? "443"
  95. : "80");
  96. this.transports = [];
  97. this._transportsByName = {};
  98. opts.transports.forEach((t) => {
  99. const transportName = t.prototype.name;
  100. this.transports.push(transportName);
  101. this._transportsByName[transportName] = t;
  102. });
  103. this.opts = Object.assign({
  104. path: "/engine.io",
  105. agent: false,
  106. withCredentials: false,
  107. upgrade: true,
  108. timestampParam: "t",
  109. rememberUpgrade: false,
  110. addTrailingSlash: true,
  111. rejectUnauthorized: true,
  112. perMessageDeflate: {
  113. threshold: 1024,
  114. },
  115. transportOptions: {},
  116. closeOnBeforeunload: false,
  117. }, opts);
  118. this.opts.path =
  119. this.opts.path.replace(/\/$/, "") +
  120. (this.opts.addTrailingSlash ? "/" : "");
  121. if (typeof this.opts.query === "string") {
  122. this.opts.query = decode(this.opts.query);
  123. }
  124. if (withEventListeners) {
  125. if (this.opts.closeOnBeforeunload) {
  126. // Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
  127. // ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
  128. // closed/reloaded)
  129. this._beforeunloadEventListener = () => {
  130. if (this.transport) {
  131. // silently close the transport
  132. this.transport.removeAllListeners();
  133. this.transport.close();
  134. }
  135. };
  136. addEventListener("beforeunload", this._beforeunloadEventListener, false);
  137. }
  138. if (this.hostname !== "localhost") {
  139. this._offlineEventListener = () => {
  140. this._onClose("transport close", {
  141. description: "network connection lost",
  142. });
  143. };
  144. OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener);
  145. }
  146. }
  147. if (this.opts.withCredentials) {
  148. this._cookieJar = createCookieJar();
  149. }
  150. this._open();
  151. }
  152. /**
  153. * Creates transport of the given type.
  154. *
  155. * @param {String} name - transport name
  156. * @return {Transport}
  157. * @private
  158. */
  159. createTransport(name) {
  160. const query = Object.assign({}, this.opts.query);
  161. // append engine.io protocol identifier
  162. query.EIO = protocol;
  163. // transport name
  164. query.transport = name;
  165. // session id if we already have one
  166. if (this.id)
  167. query.sid = this.id;
  168. const opts = Object.assign({}, this.opts, {
  169. query,
  170. socket: this,
  171. hostname: this.hostname,
  172. secure: this.secure,
  173. port: this.port,
  174. }, this.opts.transportOptions[name]);
  175. return new this._transportsByName[name](opts);
  176. }
  177. /**
  178. * Initializes transport to use and starts probe.
  179. *
  180. * @private
  181. */
  182. _open() {
  183. if (this.transports.length === 0) {
  184. // Emit error on next tick so it can be listened to
  185. this.setTimeoutFn(() => {
  186. this.emitReserved("error", "No transports available");
  187. }, 0);
  188. return;
  189. }
  190. const transportName = this.opts.rememberUpgrade &&
  191. SocketWithoutUpgrade.priorWebsocketSuccess &&
  192. this.transports.indexOf("websocket") !== -1
  193. ? "websocket"
  194. : this.transports[0];
  195. this.readyState = "opening";
  196. const transport = this.createTransport(transportName);
  197. transport.open();
  198. this.setTransport(transport);
  199. }
  200. /**
  201. * Sets the current transport. Disables the existing one (if any).
  202. *
  203. * @private
  204. */
  205. setTransport(transport) {
  206. if (this.transport) {
  207. this.transport.removeAllListeners();
  208. }
  209. // set up transport
  210. this.transport = transport;
  211. // set up transport listeners
  212. transport
  213. .on("drain", this._onDrain.bind(this))
  214. .on("packet", this._onPacket.bind(this))
  215. .on("error", this._onError.bind(this))
  216. .on("close", (reason) => this._onClose("transport close", reason));
  217. }
  218. /**
  219. * Called when connection is deemed open.
  220. *
  221. * @private
  222. */
  223. onOpen() {
  224. this.readyState = "open";
  225. SocketWithoutUpgrade.priorWebsocketSuccess =
  226. "websocket" === this.transport.name;
  227. this.emitReserved("open");
  228. this.flush();
  229. }
  230. /**
  231. * Handles a packet.
  232. *
  233. * @private
  234. */
  235. _onPacket(packet) {
  236. if ("opening" === this.readyState ||
  237. "open" === this.readyState ||
  238. "closing" === this.readyState) {
  239. this.emitReserved("packet", packet);
  240. // Socket is live - any packet counts
  241. this.emitReserved("heartbeat");
  242. switch (packet.type) {
  243. case "open":
  244. this.onHandshake(JSON.parse(packet.data));
  245. break;
  246. case "ping":
  247. this._sendPacket("pong");
  248. this.emitReserved("ping");
  249. this.emitReserved("pong");
  250. this._resetPingTimeout();
  251. break;
  252. case "error":
  253. const err = new Error("server error");
  254. // @ts-ignore
  255. err.code = packet.data;
  256. this._onError(err);
  257. break;
  258. case "message":
  259. this.emitReserved("data", packet.data);
  260. this.emitReserved("message", packet.data);
  261. break;
  262. }
  263. }
  264. else {
  265. }
  266. }
  267. /**
  268. * Called upon handshake completion.
  269. *
  270. * @param {Object} data - handshake obj
  271. * @private
  272. */
  273. onHandshake(data) {
  274. this.emitReserved("handshake", data);
  275. this.id = data.sid;
  276. this.transport.query.sid = data.sid;
  277. this._pingInterval = data.pingInterval;
  278. this._pingTimeout = data.pingTimeout;
  279. this._maxPayload = data.maxPayload;
  280. this.onOpen();
  281. // In case open handler closes socket
  282. if ("closed" === this.readyState)
  283. return;
  284. this._resetPingTimeout();
  285. }
  286. /**
  287. * Sets and resets ping timeout timer based on server pings.
  288. *
  289. * @private
  290. */
  291. _resetPingTimeout() {
  292. this.clearTimeoutFn(this._pingTimeoutTimer);
  293. const delay = this._pingInterval + this._pingTimeout;
  294. this._pingTimeoutTime = Date.now() + delay;
  295. this._pingTimeoutTimer = this.setTimeoutFn(() => {
  296. this._onClose("ping timeout");
  297. }, delay);
  298. if (this.opts.autoUnref) {
  299. this._pingTimeoutTimer.unref();
  300. }
  301. }
  302. /**
  303. * Called on `drain` event
  304. *
  305. * @private
  306. */
  307. _onDrain() {
  308. this.writeBuffer.splice(0, this._prevBufferLen);
  309. // setting prevBufferLen = 0 is very important
  310. // for example, when upgrading, upgrade packet is sent over,
  311. // and a nonzero prevBufferLen could cause problems on `drain`
  312. this._prevBufferLen = 0;
  313. if (0 === this.writeBuffer.length) {
  314. this.emitReserved("drain");
  315. }
  316. else {
  317. this.flush();
  318. }
  319. }
  320. /**
  321. * Flush write buffers.
  322. *
  323. * @private
  324. */
  325. flush() {
  326. if ("closed" !== this.readyState &&
  327. this.transport.writable &&
  328. !this.upgrading &&
  329. this.writeBuffer.length) {
  330. const packets = this._getWritablePackets();
  331. this.transport.send(packets);
  332. // keep track of current length of writeBuffer
  333. // splice writeBuffer and callbackBuffer on `drain`
  334. this._prevBufferLen = packets.length;
  335. this.emitReserved("flush");
  336. }
  337. }
  338. /**
  339. * Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
  340. * long-polling)
  341. *
  342. * @private
  343. */
  344. _getWritablePackets() {
  345. const shouldCheckPayloadSize = this._maxPayload &&
  346. this.transport.name === "polling" &&
  347. this.writeBuffer.length > 1;
  348. if (!shouldCheckPayloadSize) {
  349. return this.writeBuffer;
  350. }
  351. let payloadSize = 1; // first packet type
  352. for (let i = 0; i < this.writeBuffer.length; i++) {
  353. const data = this.writeBuffer[i].data;
  354. if (data) {
  355. payloadSize += byteLength(data);
  356. }
  357. if (i > 0 && payloadSize > this._maxPayload) {
  358. return this.writeBuffer.slice(0, i);
  359. }
  360. payloadSize += 2; // separator + packet type
  361. }
  362. return this.writeBuffer;
  363. }
  364. /**
  365. * Checks whether the heartbeat timer has expired but the socket has not yet been notified.
  366. *
  367. * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
  368. * `write()` method then the message would not be buffered by the Socket.IO client.
  369. *
  370. * @return {boolean}
  371. * @private
  372. */
  373. /* private */ _hasPingExpired() {
  374. if (!this._pingTimeoutTime)
  375. return true;
  376. const hasExpired = Date.now() > this._pingTimeoutTime;
  377. if (hasExpired) {
  378. this._pingTimeoutTime = 0;
  379. nextTick(() => {
  380. this._onClose("ping timeout");
  381. }, this.setTimeoutFn);
  382. }
  383. return hasExpired;
  384. }
  385. /**
  386. * Sends a message.
  387. *
  388. * @param {String} msg - message.
  389. * @param {Object} options.
  390. * @param {Function} fn - callback function.
  391. * @return {Socket} for chaining.
  392. */
  393. write(msg, options, fn) {
  394. this._sendPacket("message", msg, options, fn);
  395. return this;
  396. }
  397. /**
  398. * Sends a message. Alias of {@link Socket#write}.
  399. *
  400. * @param {String} msg - message.
  401. * @param {Object} options.
  402. * @param {Function} fn - callback function.
  403. * @return {Socket} for chaining.
  404. */
  405. send(msg, options, fn) {
  406. this._sendPacket("message", msg, options, fn);
  407. return this;
  408. }
  409. /**
  410. * Sends a packet.
  411. *
  412. * @param {String} type: packet type.
  413. * @param {String} data.
  414. * @param {Object} options.
  415. * @param {Function} fn - callback function.
  416. * @private
  417. */
  418. _sendPacket(type, data, options, fn) {
  419. if ("function" === typeof data) {
  420. fn = data;
  421. data = undefined;
  422. }
  423. if ("function" === typeof options) {
  424. fn = options;
  425. options = null;
  426. }
  427. if ("closing" === this.readyState || "closed" === this.readyState) {
  428. return;
  429. }
  430. options = options || {};
  431. options.compress = false !== options.compress;
  432. const packet = {
  433. type: type,
  434. data: data,
  435. options: options,
  436. };
  437. this.emitReserved("packetCreate", packet);
  438. this.writeBuffer.push(packet);
  439. if (fn)
  440. this.once("flush", fn);
  441. this.flush();
  442. }
  443. /**
  444. * Closes the connection.
  445. */
  446. close() {
  447. const close = () => {
  448. this._onClose("forced close");
  449. this.transport.close();
  450. };
  451. const cleanupAndClose = () => {
  452. this.off("upgrade", cleanupAndClose);
  453. this.off("upgradeError", cleanupAndClose);
  454. close();
  455. };
  456. const waitForUpgrade = () => {
  457. // wait for upgrade to finish since we can't send packets while pausing a transport
  458. this.once("upgrade", cleanupAndClose);
  459. this.once("upgradeError", cleanupAndClose);
  460. };
  461. if ("opening" === this.readyState || "open" === this.readyState) {
  462. this.readyState = "closing";
  463. if (this.writeBuffer.length) {
  464. this.once("drain", () => {
  465. if (this.upgrading) {
  466. waitForUpgrade();
  467. }
  468. else {
  469. close();
  470. }
  471. });
  472. }
  473. else if (this.upgrading) {
  474. waitForUpgrade();
  475. }
  476. else {
  477. close();
  478. }
  479. }
  480. return this;
  481. }
  482. /**
  483. * Called upon transport error
  484. *
  485. * @private
  486. */
  487. _onError(err) {
  488. SocketWithoutUpgrade.priorWebsocketSuccess = false;
  489. if (this.opts.tryAllTransports &&
  490. this.transports.length > 1 &&
  491. this.readyState === "opening") {
  492. this.transports.shift();
  493. return this._open();
  494. }
  495. this.emitReserved("error", err);
  496. this._onClose("transport error", err);
  497. }
  498. /**
  499. * Called upon transport close.
  500. *
  501. * @private
  502. */
  503. _onClose(reason, description) {
  504. if ("opening" === this.readyState ||
  505. "open" === this.readyState ||
  506. "closing" === this.readyState) {
  507. // clear timers
  508. this.clearTimeoutFn(this._pingTimeoutTimer);
  509. // stop event from firing again for transport
  510. this.transport.removeAllListeners("close");
  511. // ensure transport won't stay open
  512. this.transport.close();
  513. // ignore further transport communication
  514. this.transport.removeAllListeners();
  515. if (withEventListeners) {
  516. if (this._beforeunloadEventListener) {
  517. removeEventListener("beforeunload", this._beforeunloadEventListener, false);
  518. }
  519. if (this._offlineEventListener) {
  520. const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener);
  521. if (i !== -1) {
  522. OFFLINE_EVENT_LISTENERS.splice(i, 1);
  523. }
  524. }
  525. }
  526. // set ready state
  527. this.readyState = "closed";
  528. // clear session id
  529. this.id = null;
  530. // emit close event
  531. this.emitReserved("close", reason, description);
  532. // clean buffers after, so users can still
  533. // grab the buffers on `close` event
  534. this.writeBuffer = [];
  535. this._prevBufferLen = 0;
  536. }
  537. }
  538. }
  539. SocketWithoutUpgrade.protocol = protocol;
  540. /**
  541. * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
  542. * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
  543. *
  544. * This class comes with an upgrade mechanism, which means that once the connection is established with the first
  545. * low-level transport, it will try to upgrade to a better transport.
  546. *
  547. * In order to allow tree-shaking, there are no transports included, that's why the `transports` option is mandatory.
  548. *
  549. * @example
  550. * import { SocketWithUpgrade, WebSocket } from "engine.io-client";
  551. *
  552. * const socket = new SocketWithUpgrade({
  553. * transports: [WebSocket]
  554. * });
  555. *
  556. * socket.on("open", () => {
  557. * socket.send("hello");
  558. * });
  559. *
  560. * @see SocketWithoutUpgrade
  561. * @see Socket
  562. */
  563. export class SocketWithUpgrade extends SocketWithoutUpgrade {
  564. constructor() {
  565. super(...arguments);
  566. this._upgrades = [];
  567. }
  568. onOpen() {
  569. super.onOpen();
  570. if ("open" === this.readyState && this.opts.upgrade) {
  571. for (let i = 0; i < this._upgrades.length; i++) {
  572. this._probe(this._upgrades[i]);
  573. }
  574. }
  575. }
  576. /**
  577. * Probes a transport.
  578. *
  579. * @param {String} name - transport name
  580. * @private
  581. */
  582. _probe(name) {
  583. let transport = this.createTransport(name);
  584. let failed = false;
  585. SocketWithoutUpgrade.priorWebsocketSuccess = false;
  586. const onTransportOpen = () => {
  587. if (failed)
  588. return;
  589. transport.send([{ type: "ping", data: "probe" }]);
  590. transport.once("packet", (msg) => {
  591. if (failed)
  592. return;
  593. if ("pong" === msg.type && "probe" === msg.data) {
  594. this.upgrading = true;
  595. this.emitReserved("upgrading", transport);
  596. if (!transport)
  597. return;
  598. SocketWithoutUpgrade.priorWebsocketSuccess =
  599. "websocket" === transport.name;
  600. this.transport.pause(() => {
  601. if (failed)
  602. return;
  603. if ("closed" === this.readyState)
  604. return;
  605. cleanup();
  606. this.setTransport(transport);
  607. transport.send([{ type: "upgrade" }]);
  608. this.emitReserved("upgrade", transport);
  609. transport = null;
  610. this.upgrading = false;
  611. this.flush();
  612. });
  613. }
  614. else {
  615. const err = new Error("probe error");
  616. // @ts-ignore
  617. err.transport = transport.name;
  618. this.emitReserved("upgradeError", err);
  619. }
  620. });
  621. };
  622. function freezeTransport() {
  623. if (failed)
  624. return;
  625. // Any callback called by transport should be ignored since now
  626. failed = true;
  627. cleanup();
  628. transport.close();
  629. transport = null;
  630. }
  631. // Handle any error that happens while probing
  632. const onerror = (err) => {
  633. const error = new Error("probe error: " + err);
  634. // @ts-ignore
  635. error.transport = transport.name;
  636. freezeTransport();
  637. this.emitReserved("upgradeError", error);
  638. };
  639. function onTransportClose() {
  640. onerror("transport closed");
  641. }
  642. // When the socket is closed while we're probing
  643. function onclose() {
  644. onerror("socket closed");
  645. }
  646. // When the socket is upgraded while we're probing
  647. function onupgrade(to) {
  648. if (transport && to.name !== transport.name) {
  649. freezeTransport();
  650. }
  651. }
  652. // Remove all listeners on the transport and on self
  653. const cleanup = () => {
  654. transport.removeListener("open", onTransportOpen);
  655. transport.removeListener("error", onerror);
  656. transport.removeListener("close", onTransportClose);
  657. this.off("close", onclose);
  658. this.off("upgrading", onupgrade);
  659. };
  660. transport.once("open", onTransportOpen);
  661. transport.once("error", onerror);
  662. transport.once("close", onTransportClose);
  663. this.once("close", onclose);
  664. this.once("upgrading", onupgrade);
  665. if (this._upgrades.indexOf("webtransport") !== -1 &&
  666. name !== "webtransport") {
  667. // favor WebTransport
  668. this.setTimeoutFn(() => {
  669. if (!failed) {
  670. transport.open();
  671. }
  672. }, 200);
  673. }
  674. else {
  675. transport.open();
  676. }
  677. }
  678. onHandshake(data) {
  679. this._upgrades = this._filterUpgrades(data.upgrades);
  680. super.onHandshake(data);
  681. }
  682. /**
  683. * Filters upgrades, returning only those matching client transports.
  684. *
  685. * @param {Array} upgrades - server upgrades
  686. * @private
  687. */
  688. _filterUpgrades(upgrades) {
  689. const filteredUpgrades = [];
  690. for (let i = 0; i < upgrades.length; i++) {
  691. if (~this.transports.indexOf(upgrades[i]))
  692. filteredUpgrades.push(upgrades[i]);
  693. }
  694. return filteredUpgrades;
  695. }
  696. }
  697. /**
  698. * This class provides a WebSocket-like interface to connect to an Engine.IO server. The connection will be established
  699. * with one of the available low-level transports, like HTTP long-polling, WebSocket or WebTransport.
  700. *
  701. * This class comes with an upgrade mechanism, which means that once the connection is established with the first
  702. * low-level transport, it will try to upgrade to a better transport.
  703. *
  704. * @example
  705. * import { Socket } from "engine.io-client";
  706. *
  707. * const socket = new Socket();
  708. *
  709. * socket.on("open", () => {
  710. * socket.send("hello");
  711. * });
  712. *
  713. * @see SocketWithoutUpgrade
  714. * @see SocketWithUpgrade
  715. */
  716. export class Socket extends SocketWithUpgrade {
  717. constructor(uri, opts = {}) {
  718. const o = typeof uri === "object" ? uri : opts;
  719. if (!o.transports ||
  720. (o.transports && typeof o.transports[0] === "string")) {
  721. o.transports = (o.transports || ["polling", "websocket", "webtransport"])
  722. .map((transportName) => DEFAULT_TRANSPORTS[transportName])
  723. .filter((t) => !!t);
  724. }
  725. super(uri, o);
  726. }
  727. }