Skip to content

Commit d29199e

Browse files
aduh95danielleadams
authored andcommitted
quic: refactor to use more primordials
PR-URL: #36211 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 617cb58 commit d29199e

File tree

1 file changed

+93
-63
lines changed

1 file changed

+93
-63
lines changed

lib/internal/quic/core.js

+93-63
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,23 @@ assertCrypto();
1111

1212
const {
1313
ArrayFrom,
14+
ArrayPrototypePush,
1415
BigInt64Array,
1516
Boolean,
1617
Error,
18+
FunctionPrototypeBind,
19+
FunctionPrototypeCall,
1720
Map,
1821
Number,
1922
Promise,
2023
PromiseAll,
24+
PromisePrototypeThen,
25+
PromisePrototypeCatch,
26+
PromisePrototypeFinally,
2127
PromiseReject,
2228
PromiseResolve,
23-
Set,
29+
ReflectApply,
30+
SafeSet,
2431
Symbol,
2532
SymbolFor,
2633
} = primordials;
@@ -302,22 +309,25 @@ function onSessionClose(code, family, silent, statelessReset) {
302309
// being requested. It is only called if the 'clientHelloHandler' option is
303310
// specified on listen().
304311
function onSessionClientHello(alpn, servername, ciphers) {
305-
this[owner_symbol][kClientHello](alpn, servername, ciphers)
306-
.then((context) => {
312+
PromisePrototypeThen(
313+
this[owner_symbol][kClientHello](alpn, servername, ciphers),
314+
(context) => {
307315
if (context !== undefined && !context?.context)
308316
throw new ERR_INVALID_ARG_TYPE('context', 'SecureContext', context);
309317
this.onClientHelloDone(context?.context);
310-
})
311-
.catch((error) => this[owner_symbol].destroy(error));
318+
},
319+
(error) => this[owner_symbol].destroy(error)
320+
);
312321
}
313322

314323
// This callback is only ever invoked for QuicServerSession instances,
315324
// and is used to trigger OCSP request processing when needed. The
316325
// user callback must invoke .onCertDone() in order for the
317326
// TLS handshake to continue.
318327
function onSessionCert(servername) {
319-
this[owner_symbol][kHandleOcsp](servername)
320-
.then((data) => {
328+
PromisePrototypeThen(
329+
this[owner_symbol][kHandleOcsp](servername),
330+
(data) => {
321331
if (data !== undefined) {
322332
if (typeof data === 'string')
323333
data = Buffer.from(data);
@@ -329,17 +339,20 @@ function onSessionCert(servername) {
329339
}
330340
}
331341
this.onCertDone(data);
332-
})
333-
.catch((error) => this[owner_symbol].destroy(error));
342+
},
343+
(error) => this[owner_symbol].destroy(error)
344+
);
334345
}
335346

336347
// This callback is only ever invoked for QuicClientSession instances,
337348
// and is used to deliver the OCSP response as provided by the server.
338349
// If the requestOCSP configuration option is false, this will never
339350
// be called.
340351
function onSessionStatus(data) {
341-
this[owner_symbol][kHandleOcsp](data)
342-
.catch((error) => this[owner_symbol].destroy(error));
352+
PromisePrototypeCatch(
353+
this[owner_symbol][kHandleOcsp](data),
354+
(error) => this[owner_symbol].destroy(error)
355+
);
343356
}
344357

345358
// Called by the C++ internals when the TLS handshake is completed.
@@ -369,12 +382,13 @@ function onSessionHandshake(
369382
// resumption and 0RTT.
370383
function onSessionTicket(sessionTicket, transportParams) {
371384
if (this[owner_symbol]) {
372-
process.nextTick(
373-
emit.bind(
374-
this[owner_symbol],
375-
'sessionTicket',
376-
sessionTicket,
377-
transportParams));
385+
process.nextTick(FunctionPrototypeBind(
386+
emit,
387+
this[owner_symbol],
388+
'sessionTicket',
389+
sessionTicket,
390+
transportParams
391+
));
378392
}
379393
}
380394

@@ -384,13 +398,14 @@ function onSessionTicket(sessionTicket, transportParams) {
384398
function onSessionPathValidation(res, local, remote) {
385399
const session = this[owner_symbol];
386400
if (session) {
387-
process.nextTick(
388-
emit.bind(
389-
session,
390-
'pathValidation',
391-
res === NGTCP2_PATH_VALIDATION_RESULT_FAILURE ? 'failure' : 'success',
392-
local,
393-
remote));
401+
process.nextTick(FunctionPrototypeBind(
402+
emit,
403+
session,
404+
'pathValidation',
405+
res === NGTCP2_PATH_VALIDATION_RESULT_FAILURE ? 'failure' : 'success',
406+
local,
407+
remote
408+
));
394409
}
395410
}
396411

@@ -486,7 +501,7 @@ function onStreamHeaders(id, headers, kind, push_id) {
486501
// When a stream is flow control blocked, causes a blocked event
487502
// to be emitted. This is a purely informational event.
488503
function onStreamBlocked() {
489-
process.nextTick(emit.bind(this[owner_symbol], 'blocked'));
504+
process.nextTick(FunctionPrototypeBind(emit, this[owner_symbol], 'blocked'));
490505
}
491506

492507
// Register the callbacks with the QUIC internal binding.
@@ -543,14 +558,17 @@ function addressOrLocalhost(address, type) {
543558
}
544559

545560
function deferredClosePromise(state) {
546-
return state.closePromise = new Promise((resolve, reject) => {
547-
state.closePromiseResolve = resolve;
548-
state.closePromiseReject = reject;
549-
}).finally(() => {
550-
state.closePromise = undefined;
551-
state.closePromiseResolve = undefined;
552-
state.closePromiseReject = undefined;
553-
});
561+
return state.closePromise = PromisePrototypeFinally(
562+
new Promise((resolve, reject) => {
563+
state.closePromiseResolve = resolve;
564+
state.closePromiseReject = reject;
565+
}),
566+
() => {
567+
state.closePromise = undefined;
568+
state.closePromiseResolve = undefined;
569+
state.closePromiseReject = undefined;
570+
}
571+
);
554572
}
555573

556574
async function resolvePreferredAddress(lookup, preferredAddress) {
@@ -640,7 +658,7 @@ class QuicEndpoint {
640658
if (state.bindPromise !== undefined)
641659
return state.bindPromise;
642660

643-
return state.bindPromise = this[kBind]().finally(() => {
661+
return state.bindPromise = PromisePrototypeFinally(this[kBind](), () => {
644662
state.bindPromise = undefined;
645663
});
646664
}
@@ -899,7 +917,7 @@ class QuicSocket extends EventEmitter {
899917
closePromiseResolve: undefined,
900918
closePromiseReject: undefined,
901919
defaultEncoding: undefined,
902-
endpoints: new Set(),
920+
endpoints: new SafeSet(),
903921
highWaterMark: undefined,
904922
listenPending: false,
905923
listenPromise: undefined,
@@ -908,7 +926,7 @@ class QuicSocket extends EventEmitter {
908926
clientHelloHandler: undefined,
909927
server: undefined,
910928
serverSecureContext: undefined,
911-
sessions: new Set(),
929+
sessions: new SafeSet(),
912930
state: kSocketUnbound,
913931
sharedState: undefined,
914932
stats: undefined,
@@ -1048,9 +1066,12 @@ class QuicSocket extends EventEmitter {
10481066
if (state.bindPromise !== undefined)
10491067
return state.bindPromise;
10501068

1051-
return state.bindPromise = this[kBind](options).finally(() => {
1052-
state.bindPromise = undefined;
1053-
});
1069+
return state.bindPromise = PromisePrototypeFinally(
1070+
this[kBind](options),
1071+
() => {
1072+
state.bindPromise = undefined;
1073+
}
1074+
);
10541075
}
10551076

10561077
async [kBind](options) {
@@ -1074,7 +1095,7 @@ class QuicSocket extends EventEmitter {
10741095

10751096
const binds = [];
10761097
for (const endpoint of state.endpoints)
1077-
binds.push(endpoint.bind({ signal }));
1098+
ArrayPrototypePush(binds, endpoint.bind({ signal }));
10781099

10791100
await PromiseAll(binds);
10801101

@@ -1169,9 +1190,12 @@ class QuicSocket extends EventEmitter {
11691190
if (state.listenPromise !== undefined)
11701191
return state.listenPromise;
11711192

1172-
return state.listenPromise = this[kListen](options).finally(() => {
1173-
state.listenPromise = undefined;
1174-
});
1193+
return state.listenPromise = PromisePrototypeFinally(
1194+
this[kListen](options),
1195+
() => {
1196+
state.listenPromise = undefined;
1197+
}
1198+
);
11751199
}
11761200

11771201
async [kListen](options) {
@@ -1388,8 +1412,9 @@ class QuicSocket extends EventEmitter {
13881412
// Otherwise, loop through each of the known sessions and close them.
13891413
const reqs = [promise];
13901414
for (const session of state.sessions) {
1391-
reqs.push(session.close()
1392-
.catch((error) => this.destroy(error)));
1415+
ArrayPrototypePush(reqs,
1416+
PromisePrototypeCatch(session.close(),
1417+
(error) => this.destroy(error)));
13931418
}
13941419
return PromiseAll(reqs);
13951420
}
@@ -1441,11 +1466,11 @@ class QuicSocket extends EventEmitter {
14411466
if (error) {
14421467
if (typeof state.closePromiseReject === 'function')
14431468
state.closePromiseReject(error);
1444-
process.nextTick(emit.bind(this, 'error', error));
1469+
process.nextTick(FunctionPrototypeBind(emit, this, 'error', error));
14451470
} else if (typeof state.closePromiseResolve === 'function') {
14461471
state.closePromiseResolve();
14471472
}
1448-
process.nextTick(emit.bind(this, 'close'));
1473+
process.nextTick(FunctionPrototypeBind(emit, this, 'close'));
14491474
}
14501475

14511476
ref() {
@@ -1714,14 +1739,17 @@ class QuicSession extends EventEmitter {
17141739
if (state.handshakeCompletePromise !== undefined)
17151740
return state.handshakeCompletePromise;
17161741

1717-
state.handshakeCompletePromise = new Promise((resolve, reject) => {
1718-
state.handshakeCompletePromiseResolve = resolve;
1719-
state.handshakeCompletePromiseReject = reject;
1720-
}).finally(() => {
1721-
state.handshakeCompletePromise = undefined;
1722-
state.handshakeCompletePromiseReject = undefined;
1723-
state.handshakeCompletePromiseResolve = undefined;
1724-
});
1742+
state.handshakeCompletePromise = PromisePrototypeFinally(
1743+
new Promise((resolve, reject) => {
1744+
state.handshakeCompletePromiseResolve = resolve;
1745+
state.handshakeCompletePromiseReject = reject;
1746+
}),
1747+
() => {
1748+
state.handshakeCompletePromise = undefined;
1749+
state.handshakeCompletePromiseReject = undefined;
1750+
state.handshakeCompletePromiseResolve = undefined;
1751+
}
1752+
);
17251753

17261754
return state.handshakeCompletePromise;
17271755
}
@@ -1985,7 +2013,7 @@ class QuicSession extends EventEmitter {
19852013
if (error) {
19862014
if (typeof state.closePromiseReject === 'function')
19872015
state.closePromiseReject(error);
1988-
process.nextTick(emit.bind(this, 'error', error));
2016+
process.nextTick(FunctionPrototypeBind(emit, this, 'error', error));
19892017
} else if (typeof state.closePromiseResolve === 'function')
19902018
state.closePromiseResolve();
19912019

@@ -1994,7 +2022,7 @@ class QuicSession extends EventEmitter {
19942022
new ERR_OPERATION_FAILED('Handshake failed'));
19952023
}
19962024

1997-
process.nextTick(emit.bind(this, 'close'));
2025+
process.nextTick(FunctionPrototypeBind(emit, this, 'close'));
19982026
}
19992027

20002028
// For server QuicSession instances, true if earlyData is
@@ -2698,7 +2726,7 @@ class QuicStream extends Duplex {
26982726
default:
26992727
assert.fail('Invalid headers kind');
27002728
}
2701-
process.nextTick(emit.bind(this, name, headers, push_id));
2729+
process.nextTick(FunctionPrototypeBind(emit, this, name, headers, push_id));
27022730
}
27032731

27042732
[kAfterAsyncWrite]({ bytes }) {
@@ -2809,7 +2837,7 @@ class QuicStream extends Duplex {
28092837
if (!this.destroyed) {
28102838
if (!this.detached)
28112839
this[kInternalState].sharedState.writeEnded = true;
2812-
super.end.apply(this, args);
2840+
ReflectApply(super.end, this, args);
28132841
}
28142842
return this;
28152843
}
@@ -2825,13 +2853,14 @@ class QuicStream extends Duplex {
28252853
state.didRead = true;
28262854
}
28272855

2828-
streamOnResume.call(this);
2856+
FunctionPrototypeCall(streamOnResume, this);
28292857
}
28302858

28312859
sendFile(path, options = {}) {
28322860
if (this.detached)
28332861
throw new ERR_INVALID_STATE('Unable to send file');
2834-
fs.open(path, 'r', QuicStream[kOnFileOpened].bind(this, options));
2862+
fs.open(path, 'r',
2863+
FunctionPrototypeBind(QuicStream[kOnFileOpened], this, options));
28352864
}
28362865

28372866
static [kOnFileOpened](options, err, fd) {
@@ -2847,7 +2876,7 @@ class QuicStream extends Duplex {
28472876
}
28482877

28492878
if (this.destroyed || this.closed) {
2850-
fs.close(fd, (err) => { if (err) throw err; });
2879+
fs.close(fd, assert.ifError);
28512880
return;
28522881
}
28532882

@@ -2895,7 +2924,8 @@ class QuicStream extends Duplex {
28952924
static [kOnFileUnpipe]() { // Called on the StreamPipe instance.
28962925
const stream = this.sink[owner_symbol];
28972926
if (stream.ownsFd)
2898-
this.source.close().catch(stream.destroy.bind(stream));
2927+
PromisePrototypeCatch(this.source.close(),
2928+
FunctionPrototypeBind(stream.destroy, stream));
28992929
else
29002930
this.source.releaseFD();
29012931
stream.end();

0 commit comments

Comments
 (0)