diff --git a/lib/router/transition.ts b/lib/router/transition.ts index 3a43749..c1cd0b3 100644 --- a/lib/router/transition.ts +++ b/lib/router/transition.ts @@ -28,6 +28,7 @@ export type OpaqueTransition = PublicTransition; export const STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; export const PARAMS_SYMBOL = `__PARAMS__-261986232992830203-23323`; export const QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; +export const REDIRECT_DESTINATION_SYMBOL = `__RDS__-2619863929824844-32323`; /** A Transition is a thenable (a promise-like object) that represents @@ -71,6 +72,7 @@ export default class Transition implements Partial> isCausedByAbortingReplaceTransition = false; _visibleQueryParams: Dict = {}; isIntermediate = false; + [REDIRECT_DESTINATION_SYMBOL]?: Transition; /** In non-production builds, this function will return the stack that this Transition was @@ -309,6 +311,7 @@ export default class Transition implements Partial> } redirect(newTransition: Transition) { + this[REDIRECT_DESTINATION_SYMBOL] = newTransition; this.rollback(); this.router.routeWillChange(newTransition); } @@ -419,10 +422,9 @@ export default class Transition implements Partial> @public */ followRedirects(): Promise { - let router = this.router; - return this.promise!.catch(function (reason) { - if (router.activeTransition) { - return router.activeTransition.followRedirects(); + return this.promise!.catch((reason) => { + if (this[REDIRECT_DESTINATION_SYMBOL]) { + return this[REDIRECT_DESTINATION_SYMBOL].followRedirects(); } return Promise.reject(reason); }); diff --git a/tests/router_test.ts b/tests/router_test.ts index 44340ba..bc28934 100644 --- a/tests/router_test.ts +++ b/tests/router_test.ts @@ -4682,6 +4682,35 @@ scenarios.forEach(function (scenario) { }); }); + test('Transition#followRedirects() works correctly when redirecting from an async model hook', function (assert) { + assert.expect(2); + + routes.index = createHandler('index', { + beforeModel: function () { + return Promise.resolve(true).then(() => { + return router.transitionTo('about'); + }); + }, + }); + + routes.about = createHandler('about', { + setup: function () { + assert.ok(true, 'about#setup was called'); + }, + }); + + router + .transitionTo('/index') + .followRedirects() + .then(function (handler: Route) { + assert.equal( + handler, + routes.about, + 'followRedirects works with redirect from async hook transitions' + ); + }); + }); + test("Returning a redirecting Transition from a model hook doesn't cause things to explode", function (assert) { assert.expect(2);