From 111cdb5f08e07bba66bd981e2b3a81991d3bee7a Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Thu, 1 Oct 2026 23:28:45 +0700 Subject: [PATCH] fix(sio-client): reset the flags once a packet is queued When the "retries" option is set, emit() copies the current flags (compress, timeout) into the queued packet but did not clear them, so they were applied to the next emitted packets too, as long as the queue was not drained (socket not connected yet, or a previous packet still waiting for its acknowledgement). --- packages/socket.io-client/lib/socket.ts | 1 + packages/socket.io-client/test/retry.ts | 54 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/packages/socket.io-client/lib/socket.ts b/packages/socket.io-client/lib/socket.ts index cc8ff87df0..13c0ed97ce 100644 --- a/packages/socket.io-client/lib/socket.ts +++ b/packages/socket.io-client/lib/socket.ts @@ -543,6 +543,7 @@ export class Socket< args, flags: Object.assign({ fromQueue: true }, this.flags), }; + this.flags = {}; args.push((err, ...responseArgs) => { if (packet !== this._queue[0]) { diff --git a/packages/socket.io-client/test/retry.ts b/packages/socket.io-client/test/retry.ts index 9ceca208b1..536c208518 100644 --- a/packages/socket.io-client/test/retry.ts +++ b/packages/socket.io-client/test/retry.ts @@ -146,4 +146,58 @@ describe("retry", () => { }, 100); }); }); + + it("should not apply the flags of a queued packet to the next one", () => { + return wrap((done) => { + const socket = io(BASE_URL, { + forceNew: true, + retries: 3, + ackTimeout: 50, + }); + + const compressFlags: boolean[] = []; + + socket.io.engine.on("packetCreate", ({ type, data, options }) => { + if (type === "message" && data.startsWith("2")) { + compressFlags.push(options.compress); + } + }); + + // the socket is not connected yet, so both packets are queued + socket.compress(false).emit("echo", 1); + socket.emit("echo", 2, () => { + expect(compressFlags).to.eql([false, true]); + + success(done, socket); + }); + }); + }); + + it("should not apply the flags of a pending packet to the next one", () => { + return wrap((done) => { + const socket = io(BASE_URL, { + forceNew: true, + retries: 3, + ackTimeout: 50, + }); + + const compressFlags: boolean[] = []; + + socket.io.engine.on("packetCreate", ({ type, data, options }) => { + if (type === "message" && data.startsWith("2")) { + compressFlags.push(options.compress); + } + }); + + socket.on("connect", () => { + socket.emit("echo", 1); + socket.compress(false).emit("echo", 2); + socket.emit("echo", 3, () => { + expect(compressFlags).to.eql([true, false, true]); + + success(done, socket); + }); + }); + }); + }); });