diff --git a/lib/api/readable.js b/lib/api/readable.js index 356a03aedd9..c6e142b8ab9 100644 --- a/lib/api/readable.js +++ b/lib/api/readable.js @@ -4,7 +4,7 @@ const assert = require('assert') const { Readable } = require('stream') -const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = require('../core/errors') +const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require('../core/errors') const util = require('../core/util') const { ReadableStreamFrom, toUSVString } = require('../core/util') @@ -163,37 +163,31 @@ module.exports = class BodyReadable extends Readable { return this[kBody] } - dump (opts) { - let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 - const signal = opts && opts.signal - - if (signal) { - try { - if (typeof signal !== 'object' || !('aborted' in signal)) { - throw new InvalidArgumentError('signal must be an AbortSignal') - } - util.throwIfAborted(signal) - } catch (err) { - return Promise.reject(err) - } + async dump (opts) { + let limit = Number.isFinite(opts?.limit) ? opts.limit : 262144 + const signal = opts?.signal + + if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) { + throw new InvalidArgumentError('signal must be an AbortSignal') } + signal?.throwIfAborted() + if (this._readableState.closeEmitted) { - return Promise.resolve(null) + return null } - return new Promise((resolve, reject) => { - const signalListenerCleanup = signal - ? util.addAbortListener(signal, () => { - this.destroy() - }) - : noop + return await new Promise((resolve, reject) => { + const onAbort = () => { + this.destroy(signal.reason ?? new AbortError()) + } + signal?.addEventListener('abort', onAbort) this .on('close', function () { - signalListenerCleanup() - if (signal && signal.aborted) { - reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) + signal?.removeEventListener('abort', onAbort) + if (signal?.aborted) { + reject(signal.reason ?? new AbortError()) } else { resolve(null) } diff --git a/lib/core/errors.js b/lib/core/errors.js index 7af704b462a..aac259fd2cf 100644 --- a/lib/core/errors.js +++ b/lib/core/errors.js @@ -82,7 +82,16 @@ class InvalidReturnValueError extends UndiciError { } } -class RequestAbortedError extends UndiciError { +class AbortError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestAbortedError) + this.name = 'AbortError' + this.message = message || 'The operation was aborted' + } +} + +class RequestAbortedError extends AbortError { constructor (message) { super(message) Error.captureStackTrace(this, RequestAbortedError) @@ -207,6 +216,7 @@ class RequestRetryError extends UndiciError { } module.exports = { + AbortError, HTTPParserError, UndiciError, HeadersTimeoutError,