Skip to content

Commit 10b5631

Browse files
author
Robert Jackson
committed
Migrate TransitionAbortedError to builder + interface.
Avoid trying to manually extend from a native error, instead use a normal `Error` and add our name/code to it.
1 parent fe81e70 commit 10b5631

File tree

7 files changed

+32
-38
lines changed

7 files changed

+32
-38
lines changed

lib/router/route-info.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import InternalTransition, {
99
QUERY_PARAMS_SYMBOL,
1010
} from './transition';
1111
import { isParam, isPromise, merge } from './utils';
12+
import {buildTransitionAborted} from './transition-aborted-error';
1213

1314
interface IModel {
1415
id?: string | number;
@@ -372,7 +373,7 @@ export default class InternalRouteInfo<T extends Route> {
372373

373374
private checkForAbort<U>(transition: InternalTransition<T>, value: U) {
374375
if (transition.isAborted) {
375-
throw new Error('Transition aborted');
376+
throw buildTransitionAborted();
376377
}
377378

378379
return value;

lib/router/router.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import InternalTransition, {
1414
QUERY_PARAMS_SYMBOL,
1515
STATE_SYMBOL,
1616
} from './transition';
17-
import TransitionAbortedError from './transition-aborted-error';
17+
import { buildTransitionAborted, isTransitionAborted } from './transition-aborted-error';
1818
import { TransitionIntent } from './transition-intent';
1919
import NamedTransitionIntent from './transition-intent/named-transition-intent';
2020
import URLTransitionIntent from './transition-intent/url-transition-intent';
@@ -371,7 +371,7 @@ export default abstract class Router<T extends Route> {
371371
// Resolve with the final route.
372372
return routeInfos[routeInfos.length - 1].route!;
373373
} catch (e) {
374-
if (!(e instanceof TransitionAbortedError)) {
374+
if (!isTransitionAborted(e)) {
375375
let infos = transition[STATE_SYMBOL]!.routeInfos;
376376
transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route);
377377
transition.abort();
@@ -524,7 +524,7 @@ export default abstract class Router<T extends Route> {
524524
}
525525

526526
if (transition && transition.isAborted) {
527-
throw new TransitionAbortedError();
527+
throw buildTransitionAborted();
528528
}
529529

530530
route.context = context;
@@ -538,7 +538,7 @@ export default abstract class Router<T extends Route> {
538538
}
539539

540540
if (transition && transition.isAborted) {
541-
throw new TransitionAbortedError();
541+
throw buildTransitionAborted();
542542
}
543543

544544
currentRouteInfos.push(routeInfo);
Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
1-
export interface TransitionAbortedErrorContructor {
2-
new (message?: string): ITransitionAbortedError;
3-
readonly prototype: ITransitionAbortedError;
1+
export interface TransitionAbortedError extends Error {
2+
name: 'TransitionAborted';
3+
code: 'TRANSITION_ABORTED';
44
}
55

6-
export interface ITransitionAbortedError extends Error {
7-
constructor: TransitionAbortedErrorContructor;
6+
export function isTransitionAborted(maybeError: unknown): maybeError is TransitionAbortedError {
7+
return (
8+
typeof maybeError === 'object' &&
9+
maybeError !== null &&
10+
(maybeError as TransitionAbortedError).code === 'TRANSITION_ABORTED'
11+
);
812
}
913

10-
const TransitionAbortedError: TransitionAbortedErrorContructor = (function () {
11-
TransitionAbortedError.prototype = Object.create(Error.prototype);
12-
TransitionAbortedError.prototype.constructor = TransitionAbortedError;
14+
export function buildTransitionAborted(): TransitionAbortedError {
15+
let error = new Error('TransitionAborted') as TransitionAbortedError;
16+
error.name = 'TransitionAborted';
17+
error.code = 'TRANSITION_ABORTED';
1318

14-
function TransitionAbortedError(this: ITransitionAbortedError, message?: string) {
15-
let error = Error.call(this, message);
16-
this.name = 'TransitionAborted';
17-
this.message = message || 'TransitionAborted';
18-
19-
if (Error.captureStackTrace) {
20-
Error.captureStackTrace(this, TransitionAbortedError);
21-
} else {
22-
this.stack = error.stack;
23-
}
24-
}
25-
26-
return TransitionAbortedError as any;
27-
})();
28-
29-
export default TransitionAbortedError;
19+
return error;
20+
}

lib/router/transition-state.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Dict } from './core';
33
import InternalRouteInfo, { Route, ResolvedRouteInfo } from './route-info';
44
import Transition from './transition';
55
import { forEach, promiseLabel } from './utils';
6+
import { buildTransitionAborted } from './transition-aborted-error';
67

78
interface IParams {
89
[key: string]: unknown;
@@ -88,7 +89,7 @@ export default class TransitionState<T extends Route> {
8889
// Proceed after ensuring that the redirect hook
8990
// didn't abort this transition by transitioning elsewhere.
9091
if (transition.isAborted) {
91-
throw new Error('Transition aborted');
92+
throw buildTransitionAborted();
9293
}
9394

9495
return resolveOneRouteInfo();

lib/router/transition.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Promise } from 'rsvp';
22
import { Dict, Maybe, Option } from './core';
33
import InternalRouteInfo, { Route, RouteInfo, RouteInfoWithAttributes } from './route-info';
44
import Router from './router';
5-
import TransitionAborted, { ITransitionAbortedError } from './transition-aborted-error';
5+
import { TransitionAbortedError, buildTransitionAborted } from './transition-aborted-error';
66
import { OpaqueIntent } from './transition-intent';
77
import TransitionState, { TransitionError } from './transition-state';
88
import { log, promiseLabel } from './utils';
@@ -439,9 +439,10 @@ export default class Transition<T extends Route> implements Partial<Promise<T>>
439439
440440
Logs and returns an instance of TransitionAborted.
441441
*/
442-
export function logAbort(transition: Transition<any>): ITransitionAbortedError {
442+
export function logAbort(transition: Transition<any>): TransitionAbortedError {
443443
log(transition.router, transition.sequence, 'detected abort.');
444-
return new TransitionAborted();
444+
445+
return buildTransitionAborted();
445446
}
446447

447448
export function isTransition(obj: unknown): obj is typeof Transition {

tests/test_helpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import Router, { Route, Transition } from 'router';
33
import { Dict } from 'router/core';
44
import RouteInfo, { UnresolvedRouteInfoByParam } from 'router/route-info';
55
import { logAbort, PublicTransition } from 'router/transition';
6-
import TransitionAbortedError from 'router/transition-aborted-error';
76
import { TransitionError } from 'router/transition-state';
87
import { UnrecognizedURLError } from 'router/unrecognized-url-error';
98
import { configure, resolve } from 'rsvp';
9+
import { isTransitionAborted } from 'router/transition-aborted-error';
1010

1111
QUnit.config.testTimeout = 1000;
1212

@@ -45,7 +45,7 @@ function module(name: string, options?: any) {
4545

4646
function assertAbort(assert: Assert) {
4747
return function _assertAbort(e: Error) {
48-
assert.ok(e instanceof TransitionAbortedError, 'transition was redirected/aborted');
48+
assert.ok(isTransitionAborted(e), 'transition was redirected/aborted');
4949
};
5050
}
5151

tests/transition-aborted-error_test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import TransitionAbortedError from 'router/transition-aborted-error';
1+
import { isTransitionAborted, buildTransitionAborted } from 'router/transition-aborted-error';
22
import { module, test } from './test_helpers';
33

44
module('transition-aborted-error');
@@ -7,7 +7,7 @@ test('correct inheritance and name', function (assert) {
77
let error;
88

99
try {
10-
throw new TransitionAbortedError('Message');
10+
throw buildTransitionAborted();
1111
} catch (e) {
1212
error = e;
1313
}
@@ -19,6 +19,6 @@ test('correct inheritance and name', function (assert) {
1919
"TransitionAbortedError has the name 'TransitionAborted'"
2020
);
2121

22-
assert.ok(error instanceof TransitionAbortedError);
22+
assert.ok(isTransitionAborted(error));
2323
assert.ok(error instanceof Error);
2424
});

0 commit comments

Comments
 (0)