Skip to content

Commit

Permalink
refactor(router): combine functions for getting loaded config (angula…
Browse files Browse the repository at this point in the history
…r#45613)

There are two functions which do the same thing and are meant to search
for the closest loaded config in the `ActivatedRouteSnapshot` parent
tree. These can be combined to reduce code duplication.

One difference in the current implementation is the early exit for the
implementation in `activate_routes` when `route.component` is defined.
This early exit takes advantage of the fact that the component must then
also have a `RouterOutlet`, which injects `ComponentFactoryResolver`,
which would end up being the same one as what would be found if we
continued to look up the parent tree. This is only a tiny optimization
that will actually break when we add `providers` as a feature to the
`Route` config. In this scenario, we _must_ find the correct injector
in the parent routes and cannot rely on a parent `RouterOutlet` since
there may be some route with a providers list in between.

PR Close angular#45613
  • Loading branch information
atscott authored and dylhunn committed Apr 14, 2022
1 parent e250db4 commit 000363e
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 24 deletions.
3 changes: 3 additions & 0 deletions packages/core/test/bundling/router/bundle.golden_symbols.json
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,9 @@
{
"name": "getChildRouteGuards"
},
{
"name": "getClosestLoadedConfig"
},
{
"name": "getClosureSafeProperty"
},
Expand Down
13 changes: 2 additions & 11 deletions packages/router/src/operators/activate_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {NavigationTransition} from '../router';
import {ChildrenOutletContexts} from '../router_outlet_context';
import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute, RouterState} from '../router_state';
import {forEach} from '../utils/collection';
import {getClosestLoadedConfig} from '../utils/config';
import {nodeChildrenAsMap, TreeNode} from '../utils/tree';

export const activateRoutes =
Expand Down Expand Up @@ -192,7 +193,7 @@ export class ActivateRoutes {
advanceActivatedRoute(stored.route.value);
this.activateChildRoutes(futureNode, null, context.children);
} else {
const config = parentLoadedConfig(future.snapshot);
const config = getClosestLoadedConfig(future.snapshot);
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;

context.attachRef = null;
Expand All @@ -213,13 +214,3 @@ export class ActivateRoutes {
}
}
}

function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null {
for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig;
if (route && route._loadedConfig) return route._loadedConfig;
if (route && route.component) return null;
}

return null;
}
22 changes: 21 additions & 1 deletion packages/router/src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
*/

import {EmptyOutletComponent} from '../components/empty_outlet';
import {Route, Routes} from '../models';
import {LoadedRouterConfig, Route, Routes} from '../models';
import {ActivatedRouteSnapshot} from '../router_state';
import {PRIMARY_OUTLET} from '../shared';

export function validateConfig(config: Routes, parentPath: string = ''): void {
Expand Down Expand Up @@ -133,3 +134,22 @@ export function sortByMatchingOutlets(routes: Routes, outletName: string): Route
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
return sortedConfig;
}

/**
* Gets the first loaded config in the snapshot's parent tree.
*
* Returns `null` if there is no parent lazy loaded config.
*
* Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
* also used for getting the correct injector to use for creating components.
*/
export function getClosestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null {
if (!snapshot) return null;

for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig;
if (route && route._loadedConfig) return route._loadedConfig;
}

return null;
}
14 changes: 2 additions & 12 deletions packages/router/src/utils/preactivation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

import {Injector} from '@angular/core';

import {LoadedRouterConfig, RunGuardsAndResolvers} from '../models';
import {RunGuardsAndResolvers} from '../models';
import {ChildrenOutletContexts, OutletContext} from '../router_outlet_context';
import {ActivatedRouteSnapshot, equalParamsAndUrlSegments, RouterStateSnapshot} from '../router_state';
import {equalPath} from '../url_tree';
import {forEach, shallowEqual} from '../utils/collection';
import {getClosestLoadedConfig} from '../utils/config';
import {nodeChildrenAsMap, TreeNode} from '../utils/tree';

export class CanActivate {
Expand Down Expand Up @@ -54,17 +55,6 @@ export function getToken(
return injector.get(token);
}

function getClosestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null {
if (!snapshot) return null;

for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig;
if (route && route._loadedConfig) return route._loadedConfig;
}

return null;
}

function getChildRouteGuards(
futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>|null,
contexts: ChildrenOutletContexts|null, futurePath: ActivatedRouteSnapshot[], checks: Checks = {
Expand Down

0 comments on commit 000363e

Please sign in to comment.