Skip to content

Commit

Permalink
Simplify stack track merging to fix source maps.
Browse files Browse the repository at this point in the history
  • Loading branch information
zewish committed Jan 7, 2024
1 parent 3f362c9 commit d648554
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 41 deletions.
57 changes: 32 additions & 25 deletions src/__tests__/errors.test.ts
@@ -1,32 +1,32 @@
import { PersistError, RehydrateError } from '../errors';

describe('errors.ts', () => {
const extractParentErrorStack = (errorInstance: Error): string => {
const stackLines = errorInstance.stack!.split('\n');
return stackLines
.slice(2, stackLines.length)
.join('\n');
};

describe('PersistError', () => {
it('extends Error', () => {
const instance = new PersistError(new Error());
const error = new Error('ERROR 1-0');
const instance = new PersistError(error);

expect(instance).toBeInstanceOf(Error);
expect(instance).toBeInstanceOf(PersistError);
expect(instance.message).toEqual('redux-remember: persist error');
expect(instance.originalError).toEqual(error);
expect(instance.message).toEqual(`${error.name}: ${error.message}`);
});

it('copies the stack trace of wrapped Error', () => {
const error = new Error('ERROR 1');
const error = new Error('ERROR 1-1');
const errorStackLines = error.stack!.split('\n');
const errorStackOnly = errorStackLines
.slice(1, errorStackLines.length)
.join('\n');

const instance = new PersistError(error);
const instanceMessage = instance.stack!.slice(
0,
instance.stack!.indexOf('\n')
);
const instanceStackLine1 = instance.stack!.split('\n')[1];

expect(instanceMessage).toEqual(`PersistError: ${instance.message}`);
expect(extractParentErrorStack(instance)).toEqual(error.stack);
expect(instance.stack).toEqual(
`PersistError: Error: ${error.message}\n`
+ `${instanceStackLine1}\n`
+ `${errorStackOnly}`
);
});

it('does not break when an invalid error is wrapped', () => {
Expand All @@ -36,23 +36,30 @@ describe('errors.ts', () => {

describe('RehydrateError', () => {
it('extends Error', () => {
const instance = new RehydrateError(new Error());
const error = new Error('ERROR 2-0');
const instance = new RehydrateError(error);

expect(instance).toBeInstanceOf(Error);
expect(instance).toBeInstanceOf(RehydrateError);
expect(instance.message).toEqual('redux-remember: rehydrate error');
expect(instance.originalError).toEqual(error);
expect(instance.message).toEqual(`${error.name}: ${error.message}`);
});

it('copies the stack trace of wrapped Error', () => {
const error = new Error('ERROR 2');
const error = new Error('ERROR 1-1');
const errorStackLines = error.stack!.split('\n');
const errorStackOnly = errorStackLines
.slice(1, errorStackLines.length)
.join('\n');

const instance = new RehydrateError(error);
const instanceMessage = instance.stack!.slice(
0,
instance.stack!.indexOf('\n')
);
const instanceStackLine1 = instance.stack!.split('\n')[1];

expect(instanceMessage).toEqual(`RehydrateError: ${instance.message}`);
expect(extractParentErrorStack(instance)).toEqual(error.stack);
expect(instance.stack).toEqual(
`RehydrateError: Error: ${error.message}\n`
+ `${instanceStackLine1}\n`
+ `${errorStackOnly}`
);
});

it('does not break when an invalid error is wrapped', () => {
Expand Down
36 changes: 20 additions & 16 deletions src/errors.ts
@@ -1,28 +1,32 @@
class CustomError extends Error {
constructor(message: string, previousError: unknown) {
const prevStack = (previousError as Error)?.stack || '';
originalError?: Error;

constructor(originalError: unknown) {
const isOrigErrorValid = originalError instanceof Error;
const prevStackLines = isOrigErrorValid
? originalError.stack?.split('\n')
: [];

super(isOrigErrorValid
? `${originalError.name}: ${originalError.message}`
: '');

super(message);
this.name = this.constructor.name;
if (isOrigErrorValid) {
this.originalError = originalError;
}

if (prevStack && this.stack) {
if (prevStackLines?.length && this.stack) {
this.stack = this.stack
.split('\n')
.slice(0, 2)
.concat(prevStack)
.concat(
prevStackLines.slice(1, prevStackLines.length)
)
.join('\n');
}
}
}

export class PersistError extends CustomError {
constructor(previousError: unknown) {
super('redux-remember: persist error', previousError);
}
}

export class RehydrateError extends CustomError {
constructor(previousError: unknown) {
super('redux-remember: rehydrate error', previousError);
}
}
export class PersistError extends CustomError {}
export class RehydrateError extends CustomError {}

0 comments on commit d648554

Please sign in to comment.