From a5762f758e92d2d32f92ec93f9e8271525f043e7 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 6 Dec 2023 09:50:28 +0100 Subject: [PATCH] fix: more sensible stack trace from dump error --- lib/api/readable.js | 40 +++++++++++++++++----------------------- lib/core/errors.js | 12 +++++++++++- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/api/readable.js b/lib/api/readable.js index 356a03aedd9..2348de749fa 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,36 +163,30 @@ 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) { + signal?.removeEventListener('abort', onAbort) + if (signal?.aborted) { reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) } else { resolve(null) diff --git a/lib/core/errors.js b/lib/core/errors.js index 7af704b462a..9f2dcb00584 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 + } +} + +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,