From cd03389196d4d24f100198281e5316995705e6a6 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 6 Dec 2021 14:22:30 +0100 Subject: [PATCH 1/2] util: make sure error causes of any type may be inspected An error cause may be of any type. Handle all of them, no matter if they are an error or not. Fixes: https://github.com/nodejs/node/issues/41096 Signed-off-by: Ruben Bridgewater --- lib/internal/util/inspect.js | 2 +- test/message/util-inspect-error-cause.js | 13 ++++++++++++ test/message/util-inspect-error-cause.out | 25 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 0279e5ecb155f1..fb4708bc136957 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -1198,7 +1198,7 @@ function getStackFrames(ctx, err, stack) { const frames = stack.split('\n'); // Remove stack frames identical to frames in cause. - if (err.cause) { + if (err.cause && isError(err.cause)) { const causeStack = getStackString(err.cause); const causeStackStart = causeStack.indexOf('\n at'); if (causeStackStart !== -1) { diff --git a/test/message/util-inspect-error-cause.js b/test/message/util-inspect-error-cause.js index f6318357974cb6..4f22a34056cf4d 100644 --- a/test/message/util-inspect-error-cause.js +++ b/test/message/util-inspect-error-cause.js @@ -13,6 +13,19 @@ const cause2 = new FoobarError('Individual message', { cause: cause1 }); cause2.extraProperties = 'Yes!'; const cause3 = new Error('Stack causes', { cause: cause2 }); +const cause4 = new Error('Number error cause', { cause: 42 }); +const cause5 = new Error('Object cause', { + cause: { + message: 'Unique', + name: 'Error', + stack: 'Error: Unique\n' + + ' at Module._compile (node:internal/modules/cjs/loader:827:30)' + } +}); + +console.log(cause4); +console.log(cause5); + process.nextTick(() => { const error = new RangeError('New Stack Frames', { cause: cause2 }); const error2 = new RangeError('New Stack Frames', { cause: cause3 }); diff --git a/test/message/util-inspect-error-cause.out b/test/message/util-inspect-error-cause.out index bd8673ae25c031..a34ca5b46c8d47 100644 --- a/test/message/util-inspect-error-cause.out +++ b/test/message/util-inspect-error-cause.out @@ -1,3 +1,28 @@ +Error: Number error cause + at * + at * + at * + at * + at * + at * + at * { + [cause]: 42 +} +Error: Object cause + at * + at * + at * + at * + at * + at * + at * { + [cause]: { + message: 'Unique', + name: 'Error', + stack: 'Error: Unique\n' + + ' at Module._compile (node:internal/modules/cjs/loader:827:30)' + } +} RangeError: New Stack Frames at * *[90m at *[39m { From 38fc7f86a0bfe7a2cea96e763495331abdc7e74b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 6 Dec 2021 15:25:42 +0100 Subject: [PATCH 2/2] util: serialize falsy cause values while inspecting errors Signed-off-by: Ruben Bridgewater --- lib/internal/util/inspect.js | 3 ++- test/parallel/test-util-inspect.js | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index fb4708bc136957..9b9b800e36793b 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -1265,7 +1265,8 @@ function formatError(err, constructor, tag, ctx, keys) { removeDuplicateErrorKeys(ctx, keys, err, stack); - if (err.cause && (keys.length === 0 || !keys.includes('cause'))) { + if (err.cause !== undefined && + (keys.length === 0 || !keys.includes('cause'))) { keys.push('cause'); } diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index ca9d029e2f62b0..adeaa01c9b69af 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -660,6 +660,16 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); assert(ex.includes('[message]')); } +{ + const falsyCause1 = new Error('', { cause: false }); + delete falsyCause1.stack; + const falsyCause2 = new Error(undefined, { cause: null }); + falsyCause2.stack = ''; + + assert.strictEqual(util.inspect(falsyCause1), '[Error] { [cause]: false }'); + assert.strictEqual(util.inspect(falsyCause2), '[Error] { [cause]: null }'); +} + { const tmp = Error.stackTraceLimit; Error.stackTraceLimit = 0;