Skip to content

Commit f892163

Browse files
atlowChemiruyadorno
authored andcommittedSep 16, 2023
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 573eb4b commit f892163

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
@@ -355,6 +355,17 @@ The optional `callback` will be called once the `'close'` event occurs. Unlike
355355
that event, it will be called with an `Error` as its only argument if the server
356356
was not open when it was closed.
357357

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

360371
<!-- YAML

‎lib/net.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
ArrayPrototypePush,
2828
Boolean,
2929
FunctionPrototypeBind,
30+
FunctionPrototypeCall,
3031
MathMax,
3132
Number,
3233
NumberIsNaN,
@@ -35,6 +36,7 @@ const {
3536
ObjectSetPrototypeOf,
3637
Symbol,
3738
ObjectCreate,
39+
SymbolAsyncDispose,
3840
} = primordials;
3941

4042
const EventEmitter = require('events');
@@ -110,7 +112,7 @@ const {
110112
} = require('internal/errors');
111113
const { isUint8Array } = require('internal/util/types');
112114
const { queueMicrotask } = require('internal/process/task_queues');
113-
const { kEmptyObject } = require('internal/util');
115+
const { kEmptyObject, promisify } = require('internal/util');
114116
const {
115117
validateAbortSignal,
116118
validateBoolean,
@@ -2191,6 +2193,13 @@ Server.prototype.close = function(cb) {
21912193
return this;
21922194
};
21932195

2196+
Server.prototype[SymbolAsyncDispose] = async function() {
2197+
if (!this._handle) {
2198+
return;
2199+
}
2200+
return FunctionPrototypeCall(promisify(this.close), this);
2201+
};
2202+
21942203
Server.prototype._emitCloseIfDrained = function() {
21952204
debug('SERVER _emitCloseIfDrained');
21962205

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)
Please sign in to comment.