Skip to content

Commit

Permalink
fix: avoid unhandled rejection when signal is already aborted
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1211 committed Dec 2, 2024
1 parent c35bb8e commit 5b2aca1
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@types/chai": "^4.3.5",
"@types/chai-as-promised": "^7.1.5",
"@types/mocha": "^10.0.1",
"@types/node": "^22.10.1",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"chai": "^4.3.7",
Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ export function abortable<T>(
): Promise<T> {
if (!signal) return promise
return new Promise<T>((resolve, reject) => {
if (signal.aborted) {
reject(newAbortError())
return
}
const cleanup = () => {
const callbacks = { resolve, reject }
// Prevent memory leaks. If the input promise never resolves, then the handlers
Expand All @@ -33,5 +29,9 @@ export function abortable<T>(
(value) => cleanup().resolve(value),
(error) => cleanup().reject(error)
)
if (signal.aborted) {
reject(newAbortError())
return
}
})
}
12 changes: 12 additions & 0 deletions test/abortable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ describe(`abortable`, function () {
p.resolve(42),
])
})
it(`bug - unhandled rejection when signal is aborted`, async function () {
const p = withResolvers<number>()
const ac = new AbortController()
ac.abort()
const [, error] = tried(() => ac.signal.throwIfAborted())()
p.reject(new Error('test'))
await Promise.all([
expect(abortable(p.promise, ac.signal))
.to.be.rejectedWith(DOMException)
.that.eventually.deep.equals(error),
])
})
it(`rejects if signal aborts before promise resolves`, async function () {
const p = withResolvers<number>()
const ac = new AbortController()
Expand Down
4 changes: 4 additions & 0 deletions test/configure.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import chai from 'chai'
import chaiAsPromised from 'chai-as-promised'
chai.use(chaiAsPromised)

process.on('unhandledRejection', () => {
throw new Error('unhandled rejection!')
})

0 comments on commit 5b2aca1

Please sign in to comment.