1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-26 00:59:24 -05:00

feat(fetch): support abort reasons in fetch (#13106)

This commit is contained in:
Andreu Botella 2021-12-16 12:58:24 +01:00 committed by GitHub
parent 01a6b66034
commit 8efe829fca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 17 deletions

View file

@ -1272,7 +1272,60 @@ Deno.test(
} catch (error) {
assert(error instanceof DOMException);
assertEquals(error.name, "AbortError");
assertEquals(error.message, "Ongoing fetch was aborted.");
assertEquals(error.message, "The signal has been aborted");
}
},
);
Deno.test(
{ permissions: { net: true } },
async function fetchAbortWhileUploadStreamingWithReason(): Promise<void> {
const abortController = new AbortController();
const abortReason = new Error();
try {
await fetch(
"http://localhost:5552/echo_server",
{
method: "POST",
body: new ReadableStream({
pull(controller) {
abortController.abort(abortReason);
controller.enqueue(new Uint8Array([1, 2, 3, 4]));
},
}),
signal: abortController.signal,
},
);
fail("Fetch didn't reject.");
} catch (error) {
assertEquals(error, abortReason);
}
},
);
Deno.test(
{ permissions: { net: true } },
async function fetchAbortWhileUploadStreamingWithPrimitiveReason(): Promise<
void
> {
const abortController = new AbortController();
try {
await fetch(
"http://localhost:5552/echo_server",
{
method: "POST",
body: new ReadableStream({
pull(controller) {
abortController.abort("Abort reason");
controller.enqueue(new Uint8Array([1, 2, 3, 4]));
},
}),
signal: abortController.signal,
},
);
fail("Fetch didn't reject.");
} catch (error) {
assertEquals(error, "Abort reason");
}
},
);

View file

@ -27,7 +27,6 @@
abortedNetworkError,
} = window.__bootstrap.fetch;
const abortSignal = window.__bootstrap.abortSignal;
const { DOMException } = window.__bootstrap.domException;
const {
ArrayPrototypePush,
ArrayPrototypeSplice,
@ -88,10 +87,7 @@
function createResponseBodyStream(responseBodyRid, terminator) {
function onAbort() {
if (readable) {
errorReadableStream(
readable,
new DOMException("Ongoing fetch was aborted.", "AbortError"),
);
errorReadableStream(readable, terminator.reason);
}
core.tryClose(responseBodyRid);
}
@ -121,9 +117,7 @@
} catch (err) {
RESOURCE_REGISTRY.unregister(readable);
if (terminator.aborted) {
controller.error(
new DOMException("Ongoing fetch was aborted.", "AbortError"),
);
controller.error(terminator.reason);
} else {
// There was an error while reading a chunk of the body, so we
// error.
@ -155,9 +149,7 @@
}
const body = new InnerBody(req.blobUrlEntry.stream());
terminator[abortSignal.add](() =>
body.error(new DOMException("Ongoing fetch was aborted.", "AbortError"))
);
terminator[abortSignal.add](() => body.error(terminator.reason));
return {
headerList: [
@ -328,6 +320,7 @@
/**
* @param {InnerRequest} request
* @param {InnerResponse} response
* @param {AbortSignal} terminator
* @returns {Promise<InnerResponse>}
*/
function httpRedirectFetch(request, response, terminator) {
@ -405,7 +398,7 @@
const request = toInnerRequest(requestObject);
// 4.
if (requestObject.signal.aborted) {
reject(abortFetch(request, null));
reject(abortFetch(request, null, requestObject.signal.reason));
return;
}
@ -416,7 +409,9 @@
// 10.
function onabort() {
locallyAborted = true;
reject(abortFetch(request, responseObject));
reject(
abortFetch(request, responseObject, requestObject.signal.reason),
);
}
requestObject.signal[abortSignal.add](onabort);
@ -433,7 +428,13 @@
if (locallyAborted) return;
// 12.2.
if (response.aborted) {
reject(request, responseObject);
reject(
abortFetch(
request,
responseObject,
requestObject.signal.reason,
),
);
requestObject.signal[abortSignal.remove](onabort);
return;
}
@ -459,8 +460,7 @@
});
}
function abortFetch(request, responseObject) {
const error = new DOMException("Ongoing fetch was aborted.", "AbortError");
function abortFetch(request, responseObject, error) {
if (request.body !== null) {
if (WeakMapPrototypeHas(requestBodyReaders, request)) {
WeakMapPrototypeGet(requestBodyReaders, request).cancel(error);