Skip to content

Commit

Permalink
Merge pull request #122 from ronag/err-like
Browse files Browse the repository at this point in the history
improve error serialization compat
  • Loading branch information
jsumners authored Dec 27, 2022
2 parents 4353f38 + 32457db commit 22ee50b
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 34 deletions.
15 changes: 10 additions & 5 deletions lib/err-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
// * Please upstream improvements there *
// **************************************************************

const isErrorLike = (err) => {
return err && typeof err.message === 'string'
}

/**
* @param {Error|{ cause?: unknown|(()=>err)}} err
* @returns {Error|undefined}
* @returns {Error|Object|undefined}
*/
const getErrorCause = (err) => {
if (!err) return
Expand All @@ -21,11 +25,11 @@ const getErrorCause = (err) => {
// @ts-ignore
const causeResult = err.cause()

return causeResult instanceof Error
return isErrorLike(causeResult)
? causeResult
: undefined
} else {
return cause instanceof Error
return isErrorLike(cause)
? cause
: undefined
}
Expand All @@ -40,7 +44,7 @@ const getErrorCause = (err) => {
* @returns {string}
*/
const _stackWithCauses = (err, seen) => {
if (!(err instanceof Error)) return ''
if (!isErrorLike(err)) return ''

const stack = err.stack || ''

Expand Down Expand Up @@ -75,7 +79,7 @@ const stackWithCauses = (err) => _stackWithCauses(err, new Set())
* @returns {string}
*/
const _messageWithCauses = (err, seen, skip) => {
if (!(err instanceof Error)) return ''
if (!isErrorLike(err)) return ''

const message = skip ? '' : (err.message || '')

Expand Down Expand Up @@ -107,6 +111,7 @@ const _messageWithCauses = (err, seen, skip) => {
const messageWithCauses = (err) => _messageWithCauses(err, new Set())

module.exports = {
isErrorLike,
getErrorCause,
stackWithCauses,
messageWithCauses
Expand Down
8 changes: 4 additions & 4 deletions lib/err.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module.exports = errSerializer

const { messageWithCauses, stackWithCauses } = require('./err-helpers')
const { messageWithCauses, stackWithCauses, isErrorLike } = require('./err-helpers')

const { toString } = Object.prototype
const seen = Symbol('circular-ref-tag')
Expand Down Expand Up @@ -44,7 +44,7 @@ Object.defineProperty(pinoErrProto, rawSymbol, {
})

function errSerializer (err) {
if (!(err instanceof Error)) {
if (!isErrorLike(err)) {
return err
}

Expand All @@ -56,14 +56,14 @@ function errSerializer (err) {
_err.message = messageWithCauses(err)
_err.stack = stackWithCauses(err)

if (global.AggregateError !== undefined && err instanceof global.AggregateError && Array.isArray(err.errors)) {
if (Array.isArray(err.errors)) {
_err.aggregateErrors = err.errors.map(err => errSerializer(err))
}

for (const key in err) {
if (_err[key] === undefined) {
const val = err[key]
if (val instanceof Error) {
if (isErrorLike(val)) {
// We append cause messages and stacks to _err, therefore skipping causes here
if (key !== 'cause' && !Object.prototype.hasOwnProperty.call(val, seen)) {
_err[key] = errSerializer(val)
Expand Down
57 changes: 32 additions & 25 deletions test/err.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,23 @@ test('serializes nested errors', function (t) {
})

test('serializes error causes', function (t) {
t.plan(7)
const err = Error('foo')
err.cause = Error('bar')
err.cause.cause = Error('abc')
const serialized = serializer(err)
t.equal(serialized.type, 'Error')
t.equal(serialized.message, 'foo: bar: abc')
t.match(serialized.stack, /err\.test\.js:/)
t.match(serialized.stack, /Error: foo/)
t.match(serialized.stack, /Error: bar/)
t.match(serialized.stack, /Error: abc/)
t.notOk(serialized.cause)
t.plan(14)
for (const cause of [
Error('bar'),
{ message: 'bar', stack: 'Error: bar: err.test.js:' }
]) {
const err = Error('foo')
err.cause = cause
err.cause.cause = Error('abc')
const serialized = serializer(err)
t.equal(serialized.type, 'Error')
t.equal(serialized.message, 'foo: bar: abc')
t.match(serialized.stack, /err\.test\.js:/)
t.match(serialized.stack, /Error: foo/)
t.match(serialized.stack, /Error: bar/)
t.match(serialized.stack, /Error: abc/)
t.notOk(serialized.cause)
}
})

test('serializes error causes with VError support', function (t) {
Expand Down Expand Up @@ -161,7 +166,7 @@ test('redefined err.constructor doesnt crash serializer', function (t) {
check(serializer(err5), 'Error')
})

test('pass through anything that is not an Error', function (t) {
test('pass through anything that does not look like an Error', function (t) {
t.plan(3)

function check (a) {
Expand Down Expand Up @@ -191,18 +196,20 @@ test('can wrap err serializers', function (t) {
})

test('serializes aggregate errors', { skip: !global.AggregateError }, function (t) {
t.plan(8)
t.plan(14)
const foo = new Error('foo')
const bar = new Error('bar')
const aggregate = new AggregateError([foo, bar], 'aggregated message') // eslint-disable-line no-undef

const serialized = serializer(aggregate)
t.equal(serialized.type, 'AggregateError')
t.equal(serialized.message, 'aggregated message')
t.equal(serialized.aggregateErrors.length, 2)
t.equal(serialized.aggregateErrors[0].message, 'foo')
t.equal(serialized.aggregateErrors[1].message, 'bar')
t.match(serialized.aggregateErrors[0].stack, /^Error: foo/)
t.match(serialized.aggregateErrors[1].stack, /^Error: bar/)
t.match(serialized.stack, /err\.test\.js:/)
for (const aggregate of [
new AggregateError([foo, bar], 'aggregated message'), // eslint-disable-line no-undef
{ errors: [foo, bar], message: 'aggregated message', stack: 'err.test.js:' }
]) {
const serialized = serializer(aggregate)
t.equal(serialized.message, 'aggregated message')
t.equal(serialized.aggregateErrors.length, 2)
t.equal(serialized.aggregateErrors[0].message, 'foo')
t.equal(serialized.aggregateErrors[1].message, 'bar')
t.match(serialized.aggregateErrors[0].stack, /^Error: foo/)
t.match(serialized.aggregateErrors[1].stack, /^Error: bar/)
t.match(serialized.stack, /err\.test\.js:/)
}
})

0 comments on commit 22ee50b

Please sign in to comment.