Skip to content

Commit

Permalink
feat: Support serializing primitives within Error causes (pinojs#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
DArcy Rush committed Nov 12, 2024
1 parent 1a136f6 commit 2edbd8c
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 16 deletions.
30 changes: 16 additions & 14 deletions lib/err-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ const getErrorCause = (err) => {
? causeResult
: undefined
} else {
return isErrorLike(cause)
? cause
: undefined
return cause
}
}

Expand All @@ -44,8 +42,6 @@ const getErrorCause = (err) => {
* @returns {string}
*/
const _stackWithCauses = (err, seen) => {
if (!isErrorLike(err)) return ''

const stack = err.stack || ''

// Ensure we don't go circular or crazily deep
Expand All @@ -56,8 +52,12 @@ const _stackWithCauses = (err, seen) => {
const cause = getErrorCause(err)

if (cause) {
seen.add(err)
return (stack + '\ncaused by: ' + _stackWithCauses(cause, seen))
if (isErrorLike(cause)) {
seen.add(err)
return (stack + '\ncaused by: ' + _stackWithCauses(cause, seen))
} else {
return (stack + '\ncaused by: ' + String(cause))
}
} else {
return stack
}
Expand All @@ -79,8 +79,6 @@ const stackWithCauses = (err) => _stackWithCauses(err, new Set())
* @returns {string}
*/
const _messageWithCauses = (err, seen, skip) => {
if (!isErrorLike(err)) return ''

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

// Ensure we don't go circular or crazily deep
Expand All @@ -91,14 +89,18 @@ const _messageWithCauses = (err, seen, skip) => {
const cause = getErrorCause(err)

if (cause) {
seen.add(err)

// @ts-ignore
const skipIfVErrorStyleCause = typeof err.cause === 'function'

return (message +
(skipIfVErrorStyleCause ? '' : ': ') +
_messageWithCauses(cause, seen, skipIfVErrorStyleCause))
if (isErrorLike(cause)) {
seen.add(err)

return (message +
(skipIfVErrorStyleCause ? '' : ': ') +
_messageWithCauses(cause, seen, skipIfVErrorStyleCause))
} else {
return (message + (skipIfVErrorStyleCause ? '' : ': ') + String(cause))
}
} else {
return message
}
Expand Down
2 changes: 1 addition & 1 deletion lib/err-with-cause.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function errWithCauseSerializer (err) {
_err.aggregateErrors = err.errors.map(err => errWithCauseSerializer(err))
}

if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause, seen)) {
if (!!err.cause && !Object.prototype.hasOwnProperty.call(err.cause, seen)) {
_err.cause = errWithCauseSerializer(err.cause)
}

Expand Down
16 changes: 16 additions & 0 deletions test/err-with-cause.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ test('keeps non-error cause', () => {
assert.strictEqual(serialized.cause, 'abc')
})

test('keeps non-error cause from constructor', () => {
for (const cause of [
'string',
42,
['an', 'array'],
{ an: 'object' },
Symbol('symbol')
]) {
const err = Error('foo', { cause })
const serialized = serializer(err)
assert.strictEqual(serialized.type, 'Error')
assert.strictEqual(serialized.message, 'foo')
assert.strictEqual(serialized.cause, cause)
}
})

test('prevents infinite recursion', () => {
const err = Error('foo')
err.inner = err
Expand Down
19 changes: 18 additions & 1 deletion test/err.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ test('serializes error causes', () => {
}
})

test('serializes non Error error cause from constructor', () => {
for (const cause of [
'string',
42,
// ["an", "array"],
// { an: "object" },
Symbol('symbol')
]) {
const err = Error('foo', { cause })
const serialized = serializer(err)
assert.strictEqual(serialized.type, 'Error')
assert.strictEqual(serialized.message, 'foo: ' + String(cause))
assert.match(serialized.stack, /err\.test\.js:/)
assert.match(serialized.stack, /Error: foo/)
}
})

test('serializes error causes with VError support', function (t) {
// Fake VError-style setup
const err = Error('foo: bar')
Expand All @@ -85,7 +102,7 @@ test('keeps non-error cause', () => {
err.cause = 'abc'
const serialized = serializer(err)
assert.strictEqual(serialized.type, 'Error')
assert.strictEqual(serialized.message, 'foo')
assert.strictEqual(serialized.message, 'foo: abc')
assert.strictEqual(serialized.cause, 'abc')
})

Expand Down

0 comments on commit 2edbd8c

Please sign in to comment.