fix(ext/http): ensure signal is created iff requested (#23601)

This correctly creates the `AbortSignal` regardless of when we request
it. If the signal is requested after the request has completed, the
signal is created in the aborted state.

Using GC counts, we can see a reduction in object creation:

This PR: 440
deno 1.42.4: 1650
deno 1.43.0+b02ffec: 874
This commit is contained in:
Matt Mastracci 2024-04-29 09:40:02 -06:00 committed by GitHub
parent da52058a94
commit 56fec538e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 4 deletions

View file

@ -9,7 +9,7 @@
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
import { core, primordials } from "ext:core/mod.js";
import { core, internals, primordials } from "ext:core/mod.js";
const {
ArrayPrototypeMap,
ArrayPrototypeSlice,
@ -269,10 +269,20 @@ class Request {
/** @type {AbortSignal} */
get [_signal]() {
const signal = this[_signalCache];
if (signal !== undefined) {
// This signal not been created yet, and the request is still in progress
if (signal === undefined) {
const signal = newSignal();
this[_signalCache] = signal;
return signal;
}
return (this[_signalCache] = newSignal());
// This signal has not been created yet, but the request has already completed
if (signal === false) {
const signal = newSignal();
this[_signalCache] = signal;
signal[signalAbort](signalAbortError);
return signal;
}
return signal;
}
get [_mimeType]() {
const values = getDecodeSplitHeader(
@ -593,11 +603,20 @@ const signalAbortError = new DOMException(
ObjectFreeze(signalAbortError);
function abortRequest(request) {
if (request[_signal]) {
if (request[_signalCache] !== undefined) {
request[_signal][signalAbort](signalAbortError);
} else {
request[_signalCache] = false;
}
}
function getCachedAbortSignal(request) {
return request[_signalCache];
}
// For testing
internals.getCachedAbortSignal = getCachedAbortSignal;
export {
abortRequest,
fromInnerRequest,