diff --git a/cli/tests/unit/net_test.ts b/cli/tests/unit/net_test.ts index 2a98b5e26f3e0a..a6803e20447c82 100644 --- a/cli/tests/unit/net_test.ts +++ b/cli/tests/unit/net_test.ts @@ -1224,7 +1224,7 @@ Deno.test({ }); Deno.test({ - ignore: Deno.build.os === "linux", + ignore: Deno.build.os === "linux" || Deno.build.os === "darwin", permissions: { net: true }, }, function netTcpListenReusePortDoesNothing() { const listener1 = Deno.listen({ port: 4003, reusePort: true }); diff --git a/ext/net/01_net.js b/ext/net/01_net.js index f2bf5e7dfa2c64..3256035a56ec26 100644 --- a/ext/net/01_net.js +++ b/ext/net/01_net.js @@ -420,12 +420,20 @@ class Datagram { const listenOptionApiName = Symbol("listenOptionApiName"); function listen(args) { + return listenInternal(args, true); +} + +function listenInternal(args, checkUnstable = true) { switch (args.transport ?? "tcp") { case "tcp": { - const { 0: rid, 1: addr } = ops.op_net_listen_tcp({ - hostname: args.hostname ?? "0.0.0.0", - port: Number(args.port), - }, args.reusePort); + const { 0: rid, 1: addr } = ops.op_net_listen_tcp( + { + hostname: args.hostname ?? "0.0.0.0", + port: Number(args.port), + }, + args.reusePort, + checkUnstable, + ); addr.transport = "tcp"; return new Listener(rid, addr); } @@ -511,6 +519,7 @@ export { Datagram, listen, Listener, + listenInternal, listenOptionApiName, resolveDns, shutdown, diff --git a/ext/net/ops.rs b/ext/net/ops.rs index 5738620f8cf72c..f2ab49c81f683f 100644 --- a/ext/net/ops.rs +++ b/ext/net/ops.rs @@ -356,11 +356,13 @@ pub fn op_net_listen_tcp( state: &mut OpState, #[serde] addr: IpAddr, reuse_port: bool, + check_unstable: bool, ) -> Result<(ResourceId, IpAddr), AnyError> where NP: NetPermissions + 'static, { - if reuse_port { + // Do not check for unstable if used by internal Node code, + if check_unstable && reuse_port { super::check_unstable(state, "Deno.listen({ reusePort: true })"); } state @@ -378,7 +380,7 @@ where #[cfg(not(windows))] socket.set_reuse_address(true)?; if reuse_port { - #[cfg(target_os = "linux")] + #[cfg(not(windows))] socket.set_reuse_port(true)?; } let socket_addr = socket2::SockAddr::from(addr); diff --git a/ext/node/polyfills/internal_binding/tcp_wrap.ts b/ext/node/polyfills/internal_binding/tcp_wrap.ts index 3725b632507b2c..21dfbf0eadfc1f 100644 --- a/ext/node/polyfills/internal_binding/tcp_wrap.ts +++ b/ext/node/polyfills/internal_binding/tcp_wrap.ts @@ -45,6 +45,7 @@ import { INITIAL_ACCEPT_BACKOFF_DELAY, MAX_ACCEPT_BACKOFF_DELAY, } from "ext:deno_node/internal_binding/_listen.ts"; +import { listenInternal } from "ext:deno_net/01_net.js"; /** The type of TCP socket. */ enum socketType { @@ -204,12 +205,13 @@ export class TCP extends ConnectionWrap { hostname: this.#address!, port: this.#port!, transport: "tcp" as const, + reusePort: true, }; let listener; try { - listener = Deno.listen(listenOptions); + listener = listenInternal(listenOptions, false); } catch (e) { if (e instanceof Deno.errors.AddrInUse) { return codeMap.get("EADDRINUSE")!;