From c1eba5886f4501aba59571dadbd22009bde16ddb Mon Sep 17 00:00:00 2001 From: Ciro Spaciari Date: Fri, 6 Dec 2024 16:10:33 -0800 Subject: [PATCH] fix(net) signal should destroy the connection and propagate the error properly (#15624) --- src/js/node/net.ts | 16 +++++++++++++-- test/js/node/net/node-net.test.ts | 33 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/js/node/net.ts b/src/js/node/net.ts index c06c476816..277900dd99 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -99,6 +99,15 @@ function finishSocket(hasError) { detachSocket(this); this.emit("close", hasError); } + +function destroyNT(self, err) { + self.destroy(err); +} +function destroyWhenAborted(err) { + if (!this.destroyed) { + this.destroy(err.target.reason); + } +} // Provide a better error message when we call end() as a result // of the other side sending a FIN. The standard 'write after end' // is overly vague, and makes it seem like the user's code is to blame. @@ -479,9 +488,12 @@ const Socket = (function (InternalSocket) { }, }; } - if (signal) { - signal.addEventListener("abort", () => this.destroy()); + if (signal.aborted) { + process.nextTick(destroyNT, this, signal.reason); + } else { + signal.addEventListener("abort", destroyWhenAborted.bind(this)); + } } } diff --git a/test/js/node/net/node-net.test.ts b/test/js/node/net/node-net.test.ts index ef56deafe9..ebf70d065b 100644 --- a/test/js/node/net/node-net.test.ts +++ b/test/js/node/net/node-net.test.ts @@ -563,6 +563,39 @@ it("should not hang after destroy", async () => { } }); +it("should trigger error when aborted even if connection failed #13126", async () => { + const signal = AbortSignal.timeout(100); + const socket = createConnection({ + host: "example.com", + port: 999, + signal: signal, + }); + const { promise, resolve, reject } = Promise.withResolvers(); + + socket.on("connect", reject); + socket.on("error", resolve); + + const err = (await promise) as Error; + expect(err.name).toBe("TimeoutError"); +}); + +it("should trigger error when aborted even if connection failed, and the signal is already aborted #13126", async () => { + const signal = AbortSignal.timeout(1); + await Bun.sleep(10); + const socket = createConnection({ + host: "example.com", + port: 999, + signal: signal, + }); + const { promise, resolve, reject } = Promise.withResolvers(); + + socket.on("connect", reject); + socket.on("error", resolve); + + const err = (await promise) as Error; + expect(err.name).toBe("TimeoutError"); +}); + it.if(isWindows)( "should work with named pipes", async () => {