Skip to content

Commit cfa69bd

Browse files
atlowChemijuanarbol
authored andcommitted
net: server add asyncDispose
PR-URL: #48717 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent c47b2cb commit cfa69bd

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

doc/api/net.md

+11
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,17 @@ The optional `callback` will be called once the `'close'` event occurs. Unlike
357357
that event, it will be called with an `Error` as its only argument if the server
358358
was not open when it was closed.
359359

360+
### `server[Symbol.asyncDispose]()`
361+
362+
<!-- YAML
363+
added: REPLACEME
364+
-->
365+
366+
> Stability: 1 - Experimental
367+
368+
Calls [`server.close()`][] and returns a promise that fulfills when the
369+
server has closed.
370+
360371
### `server.getConnections(callback)`
361372

362373
<!-- YAML

lib/net.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ const {
2828
ArrayPrototypePush,
2929
Boolean,
3030
FunctionPrototypeBind,
31+
FunctionPrototypeCall,
3132
MathMax,
3233
Number,
3334
NumberIsNaN,
3435
NumberParseInt,
3536
ObjectDefineProperty,
3637
ObjectSetPrototypeOf,
3738
Symbol,
39+
SymbolAsyncDispose,
3840
SymbolDispose,
3941
} = primordials;
4042

@@ -112,7 +114,7 @@ const {
112114
} = require('internal/errors');
113115
const { isUint8Array } = require('internal/util/types');
114116
const { queueMicrotask } = require('internal/process/task_queues');
115-
const { kEmptyObject, guessHandleType } = require('internal/util');
117+
const { kEmptyObject, guessHandleType, promisify } = require('internal/util');
116118
const {
117119
validateAbortSignal,
118120
validateBoolean,
@@ -2243,6 +2245,13 @@ Server.prototype.close = function(cb) {
22432245
return this;
22442246
};
22452247

2248+
Server.prototype[SymbolAsyncDispose] = async function() {
2249+
if (!this._handle) {
2250+
return;
2251+
}
2252+
return FunctionPrototypeCall(promisify(this.close), this);
2253+
};
2254+
22462255
Server.prototype._emitCloseIfDrained = function() {
22472256
debug('SERVER _emitCloseIfDrained');
22482257

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as common from '../common/index.mjs';
2+
import assert from 'node:assert';
3+
import net from 'node:net';
4+
import { describe, it } from 'node:test';
5+
6+
describe('net.Server[Symbol.asyncDispose]()', () => {
7+
it('should close the server', async () => {
8+
const server = net.createServer();
9+
const timeoutRef = setTimeout(common.mustNotCall(), 2 ** 31 - 1);
10+
11+
server.listen(0, common.mustCall(async () => {
12+
await server[Symbol.asyncDispose]().then(common.mustCall());
13+
assert.strictEqual(server.address(), null);
14+
clearTimeout(timeoutRef);
15+
}));
16+
17+
server.on('close', common.mustCall());
18+
});
19+
20+
it('should resolve even if the server is already closed', async () => {
21+
const server = net.createServer();
22+
const timeoutRef = setTimeout(common.mustNotCall(), 2 ** 31 - 1);
23+
24+
server.listen(0, common.mustCall(async () => {
25+
await server[Symbol.asyncDispose]().then(common.mustCall());
26+
await server[Symbol.asyncDispose]().then(common.mustCall(), common.mustNotCall());
27+
clearTimeout(timeoutRef);
28+
}));
29+
});
30+
});

0 commit comments

Comments
 (0)