Skip to content

Commit

Permalink
Tighten Error determination (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
fregante authored Jan 4, 2025
1 parent 1d8395b commit 7fc2898
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
9 changes: 5 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,16 @@ export function deserializeError(value, options = {}) {
export function isErrorLike(value) {
return Boolean(value)
&& typeof value === 'object'
&& 'name' in value
&& 'message' in value
&& 'stack' in value;
&& typeof value.name === 'string'
&& typeof value.message === 'string'
&& typeof value.stack === 'string';
}

// Used as a weak check for immediately-passed objects, whereas `isErrorLike` is used for nested values to avoid bad detection
function isMinimumViableSerializedError(value) {
return Boolean(value)
&& typeof value === 'object'
&& 'message' in value
&& typeof value.message === 'string'
&& !Array.isArray(value);
}

Expand Down
45 changes: 44 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import {Buffer} from 'node:buffer';
import Stream from 'node:stream';
import test from 'ava';
import errorConstructors from './error-constructors.js';
import {serializeError, deserializeError, isErrorLike} from './index.js';
import {
serializeError,
deserializeError,
isErrorLike,
NonError,
} from './index.js';

function deserializeNonError(t, value) {
const deserialized = deserializeError(value);
Expand Down Expand Up @@ -351,6 +356,44 @@ test('should deserialize properties up to `Options.maxDepth` levels deep', t =>
t.deepEqual(levelThree, error);
});

test('should ignore invalid error-like objects', t => {
const errorLike = {
name: 'Error',
message: 'Some error message',
};

const nonErrorLike = {
name: 'Error',
message: (new class Message {}('Bottle')),
};

t.true(deserializeError(errorLike) instanceof Error);
t.true(deserializeError(nonErrorLike) instanceof NonError);
});

test('should ignore nested invalid error-like objects', t => {
const errorLike = {
message: 'Base',
nested: {
name: 'Error',
message: 'Some error message',
stack: 'at <anonymous>:1:13',
},
};

const nonErrorLike = {
message: 'Base',
nested: {
name: 'Error',
message: (new class Message {}('Bottle')),
stack: 'at <anonymous>:1:13',
},
};

t.true(deserializeError(errorLike).nested instanceof Error);
t.false(deserializeError(nonErrorLike).nested instanceof Error);
});

test('should serialize Date as ISO string', t => {
const date = {date: new Date(0)};
const serialized = serializeError(date);
Expand Down

0 comments on commit 7fc2898

Please sign in to comment.