From 0f283646387e1c05765680619b320a475efdc095 Mon Sep 17 00:00:00 2001 From: Christian Owusu <36159205+crisshaker@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:01:11 +0000 Subject: [PATCH 1/4] Fix signal handling for Request objects Fix lint issues --- source/core/Ky.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index b8f43949..cf8ee2cc 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -129,8 +129,11 @@ export class Ky { ? this._input.credentials : undefined; + const signal = this._input instanceof Request ? this._input.signal : undefined; + this._options = { ...(credentials && {credentials}), // For exactOptionalPropertyTypes + ...(signal && {signal}), // For exactOptionalPropertyTypes ...options, headers: mergeHeaders((this._input as Request).headers, options.headers), hooks: deepMerge>( From 159f1199a9894aba2ef8c628246796a61168b125 Mon Sep 17 00:00:00 2001 From: Seth Holladay Date: Mon, 29 Jul 2024 17:28:45 -0400 Subject: [PATCH 2/4] Simplify signal handling --- source/core/Ky.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index cf8ee2cc..9330a92d 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -129,11 +129,8 @@ export class Ky { ? this._input.credentials : undefined; - const signal = this._input instanceof Request ? this._input.signal : undefined; - this._options = { ...(credentials && {credentials}), // For exactOptionalPropertyTypes - ...(signal && {signal}), // For exactOptionalPropertyTypes ...options, headers: mergeHeaders((this._input as Request).headers, options.headers), hooks: deepMerge>( @@ -172,10 +169,9 @@ export class Ky { if (supportsAbortController) { this.abortController = new globalThis.AbortController(); - if (this._options.signal) { - const originalSignal = this._options.signal; - - this._options.signal.addEventListener('abort', () => { + const originalSignal = this._options.signal || (this._input as Request).signal; + if (originalSignal) { + originalSignal.addEventListener('abort', () => { this.abortController!.abort(originalSignal.reason); }); } From b46c6eb1d3a8864d8e3d3aec21f5fff82c6e508b Mon Sep 17 00:00:00 2001 From: Seth Holladay Date: Mon, 29 Jul 2024 17:31:50 -0400 Subject: [PATCH 3/4] Fix lint error --- source/core/Ky.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index 9330a92d..a370b54d 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -169,7 +169,7 @@ export class Ky { if (supportsAbortController) { this.abortController = new globalThis.AbortController(); - const originalSignal = this._options.signal || (this._input as Request).signal; + const originalSignal = this._options.signal ?? (this._input as Request).signal; if (originalSignal) { originalSignal.addEventListener('abort', () => { this.abortController!.abort(originalSignal.reason); From fe37f6070749c18e1e1a6e97e77e574a0df9192b Mon Sep 17 00:00:00 2001 From: Seth Holladay Date: Wed, 31 Jul 2024 17:57:22 -0400 Subject: [PATCH 4/4] Add a test for aborting via a Request object --- source/core/Ky.ts | 8 +++----- test/main.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/source/core/Ky.ts b/source/core/Ky.ts index a370b54d..a14ea1ba 100644 --- a/source/core/Ky.ts +++ b/source/core/Ky.ts @@ -170,11 +170,9 @@ export class Ky { if (supportsAbortController) { this.abortController = new globalThis.AbortController(); const originalSignal = this._options.signal ?? (this._input as Request).signal; - if (originalSignal) { - originalSignal.addEventListener('abort', () => { - this.abortController!.abort(originalSignal.reason); - }); - } + originalSignal?.addEventListener('abort', () => { + this.abortController!.abort(originalSignal.reason); + }); this._options.signal = this.abortController.signal; } diff --git a/test/main.ts b/test/main.ts index a830ae41..4ea3a231 100644 --- a/test/main.ts +++ b/test/main.ts @@ -655,6 +655,23 @@ test('throws DOMException/Error with name AbortError when aborted by user', asyn t.is(error.name, 'AbortError', `Expected AbortError, got ${error.name}`); }); +test('throws AbortError when aborted via Request', async t => { + const server = await createHttpTestServer(); + // eslint-disable-next-line @typescript-eslint/no-empty-function + server.get('/', () => {}); + + const abortController = new AbortController(); + const {signal} = abortController; + const request = new Request(server.url, {signal}); + const response = ky(request); + abortController.abort(); + + const error = (await t.throwsAsync(response))!; + + t.true(['DOMException', 'Error'].includes(error.constructor.name), `Expected DOMException or Error, got ${error.constructor.name}`); + t.is(error.name, 'AbortError', `Expected AbortError, got ${error.name}`); +}); + test('supports Request instance as input', async t => { const server = await createHttpTestServer(); const inputRequest = new Request(server.url, {method: 'POST'});