From a5e5d9b1cd4d38b1557492c287731df0eb13f9b6 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Wed, 2 Dec 2020 11:44:17 +0000 Subject: [PATCH] [OError] getFullInfo returns the error context of nested causes (#14) * [OError] add getFullInfoIncludeCause for retrieving nested cause info * Revert "[OError] add getFullInfoIncludeCause for retrieving nested cause info" This reverts commit 4c7517255a0f37ba94223e559a3926f19bab618d * [OError] getFullInfo returns the error context of nested causes * [OError] getFullInfo flip sequence of merging, add test case for it --- libraries/o-error/README.md | 4 +-- libraries/o-error/index.d.ts | 4 +-- libraries/o-error/index.js | 6 ++-- libraries/o-error/test/o-error-util.test.js | 34 ++++++++++++++++++--- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/libraries/o-error/README.md b/libraries/o-error/README.md index e5944432ea..cf6582b854 100644 --- a/libraries/o-error/README.md +++ b/libraries/o-error/README.md @@ -442,7 +442,7 @@ async function cleanup() { ### OError.getFullInfo(error) ⇒ Object -The merged info from any `tag`s on the given error. +The merged info from any `tag`s and causes on the given error. If an info property is repeated, the last one wins. @@ -450,7 +450,7 @@ If an info property is repeated, the last one wins. | Param | Type | Description | | --- | --- | --- | -| error | Error \| null \| undefined | any errror (may or may not be an `OError`) | +| error | Error \| null \| undefined | any error (may or may not be an `OError`) | diff --git a/libraries/o-error/index.d.ts b/libraries/o-error/index.d.ts index 44332e887b..005be4e078 100644 --- a/libraries/o-error/index.d.ts +++ b/libraries/o-error/index.d.ts @@ -63,11 +63,11 @@ declare namespace OError { */ export function tag(error: Error, message?: string, info?: any): Error; /** - * The merged info from any `tag`s on the given error. + * The merged info from any `tag`s and causes on the given error. * * If an info property is repeated, the last one wins. * - * @param {Error | null | undefined} error any errror (may or may not be an `OError`) + * @param {Error | null | undefined} error any error (may or may not be an `OError`) * @return {Object} */ export function getFullInfo(error: Error): any; diff --git a/libraries/o-error/index.js b/libraries/o-error/index.js index 8af8d1deba..5da737181f 100644 --- a/libraries/o-error/index.js +++ b/libraries/o-error/index.js @@ -98,11 +98,11 @@ class OError extends Error { } /** - * The merged info from any `tag`s on the given error. + * The merged info from any `tag`s and causes on the given error. * * If an info property is repeated, the last one wins. * - * @param {Error | null | undefined} error any errror (may or may not be an `OError`) + * @param {Error | null | undefined} error any error (may or may not be an `OError`) * @return {Object} */ static getFullInfo(error) { @@ -112,6 +112,8 @@ class OError extends Error { const oError = /** @type{OError} */ (error) + if (oError.cause) Object.assign(info, OError.getFullInfo(oError.cause)) + if (typeof oError.info === 'object') Object.assign(info, oError.info) if (oError._oErrorTags) { diff --git a/libraries/o-error/test/o-error-util.test.js b/libraries/o-error/test/o-error-util.test.js index b82c1093e6..67ecf0875e 100644 --- a/libraries/o-error/test/o-error-util.test.js +++ b/libraries/o-error/test/o-error-util.test.js @@ -282,12 +282,38 @@ describe('OError.getFullInfo', function () { }) }) - it('does not merge info from a cause', function () { + it('merges info from a cause', function () { const err1 = new Error('foo') const err2 = new Error('bar') err1.cause = err2 err2.info = { userId: 123 } - expect(OError.getFullInfo(err1)).to.deep.equal({}) + expect(OError.getFullInfo(err1)).to.deep.equal({ userId: 123 }) + }) + + it('merges info from a nested cause', function () { + const err1 = new Error('foo') + const err2 = new Error('bar') + const err3 = new Error('baz') + err1.cause = err2 + err2.info = { userId: 123 } + err2.cause = err3 + err3.info = { foo: 42 } + expect(OError.getFullInfo(err1)).to.deep.equal({ + userId: 123, + foo: 42, + }) + }) + + it('merges info from cause with duplicate keys', function () { + const err1 = new Error('foo') + const err2 = new Error('bar') + err1.info = { userId: 42, foo: 1337 } + err1.cause = err2 + err2.info = { userId: 1 } + expect(OError.getFullInfo(err1)).to.deep.equal({ + userId: 42, + foo: 1337, + }) }) it('merges info from tags with duplicate keys', function () { @@ -371,8 +397,8 @@ describe('OError.getFullStack', function () { ' TaggedError: failed to foo', ]) - // The info from the wrapped cause should not leak out. - expect(OError.getFullInfo(error)).to.eql({ bat: 1 }) + // The info from the wrapped cause should be picked up for logging. + expect(OError.getFullInfo(error)).to.eql({ bat: 1, foo: 1 }) // But it should still be recorded. expect(OError.getFullInfo(error.cause)).to.eql({ foo: 1 })