Skip to content

Commit 92b378e

Browse files
authored
Fix support for AbortSignal#timeout() (#2388)
1 parent f4f3ba8 commit 92b378e

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

source/core/index.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,12 @@ export default class Request extends Duplex implements RequestEvents<Request> {
264264

265265
if (this.options.signal) {
266266
const abort = () => {
267-
this.destroy(new AbortError(this));
267+
// See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static#return_value
268+
if (this.options.signal?.reason?.name === 'TimeoutError') {
269+
this.destroy(new TimeoutError(this.options.signal.reason, this.timings!, this));
270+
} else {
271+
this.destroy(new AbortError(this));
272+
}
268273
};
269274

270275
if (this.options.signal.aborted) {

test/abort.ts

+52
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,55 @@ test('support setting the signal as a default option', async t => {
324324

325325
t.true(signalHandlersRemoved(), 'Abort signal event handlers not removed');
326326
});
327+
328+
const timeoutErrorCode = 23;
329+
// See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static
330+
test('support AbortSignal.timeout()', async t => {
331+
const signal = AbortSignal.timeout(1);
332+
333+
const p = got('http://example.com', {signal});
334+
335+
await t.throwsAsync(p, {
336+
code: timeoutErrorCode,
337+
message: 'The operation was aborted due to timeout',
338+
});
339+
});
340+
341+
test('support AbortSignal.timeout() without user abort', async t => {
342+
const {controller, signalHandlersRemoved} = createAbortController();
343+
const timeoutSignal = AbortSignal.timeout(1);
344+
const signal = AbortSignal.any([
345+
controller.signal,
346+
timeoutSignal,
347+
]);
348+
const p = got('http://example.com', {signal});
349+
350+
await t.throwsAsync(p, {
351+
code: timeoutErrorCode,
352+
message: 'The operation was aborted due to timeout',
353+
});
354+
355+
t.true(signalHandlersRemoved(), 'Abort signal event handlers not removed');
356+
});
357+
358+
test('support AbortSignal.timeout() with user abort', async t => {
359+
const {controller, signalHandlersRemoved} = createAbortController();
360+
const timeoutSignal = AbortSignal.timeout(1000);
361+
const signal = AbortSignal.any([
362+
controller.signal,
363+
timeoutSignal,
364+
]);
365+
366+
setTimeout(() => {
367+
controller.abort();
368+
}, 10);
369+
370+
const p = got('http://example.com', {signal});
371+
372+
await t.throwsAsync(p, {
373+
code: 'ERR_ABORTED',
374+
message: 'This operation was aborted.',
375+
});
376+
377+
t.true(signalHandlersRemoved(), 'Abort signal event handlers not removed');
378+
});

0 commit comments

Comments
 (0)