Skip to content

Commit eb5e0b6

Browse files
committed
Improve error detection
1 parent f7d6862 commit eb5e0b6

5 files changed

Lines changed: 31 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 2.7.0
2+
3+
## Features
4+
5+
- Improve error detection
6+
17
# 2.6.0
28

39
## Features

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"node": ">=14.18.0"
5454
},
5555
"dependencies": {
56+
"is-error-instance": "^1.1.0",
5657
"is-plain-obj": "^4.1.0"
5758
}
5859
}

src/create/main.js

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import isErrorInstance from 'is-error-instance'
12
import isPlainObj from 'is-plain-obj'
23

34
import { isNonModifiableError } from './modifiable.js'
@@ -12,8 +13,8 @@ export const createError = function (value) {
1213
return objectifyError(value)
1314
}
1415

15-
if (!isError(value)) {
16-
return handleNonError(value)
16+
if (!isErrorInstance(value)) {
17+
return stringifyError(value)
1718
}
1819

1920
if (isInvalidError(value)) {
@@ -32,40 +33,25 @@ const isErrorPlainObj = function (value) {
3233
}
3334
}
3435

35-
// Unlike `instanceof Error`, this works cross-realm,
36-
// e.g. `vm.runInNewContext('Error')`.
37-
// Handle hooks exceptions when `value` is a Proxy.
38-
const isError = function (value) {
39-
try {
40-
return (
41-
objectToString.call(value) === '[object Error]' &&
42-
!(Symbol.toStringTag in value)
43-
)
44-
} catch {
45-
return false
46-
}
47-
}
48-
49-
const handleNonError = function (value) {
50-
return isProxy(value) ? objectifyError(value) : stringifyError(value)
36+
const isInvalidError = function (value) {
37+
return (
38+
isProxy(value) ||
39+
isNonModifiableError(value) ||
40+
hasInvalidConstructor(value)
41+
)
5142
}
5243

5344
// Proxies of Errors are converted to non-proxies.
5445
// This can only work within the same realm, because the only way to detect
5546
// proxies is combining `Object.prototype.toString()` and `instanceof`.
56-
// Handle hooks exceptions when `value` is a Proxy.
5747
const isProxy = function (value) {
5848
try {
59-
return value instanceof Error
49+
return objectToString.call(value) === '[object Object]'
6050
} catch {
6151
return true
6252
}
6353
}
6454

65-
const isInvalidError = function (value) {
66-
return isNonModifiableError(value) || hasInvalidConstructor(value)
67-
}
68-
6955
// `error.constructor` is often used for type checking, so we ensure it
7056
// is normal.
7157
const hasInvalidConstructor = function (error) {

test/create/main.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ test('Plain-objects errors work cross-realm', (t) => {
1313
t.true(error instanceof TypeError)
1414
})
1515

16-
test('Plain-objects with toString tag', (t) => {
17-
const error = normalizeException({
18-
[Symbol.toStringTag]: 'Error',
19-
message: 'test',
20-
})
21-
t.is(error.message, '[object Error]')
22-
t.true(error instanceof Error)
23-
})
24-
2516
const constructorWithoutName = function () {}
2617
// eslint-disable-next-line fp/no-mutating-methods
2718
Object.defineProperty(constructorWithoutName, 'name', { value: false })

0 commit comments

Comments
 (0)