Skip to content

Commit

Permalink
Improve error normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Jun 5, 2022
1 parent cfe63f6 commit 30a0eae
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 23 deletions.
30 changes: 9 additions & 21 deletions src/error/normalize/main.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { setErrorProperty } from './set.js'
import { setFullStack, getStackHeader, fixStack } from './stack.js'

// Ensure we are using an Error instance
Expand Down Expand Up @@ -29,20 +30,17 @@ const createError = function (value) {
// Ensure `error.name` is a string
const normalizeName = function (error) {
if (!isDefinedString(error.name)) {
setErrorProperty(
error,
'name',
isDefinedString(error.constructor.name)
? error.constructor.name
: 'Error',
)
const name = isDefinedString(error.constructor.name)
? error.constructor.name
: 'Error'
setErrorProperty(error, 'name', name)
}
}

// Ensure `error.message` is a string
const normalizeMessage = function (error) {
if (!isDefinedString(error.message)) {
error.message = ''
setErrorProperty(error, 'message', '')
}
}

Expand All @@ -66,7 +64,7 @@ const isDefinedString = function (value) {
// Recurse over `error.cause`
const normalizeCause = function (error) {
if (error.cause !== undefined) {
error.cause = normalizeError(error.cause)
setErrorProperty(error, 'cause', normalizeError(error.cause))
}
}

Expand All @@ -76,26 +74,16 @@ const normalizeAggregate = function (error) {
if (Array.isArray(error.errors)) {
normalizeAggregateErrors(error)
} else if (error instanceof AggregateError) {
error.errors = []
setErrorProperty(error, 'errors', [])
}
}

const normalizeAggregateErrors = function (error) {
if (error instanceof AggregateError || error.errors.some(isErrorInstance)) {
error.errors = error.errors.map(normalizeError)
setErrorProperty(error, 'errors', error.errors.map(normalizeError))
}
}

const isErrorInstance = function (error) {
return error instanceof Error
}

// Error properties are non-enumerable
const setErrorProperty = function (error, propName, value) {
// eslint-disable-next-line fp/no-mutating-methods
Object.defineProperty(error, 'name', {
value,
writable: true,
enumerable: false,
})
}
9 changes: 9 additions & 0 deletions src/error/normalize/set.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Error properties are non-enumerable
export const setErrorProperty = function (error, propName, value) {
// eslint-disable-next-line fp/no-mutating-methods
Object.defineProperty(error, 'name', {
value,
writable: true,
enumerable: false,
})
}
8 changes: 6 additions & 2 deletions src/error/normalize/stack.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { setErrorProperty } from './set.js'

// Ensure `error.stack` reflects `error.name` and `error.message`
// Also create stack trace if missing.
export const setFullStack = function (error) {
error.stack = `${getStackHeader(error)}\n${getStackTrace()}`
const stack = `${getStackHeader(error)}\n${getStackTrace()}`
setErrorProperty(error, 'stack', stack)
}

// Expected first line of `error.stack`
Expand All @@ -14,7 +17,8 @@ export const fixStack = function (error, header) {
const lines = error.stack.split('\n')
const index = lines.findIndex(isStackLine)
const linesA = index === -1 ? [getStackTrace()] : lines.slice(index)
error.stack = [header, ...linesA].join('\n')
const stack = [header, ...linesA].join('\n')
setErrorProperty(error, 'stack', stack)
}

const isStackLine = function (line) {
Expand Down

0 comments on commit 30a0eae

Please sign in to comment.