diff --git a/error-constructors.d.ts b/error-constructors.d.ts index ec487a7..91a926c 100644 --- a/error-constructors.d.ts +++ b/error-constructors.d.ts @@ -1,10 +1,8 @@ +type BaseErrorConstructor = new (message?: string, ...arguments_: unknown[]) => Error; + /** Let `serialize-error` know about your custom error constructors so that when `{name: 'MyCustomError', message: 'It broke'}` is found, it uses the right error constructor. If "MyCustomError" isn't found in the global list of known constructors, it defaults to the base `Error` error constructor. Warning: The constructor must work without any arguments or this function will throw. */ - -type BaseErrorConstructor = new (message?: string, ...arguments_: unknown[]) => Error; -declare function addKnownErrorConstructor(constructor: BaseErrorConstructor): void; - -export {addKnownErrorConstructor}; +export function addKnownErrorConstructor(constructor: BaseErrorConstructor): void; diff --git a/error-constructors.js b/error-constructors.js index 99938f0..a2ad070 100644 --- a/error-constructors.js +++ b/error-constructors.js @@ -26,16 +26,16 @@ const list = [ export const errorConstructors = new Map(list); export function addKnownErrorConstructor(constructor) { - const {name} = constructor; - if (errorConstructors.has(name)) { - throw new Error(`The error constructor "${name}" is already known.`); - } - + let instance; try { - // eslint-disable-next-line no-new -- It just needs to be verified - new constructor(); + instance = new constructor(); } catch (error) { - throw new Error(`The error constructor "${name}" is not compatible`, {cause: error}); + throw new Error(`The error constructor "${constructor.name}" is not compatible`, {cause: error}); + } + + const {name} = instance; + if (errorConstructors.has(name)) { + throw new Error(`The error constructor "${name}" is already known.`); } errorConstructors.set(name, constructor); diff --git a/test.js b/test.js index 19a080d..92a5a81 100644 --- a/test.js +++ b/test.js @@ -295,6 +295,32 @@ test('should not allow adding incompatible or redundant error constructors', t = }, {message: 'The error constructor "BadError" is not compatible'}); }); +test('should handle minified constructors correctly using instance name', t => { + class CustomError extends Error { + constructor(message) { + super(message); + this.name = 'CustomError'; + } + } + + // Simulate minification by changing constructor name + Object.defineProperty(CustomError, 'name', { + value: 'a', // Minified name + configurable: true, + }); + + addKnownErrorConstructor(CustomError); + + const error = new CustomError('test message'); + const serialized = serializeError(error); + t.is(serialized.name, 'CustomError'); + + const deserialized = deserializeError(serialized); + t.true(deserialized instanceof CustomError); + t.is(deserialized.name, 'CustomError'); + t.is(deserialized.message, 'test message'); +}); + test('should deserialize plain object', t => { const object = { message: 'error message',