fix(ext/fetch): Properly cancel upload stream when aborting (#11966)

Co-authored-by: Luca Casonato <lucacasonato@yahoo.com>
This commit is contained in:
Nayeem Rahman 2021-09-13 00:19:38 +01:00 committed by GitHub
parent 0520ae62dd
commit 2cc1577d28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View file

@ -40,6 +40,11 @@
TypedArrayPrototypeSubarray,
TypeError,
Uint8Array,
WeakMap,
WeakMapPrototypeDelete,
WeakMapPrototypeGet,
WeakMapPrototypeHas,
WeakMapPrototypeSet,
} = window.__bootstrap.primordials;
const REQUEST_BODY_HEADER_NAMES = [
@ -49,6 +54,8 @@
"content-type",
];
const requestBodyReaders = new WeakMap();
/**
* @param {{ method: string, url: string, headers: [string, string][], clientRid: number | null, hasBody: boolean }} args
* @param {Uint8Array | null} body
@ -193,6 +200,7 @@
reqBody = req.body.stream;
} else {
const reader = req.body.stream.getReader();
WeakMapPrototypeSet(requestBodyReaders, req, reader);
const r1 = await reader.read();
if (r1.done) {
reqBody = new Uint8Array(0);
@ -201,6 +209,7 @@
const r2 = await reader.read();
if (!r2.done) throw new TypeError("Unreachable");
}
WeakMapPrototypeDelete(requestBodyReaders, req);
}
} else {
req.body.streamOrStatic.consumed = true;
@ -232,6 +241,7 @@
throw new TypeError("Unreachable");
}
const reader = reqBody.getReader();
WeakMapPrototypeSet(requestBodyReaders, req, reader);
(async () => {
while (true) {
const { value, done } = await PromisePrototypeCatch(
@ -260,6 +270,7 @@
break;
}
}
WeakMapPrototypeDelete(requestBodyReaders, req);
core.tryClose(requestBodyRid);
})();
}
@ -473,7 +484,13 @@
function abortFetch(request, responseObject) {
const error = new DOMException("Ongoing fetch was aborted.", "AbortError");
if (request.body !== null) request.body.cancel(error);
if (request.body !== null) {
if (WeakMapPrototypeHas(requestBodyReaders, request)) {
WeakMapPrototypeGet(requestBodyReaders, request).cancel(error);
} else {
request.body.cancel(error);
}
}
if (responseObject !== null) {
const response = toInnerResponse(responseObject);
if (response.body !== null) response.body.error(error);