From 1a08f90f402336e4d00e9ee82f211c6adb1640b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Mozgovoy Date: Thu, 25 Jan 2024 20:42:38 +0200 Subject: [PATCH] fix: capture async stack only for rejections with native error objects; (#6203) --- lib/core/Axios.js | 25 ++++++++++++++----------- test/unit/adapters/http.js | 31 ++++++++++++++++--------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/lib/core/Axios.js b/lib/core/Axios.js index 486024c699..2713364a0a 100644 --- a/lib/core/Axios.js +++ b/lib/core/Axios.js @@ -39,17 +39,20 @@ class Axios { try { return await this._request(configOrUrl, config); } catch (err) { - const dummy = {} - if (Error.captureStackTrace) { - Error.captureStackTrace(dummy) - } else { - dummy.stack = new Error().stack; - } - // slice off the Error: ... line - dummy.stack = dummy.stack.replace(/^.+\n/, ''); - // match without the 2 top stack lines - if (!err.stack.endsWith(dummy.stack.replace(/^.+\n.+\n/, ''))) { - err.stack += '\n' + dummy.stack + if (err instanceof Error) { + let dummy; + + Error.captureStackTrace ? Error.captureStackTrace(dummy = {}) : (dummy = new Error()); + + // slice off the Error: ... line + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : ''; + + if (!err.stack) { + err.stack = stack; + // match without the 2 top stack lines + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ''))) { + err.stack += '\n' + stack + } } throw err; diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js index 0af22789b5..4e27eb2473 100644 --- a/test/unit/adapters/http.js +++ b/test/unit/adapters/http.js @@ -449,28 +449,29 @@ describe('supports http with nodejs', function () { }); }); - it('should wrap HTTP errors and keep stack', function (done) { + it('should wrap HTTP errors and keep stack', async function () { if (nodeMajorVersion <= 12) { this.skip(); // node 12 support for async stack traces appears lacking return; } - server = http.createServer(function (req, res) { + + server = await startHTTPServer((req, res) => { res.statusCode = 400; res.end(); - }).listen(4444, function () { - void assert.rejects( - async function findMeInStackTrace() { - await axios.head('http://localhost:4444/one') - }, - function (err) { - assert.equal(err.name, 'AxiosError') - assert.equal(err.isAxiosError, true) - const matches = [...err.stack.matchAll(/findMeInStackTrace/g)] - assert.equal(matches.length, 1, err.stack) - return true; - } - ).then(done).catch(done); }); + + return assert.rejects( + async function findMeInStackTrace() { + await axios.head('http://localhost:4444/one') + }, + function (err) { + assert.equal(err.name, 'AxiosError') + assert.equal(err.isAxiosError, true) + const matches = [...err.stack.matchAll(/findMeInStackTrace/g)] + assert.equal(matches.length, 1, err.stack) + return true; + } + ) }); it('should wrap interceptor errors and keep stack', function (done) {