aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/internal/util.js8
-rw-r--r--lib/util.js12
-rw-r--r--test/parallel/test-internal-util-helpers.js37
3 files changed, 54 insertions, 3 deletions
diff --git a/lib/internal/util.js b/lib/internal/util.js
index 414d037a29..ee550fad2e 100644
--- a/lib/internal/util.js
+++ b/lib/internal/util.js
@@ -12,6 +12,9 @@ const {
arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex,
decorated_private_symbol: kDecoratedPrivateSymbolIndex
} = internalBinding('util');
+const {
+ isNativeError
+} = internalBinding('types');
const { errmap } = internalBinding('uv');
@@ -26,7 +29,10 @@ function removeColors(str) {
}
function isError(e) {
- return objectToString(e) === '[object Error]' || e instanceof Error;
+ // An error could be an instance of Error while not being a native error
+ // or could be from a different realm and not be instance of Error but still
+ // be a native error.
+ return isNativeError(e) || e instanceof Error;
}
function objectToString(o) {
diff --git a/lib/util.js b/lib/util.js
index 63b34f48bf..8f7f3a92dd 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -42,10 +42,16 @@ const {
const {
deprecate,
getSystemErrorName: internalErrorName,
- isError,
promisify,
} = require('internal/util');
+const ReflectApply = Reflect.apply;
+
+function uncurryThis(func) {
+ return (thisArg, ...args) => ReflectApply(func, thisArg, args);
+}
+const objectToString = uncurryThis(Object.prototype.toString);
+
let CIRCULAR_ERROR_MESSAGE;
let internalDeepEqual;
@@ -443,7 +449,9 @@ module.exports = exports = {
isRegExp,
isObject,
isDate,
- isError,
+ isError(e) {
+ return objectToString(e) === '[object Error]' || e instanceof Error;
+ },
isFunction,
isPrimitive,
log,
diff --git a/test/parallel/test-internal-util-helpers.js b/test/parallel/test-internal-util-helpers.js
new file mode 100644
index 0000000000..bf60cff9bd
--- /dev/null
+++ b/test/parallel/test-internal-util-helpers.js
@@ -0,0 +1,37 @@
+// Flags: --expose-internals
+'use strict';
+
+require('../common');
+const assert = require('assert');
+const { types } = require('util');
+const { isError } = require('internal/util');
+const vm = require('vm');
+
+// Special cased errors. Test the internal function which is used in
+// `util.inspect()`, the `repl` and maybe more. This verifies that errors from
+// different realms, and non native instances of error are properly detected as
+// error while definitely false ones are not detected. This is different than
+// the public `util.isError()` function which falsy detects the fake errors as
+// actual errors.
+{
+ const fake = { [Symbol.toStringTag]: 'Error' };
+ assert(!types.isNativeError(fake));
+ assert(!(fake instanceof Error));
+ assert(!isError(fake));
+
+ const err = new Error('test');
+ const newErr = Object.create(
+ Object.getPrototypeOf(err),
+ Object.getOwnPropertyDescriptors(err));
+ Object.defineProperty(err, 'message', { value: err.message });
+ assert(types.isNativeError(err));
+ assert(!types.isNativeError(newErr));
+ assert(newErr instanceof Error);
+ assert(isError(newErr));
+
+ const context = vm.createContext({});
+ const differentRealmErr = vm.runInContext('new Error()', context);
+ assert(types.isNativeError(differentRealmErr));
+ assert(!(differentRealmErr instanceof Error));
+ assert(isError(differentRealmErr));
+}