Skip to content

Commit 3fa9db5

Browse files
committed
net: server add asyncDispose
1 parent 260deef commit 3fa9db5

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

doc/api/net.md

Lines changed: 11 additions & 0 deletions
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

Lines changed: 10 additions & 1 deletion
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
} = primordials;
3941

4042
const EventEmitter = require('events');
@@ -111,7 +113,7 @@ const {
111113
} = require('internal/errors');
112114
const { isUint8Array } = require('internal/util/types');
113115
const { queueMicrotask } = require('internal/process/task_queues');
114-
const { kEmptyObject, guessHandleType } = require('internal/util');
116+
const { kEmptyObject, guessHandleType, promisify } = require('internal/util');
115117
const {
116118
validateAbortSignal,
117119
validateBoolean,
@@ -2241,6 +2243,13 @@ Server.prototype.close = function(cb) {
22412243
return this;
22422244
};
22432245

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

Lines changed: 30 additions & 0 deletions
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)