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:
parent
01a6b66034
commit
8efe829fca
2 changed files with 70 additions and 17 deletions
|
@ -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");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue