@angular/router 14.0.0-next.11 → 14.0.0-next.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/esm2020/src/apply_redirects.mjs +56 -46
  2. package/esm2020/src/components/empty_outlet.mjs +3 -3
  3. package/esm2020/src/create_url_tree.mjs +25 -11
  4. package/esm2020/src/directives/router_link.mjs +6 -6
  5. package/esm2020/src/directives/router_link_active.mjs +3 -3
  6. package/esm2020/src/directives/router_outlet.mjs +24 -15
  7. package/esm2020/src/models.mjs +2 -7
  8. package/esm2020/src/operators/activate_routes.mjs +7 -14
  9. package/esm2020/src/operators/apply_redirects.mjs +3 -3
  10. package/esm2020/src/operators/resolve_data.mjs +5 -12
  11. package/esm2020/src/page_title_strategy.mjs +3 -3
  12. package/esm2020/src/recognize.mjs +24 -6
  13. package/esm2020/src/router.mjs +9 -6
  14. package/esm2020/src/router_config_loader.mjs +29 -18
  15. package/esm2020/src/router_module.mjs +10 -9
  16. package/esm2020/src/router_outlet_context.mjs +6 -1
  17. package/esm2020/src/router_preloader.mjs +31 -24
  18. package/esm2020/src/router_scroller.mjs +3 -3
  19. package/esm2020/src/router_state.mjs +3 -3
  20. package/esm2020/src/url_tree.mjs +1 -1
  21. package/esm2020/src/utils/config.mjs +44 -1
  22. package/esm2020/src/utils/config_matching.mjs +4 -1
  23. package/esm2020/src/utils/preactivation.mjs +5 -14
  24. package/esm2020/src/version.mjs +1 -1
  25. package/esm2020/testing/src/router_testing_module.mjs +4 -4
  26. package/fesm2015/router.mjs +719 -625
  27. package/fesm2015/router.mjs.map +1 -1
  28. package/fesm2015/testing.mjs +5 -5
  29. package/fesm2015/upgrade.mjs +1 -1
  30. package/fesm2020/router.mjs +709 -625
  31. package/fesm2020/router.mjs.map +1 -1
  32. package/fesm2020/testing.mjs +5 -5
  33. package/fesm2020/upgrade.mjs +1 -1
  34. package/package.json +4 -4
  35. package/router.d.ts +54 -14
  36. package/testing/testing.d.ts +1 -1
  37. package/upgrade/upgrade.d.ts +1 -1
@@ -1,13 +1,13 @@
1
1
  /**
2
- * @license Angular v14.0.0-next.11
2
+ * @license Angular v14.0.0-next.14
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, NgModuleRef, InjectionToken, InjectFlags, NgModuleFactory, ɵConsole, NgZone, Injectable, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
8
+ import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, ComponentFactoryResolver, createEnvironmentInjector, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
9
9
  import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
10
- import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, refCount, finalize, mergeAll } from 'rxjs/operators';
10
+ import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, mapTo, finalize, refCount, mergeAll } from 'rxjs/operators';
11
11
  import * as i3 from '@angular/common';
12
12
  import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
13
13
  import * as i1 from '@angular/platform-browser';
@@ -1362,7 +1362,6 @@ class ActivatedRoute {
1362
1362
  /** The outlet name of the route, a constant. */
1363
1363
  outlet,
1364
1364
  /** The component of the route, a constant. */
1365
- // TODO(vsavkin): remove |string
1366
1365
  component, futureSnapshot) {
1367
1366
  this.url = url;
1368
1367
  this.params = params;
@@ -1518,7 +1517,7 @@ class ActivatedRouteSnapshot {
1518
1517
  /** The outlet name of the route */
1519
1518
  outlet,
1520
1519
  /** The component of the route */
1521
- component, routeConfig, urlSegment, lastPathIndex, resolve) {
1520
+ component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
1522
1521
  this.url = url;
1523
1522
  this.params = params;
1524
1523
  this.queryParams = queryParams;
@@ -1529,6 +1528,7 @@ class ActivatedRouteSnapshot {
1529
1528
  this.routeConfig = routeConfig;
1530
1529
  this._urlSegment = urlSegment;
1531
1530
  this._lastPathIndex = lastPathIndex;
1531
+ this._correctedLastPathIndex = correctedLastPathIndex !== null && correctedLastPathIndex !== void 0 ? correctedLastPathIndex : lastPathIndex;
1532
1532
  this._resolve = resolve;
1533
1533
  }
1534
1534
  /** The root of the router state */
@@ -1713,6 +1713,7 @@ function createActivatedRoute(c) {
1713
1713
  * found in the LICENSE file at https://angular.io/license
1714
1714
  */
1715
1715
  function createUrlTree(route, urlTree, commands, queryParams, fragment) {
1716
+ var _a, _b;
1716
1717
  if (commands.length === 0) {
1717
1718
  return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);
1718
1719
  }
@@ -1720,11 +1721,27 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
1720
1721
  if (nav.toRoot()) {
1721
1722
  return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
1722
1723
  }
1723
- const startingPosition = findStartingPosition(nav, urlTree, route);
1724
- const segmentGroup = startingPosition.processChildren ?
1725
- updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
1726
- updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
1727
- return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
1724
+ function createTreeUsingPathIndex(lastPathIndex) {
1725
+ var _a;
1726
+ const startingPosition = findStartingPosition(nav, urlTree, (_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._urlSegment, lastPathIndex);
1727
+ const segmentGroup = startingPosition.processChildren ?
1728
+ updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
1729
+ updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
1730
+ return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
1731
+ }
1732
+ // Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
1733
+ // may be the case. Since we try to access it at an earlier point before the refactor to add the
1734
+ // warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
1735
+ // didn't before.
1736
+ const result = createTreeUsingPathIndex((_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._lastPathIndex);
1737
+ // Check if application is relying on `relativeLinkResolution: 'legacy'`
1738
+ if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
1739
+ const correctedResult = createTreeUsingPathIndex((_b = route.snapshot) === null || _b === void 0 ? void 0 : _b._correctedLastPathIndex);
1740
+ if (correctedResult.toString() !== result.toString()) {
1741
+ console.warn(`relativeLinkResolution: 'legacy' is deprecated and will be removed in a future version of Angular. The link to ${result.toString()} will change to ${correctedResult.toString()} if the code is not updated before then.`);
1742
+ }
1743
+ }
1744
+ return result;
1728
1745
  }
1729
1746
  function isMatrixParams(command) {
1730
1747
  return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
@@ -1829,12 +1846,11 @@ class Position {
1829
1846
  this.index = index;
1830
1847
  }
1831
1848
  }
1832
- function findStartingPosition(nav, tree, route) {
1849
+ function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
1833
1850
  if (nav.isAbsolute) {
1834
1851
  return new Position(tree.root, true, 0);
1835
1852
  }
1836
- if (route.snapshot._lastPathIndex === -1) {
1837
- const segmentGroup = route.snapshot._urlSegment;
1853
+ if (lastPathIndex === -1) {
1838
1854
  // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
1839
1855
  // see issue #26224, #13011, #35687
1840
1856
  // However, if the ActivatedRoute is the root we should process children like above.
@@ -1842,8 +1858,8 @@ function findStartingPosition(nav, tree, route) {
1842
1858
  return new Position(segmentGroup, processChildren, 0);
1843
1859
  }
1844
1860
  const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
1845
- const index = route.snapshot._lastPathIndex + modifier;
1846
- return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
1861
+ const index = lastPathIndex + modifier;
1862
+ return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
1847
1863
  }
1848
1864
  function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
1849
1865
  let g = group;
@@ -2006,181 +2022,76 @@ function compare(path, params, segment) {
2006
2022
  * Use of this source code is governed by an MIT-style license that can be
2007
2023
  * found in the LICENSE file at https://angular.io/license
2008
2024
  */
2009
- const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2010
- new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2011
- .activate(rootContexts);
2012
- return t;
2013
- });
2014
- class ActivateRoutes {
2015
- constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2016
- this.routeReuseStrategy = routeReuseStrategy;
2017
- this.futureState = futureState;
2018
- this.currState = currState;
2019
- this.forwardEvent = forwardEvent;
2020
- }
2021
- activate(parentContexts) {
2022
- const futureRoot = this.futureState._root;
2023
- const currRoot = this.currState ? this.currState._root : null;
2024
- this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2025
- advanceActivatedRoute(this.futureState.root);
2026
- this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2027
- }
2028
- // De-activate the child route that are not re-used for the future state
2029
- deactivateChildRoutes(futureNode, currNode, contexts) {
2030
- const children = nodeChildrenAsMap(currNode);
2031
- // Recurse on the routes active in the future state to de-activate deeper children
2032
- futureNode.children.forEach(futureChild => {
2033
- const childOutletName = futureChild.value.outlet;
2034
- this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2035
- delete children[childOutletName];
2036
- });
2037
- // De-activate the routes that will not be re-used
2038
- forEach(children, (v, childName) => {
2039
- this.deactivateRouteAndItsChildren(v, contexts);
2040
- });
2041
- }
2042
- deactivateRoutes(futureNode, currNode, parentContext) {
2043
- const future = futureNode.value;
2044
- const curr = currNode ? currNode.value : null;
2045
- if (future === curr) {
2046
- // Reusing the node, check to see if the children need to be de-activated
2047
- if (future.component) {
2048
- // If we have a normal route, we need to go through an outlet.
2049
- const context = parentContext.getContext(future.outlet);
2050
- if (context) {
2051
- this.deactivateChildRoutes(futureNode, currNode, context.children);
2052
- }
2053
- }
2054
- else {
2055
- // if we have a componentless route, we recurse but keep the same outlet map.
2056
- this.deactivateChildRoutes(futureNode, currNode, parentContext);
2057
- }
2058
- }
2059
- else {
2060
- if (curr) {
2061
- // Deactivate the current route which will not be re-used
2062
- this.deactivateRouteAndItsChildren(currNode, parentContext);
2063
- }
2064
- }
2025
+ /**
2026
+ * Store contextual information about a `RouterOutlet`
2027
+ *
2028
+ * @publicApi
2029
+ */
2030
+ class OutletContext {
2031
+ constructor() {
2032
+ this.outlet = null;
2033
+ this.route = null;
2034
+ /**
2035
+ * @deprecated Passing a resolver to retrieve a component factory is not required and is
2036
+ * deprecated since v14.
2037
+ */
2038
+ this.resolver = null;
2039
+ this.injector = null;
2040
+ this.children = new ChildrenOutletContexts();
2041
+ this.attachRef = null;
2065
2042
  }
2066
- deactivateRouteAndItsChildren(route, parentContexts) {
2067
- // If there is no component, the Route is never attached to an outlet (because there is no
2068
- // component to attach).
2069
- if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2070
- this.detachAndStoreRouteSubtree(route, parentContexts);
2071
- }
2072
- else {
2073
- this.deactivateRouteAndOutlet(route, parentContexts);
2074
- }
2043
+ }
2044
+ /**
2045
+ * Store contextual information about the children (= nested) `RouterOutlet`
2046
+ *
2047
+ * @publicApi
2048
+ */
2049
+ class ChildrenOutletContexts {
2050
+ constructor() {
2051
+ // contexts for child outlets, by name.
2052
+ this.contexts = new Map();
2075
2053
  }
2076
- detachAndStoreRouteSubtree(route, parentContexts) {
2077
- const context = parentContexts.getContext(route.value.outlet);
2078
- const contexts = context && route.value.component ? context.children : parentContexts;
2079
- const children = nodeChildrenAsMap(route);
2080
- for (const childOutlet of Object.keys(children)) {
2081
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2082
- }
2083
- if (context && context.outlet) {
2084
- const componentRef = context.outlet.detach();
2085
- const contexts = context.children.onOutletDeactivated();
2086
- this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2087
- }
2054
+ /** Called when a `RouterOutlet` directive is instantiated */
2055
+ onChildOutletCreated(childName, outlet) {
2056
+ const context = this.getOrCreateContext(childName);
2057
+ context.outlet = outlet;
2058
+ this.contexts.set(childName, context);
2088
2059
  }
2089
- deactivateRouteAndOutlet(route, parentContexts) {
2090
- const context = parentContexts.getContext(route.value.outlet);
2091
- // The context could be `null` if we are on a componentless route but there may still be
2092
- // children that need deactivating.
2093
- const contexts = context && route.value.component ? context.children : parentContexts;
2094
- const children = nodeChildrenAsMap(route);
2095
- for (const childOutlet of Object.keys(children)) {
2096
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2097
- }
2098
- if (context && context.outlet) {
2099
- // Destroy the component
2100
- context.outlet.deactivate();
2101
- // Destroy the contexts for all the outlets that were in the component
2102
- context.children.onOutletDeactivated();
2103
- // Clear the information about the attached component on the context but keep the reference to
2104
- // the outlet.
2060
+ /**
2061
+ * Called when a `RouterOutlet` directive is destroyed.
2062
+ * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2063
+ * re-created later.
2064
+ */
2065
+ onChildOutletDestroyed(childName) {
2066
+ const context = this.getContext(childName);
2067
+ if (context) {
2068
+ context.outlet = null;
2105
2069
  context.attachRef = null;
2106
- context.resolver = null;
2107
- context.route = null;
2108
2070
  }
2109
2071
  }
2110
- activateChildRoutes(futureNode, currNode, contexts) {
2111
- const children = nodeChildrenAsMap(currNode);
2112
- futureNode.children.forEach(c => {
2113
- this.activateRoutes(c, children[c.value.outlet], contexts);
2114
- this.forwardEvent(new ActivationEnd(c.value.snapshot));
2115
- });
2116
- if (futureNode.children.length) {
2117
- this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2118
- }
2072
+ /**
2073
+ * Called when the corresponding route is deactivated during navigation.
2074
+ * Because the component get destroyed, all children outlet are destroyed.
2075
+ */
2076
+ onOutletDeactivated() {
2077
+ const contexts = this.contexts;
2078
+ this.contexts = new Map();
2079
+ return contexts;
2119
2080
  }
2120
- activateRoutes(futureNode, currNode, parentContexts) {
2121
- const future = futureNode.value;
2122
- const curr = currNode ? currNode.value : null;
2123
- advanceActivatedRoute(future);
2124
- // reusing the node
2125
- if (future === curr) {
2126
- if (future.component) {
2127
- // If we have a normal route, we need to go through an outlet.
2128
- const context = parentContexts.getOrCreateContext(future.outlet);
2129
- this.activateChildRoutes(futureNode, currNode, context.children);
2130
- }
2131
- else {
2132
- // if we have a componentless route, we recurse but keep the same outlet map.
2133
- this.activateChildRoutes(futureNode, currNode, parentContexts);
2134
- }
2135
- }
2136
- else {
2137
- if (future.component) {
2138
- // if we have a normal route, we need to place the component into the outlet and recurse.
2139
- const context = parentContexts.getOrCreateContext(future.outlet);
2140
- if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2141
- const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2142
- this.routeReuseStrategy.store(future.snapshot, null);
2143
- context.children.onOutletReAttached(stored.contexts);
2144
- context.attachRef = stored.componentRef;
2145
- context.route = stored.route.value;
2146
- if (context.outlet) {
2147
- // Attach right away when the outlet has already been instantiated
2148
- // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2149
- context.outlet.attach(stored.componentRef, stored.route.value);
2150
- }
2151
- advanceActivatedRoute(stored.route.value);
2152
- this.activateChildRoutes(futureNode, null, context.children);
2153
- }
2154
- else {
2155
- const config = parentLoadedConfig(future.snapshot);
2156
- const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
2157
- context.attachRef = null;
2158
- context.route = future;
2159
- context.resolver = cmpFactoryResolver;
2160
- if (context.outlet) {
2161
- // Activate the outlet when it has already been instantiated
2162
- // Otherwise it will get activated from its `ngOnInit` when instantiated
2163
- context.outlet.activateWith(future, cmpFactoryResolver);
2164
- }
2165
- this.activateChildRoutes(futureNode, null, context.children);
2166
- }
2167
- }
2168
- else {
2169
- // if we have a componentless route, we recurse but keep the same outlet map.
2170
- this.activateChildRoutes(futureNode, null, parentContexts);
2171
- }
2081
+ onOutletReAttached(contexts) {
2082
+ this.contexts = contexts;
2083
+ }
2084
+ getOrCreateContext(childName) {
2085
+ let context = this.getContext(childName);
2086
+ if (!context) {
2087
+ context = new OutletContext();
2088
+ this.contexts.set(childName, context);
2172
2089
  }
2090
+ return context;
2173
2091
  }
2174
- }
2175
- function parentLoadedConfig(snapshot) {
2176
- for (let s = snapshot.parent; s; s = s.parent) {
2177
- const route = s.routeConfig;
2178
- if (route && route._loadedConfig)
2179
- return route._loadedConfig;
2180
- if (route && route.component)
2181
- return null;
2092
+ getContext(childName) {
2093
+ return this.contexts.get(childName) || null;
2182
2094
  }
2183
- return null;
2184
2095
  }
2185
2096
 
2186
2097
  /**
@@ -2190,182 +2101,13 @@ function parentLoadedConfig(snapshot) {
2190
2101
  * Use of this source code is governed by an MIT-style license that can be
2191
2102
  * found in the LICENSE file at https://angular.io/license
2192
2103
  */
2193
- class LoadedRouterConfig {
2194
- constructor(routes, module) {
2195
- this.routes = routes;
2196
- this.module = module;
2197
- }
2198
- }
2199
-
2200
2104
  /**
2201
- * @license
2202
- * Copyright Google LLC All Rights Reserved.
2105
+ * @description
2203
2106
  *
2204
- * Use of this source code is governed by an MIT-style license that can be
2205
- * found in the LICENSE file at https://angular.io/license
2206
- */
2207
- /**
2208
- * Simple function check, but generic so type inference will flow. Example:
2107
+ * Acts as a placeholder that Angular dynamically fills based on the current router state.
2209
2108
  *
2210
- * function product(a: number, b: number) {
2211
- * return a * b;
2212
- * }
2213
- *
2214
- * if (isFunction<product>(fn)) {
2215
- * return fn(1, 2);
2216
- * } else {
2217
- * throw "Must provide the `product` function";
2218
- * }
2219
- */
2220
- function isFunction(v) {
2221
- return typeof v === 'function';
2222
- }
2223
- function isBoolean(v) {
2224
- return typeof v === 'boolean';
2225
- }
2226
- function isUrlTree(v) {
2227
- return v instanceof UrlTree;
2228
- }
2229
- function isCanLoad(guard) {
2230
- return guard && isFunction(guard.canLoad);
2231
- }
2232
- function isCanActivate(guard) {
2233
- return guard && isFunction(guard.canActivate);
2234
- }
2235
- function isCanActivateChild(guard) {
2236
- return guard && isFunction(guard.canActivateChild);
2237
- }
2238
- function isCanDeactivate(guard) {
2239
- return guard && isFunction(guard.canDeactivate);
2240
- }
2241
-
2242
- /**
2243
- * @license
2244
- * Copyright Google LLC All Rights Reserved.
2245
- *
2246
- * Use of this source code is governed by an MIT-style license that can be
2247
- * found in the LICENSE file at https://angular.io/license
2248
- */
2249
- const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2250
- function prioritizedGuardValue() {
2251
- return switchMap(obs => {
2252
- return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2253
- .pipe(scan((acc, list) => {
2254
- let isPending = false;
2255
- return list.reduce((innerAcc, val, i) => {
2256
- if (innerAcc !== INITIAL_VALUE)
2257
- return innerAcc;
2258
- // Toggle pending flag if any values haven't been set yet
2259
- if (val === INITIAL_VALUE)
2260
- isPending = true;
2261
- // Any other return values are only valid if we haven't yet hit a pending
2262
- // call. This guarantees that in the case of a guard at the bottom of the
2263
- // tree that returns a redirect, we will wait for the higher priority
2264
- // guard at the top to finish before performing the redirect.
2265
- if (!isPending) {
2266
- // Early return when we hit a `false` value as that should always
2267
- // cancel navigation
2268
- if (val === false)
2269
- return val;
2270
- if (i === list.length - 1 || isUrlTree(val)) {
2271
- return val;
2272
- }
2273
- }
2274
- return innerAcc;
2275
- }, acc);
2276
- }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2277
- take(1));
2278
- });
2279
- }
2280
-
2281
- /**
2282
- * @license
2283
- * Copyright Google LLC All Rights Reserved.
2284
- *
2285
- * Use of this source code is governed by an MIT-style license that can be
2286
- * found in the LICENSE file at https://angular.io/license
2287
- */
2288
- /**
2289
- * Store contextual information about a `RouterOutlet`
2290
- *
2291
- * @publicApi
2292
- */
2293
- class OutletContext {
2294
- constructor() {
2295
- this.outlet = null;
2296
- this.route = null;
2297
- this.resolver = null;
2298
- this.children = new ChildrenOutletContexts();
2299
- this.attachRef = null;
2300
- }
2301
- }
2302
- /**
2303
- * Store contextual information about the children (= nested) `RouterOutlet`
2304
- *
2305
- * @publicApi
2306
- */
2307
- class ChildrenOutletContexts {
2308
- constructor() {
2309
- // contexts for child outlets, by name.
2310
- this.contexts = new Map();
2311
- }
2312
- /** Called when a `RouterOutlet` directive is instantiated */
2313
- onChildOutletCreated(childName, outlet) {
2314
- const context = this.getOrCreateContext(childName);
2315
- context.outlet = outlet;
2316
- this.contexts.set(childName, context);
2317
- }
2318
- /**
2319
- * Called when a `RouterOutlet` directive is destroyed.
2320
- * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2321
- * re-created later.
2322
- */
2323
- onChildOutletDestroyed(childName) {
2324
- const context = this.getContext(childName);
2325
- if (context) {
2326
- context.outlet = null;
2327
- context.attachRef = null;
2328
- }
2329
- }
2330
- /**
2331
- * Called when the corresponding route is deactivated during navigation.
2332
- * Because the component get destroyed, all children outlet are destroyed.
2333
- */
2334
- onOutletDeactivated() {
2335
- const contexts = this.contexts;
2336
- this.contexts = new Map();
2337
- return contexts;
2338
- }
2339
- onOutletReAttached(contexts) {
2340
- this.contexts = contexts;
2341
- }
2342
- getOrCreateContext(childName) {
2343
- let context = this.getContext(childName);
2344
- if (!context) {
2345
- context = new OutletContext();
2346
- this.contexts.set(childName, context);
2347
- }
2348
- return context;
2349
- }
2350
- getContext(childName) {
2351
- return this.contexts.get(childName) || null;
2352
- }
2353
- }
2354
-
2355
- /**
2356
- * @license
2357
- * Copyright Google LLC All Rights Reserved.
2358
- *
2359
- * Use of this source code is governed by an MIT-style license that can be
2360
- * found in the LICENSE file at https://angular.io/license
2361
- */
2362
- /**
2363
- * @description
2364
- *
2365
- * Acts as a placeholder that Angular dynamically fills based on the current router state.
2366
- *
2367
- * Each outlet can have a unique name, determined by the optional `name` attribute.
2368
- * The name cannot be set or changed dynamically. If not set, default value is "primary".
2109
+ * Each outlet can have a unique name, determined by the optional `name` attribute.
2110
+ * The name cannot be set or changed dynamically. If not set, default value is "primary".
2369
2111
  *
2370
2112
  * ```
2371
2113
  * <router-outlet></router-outlet>
@@ -2411,11 +2153,11 @@ class ChildrenOutletContexts {
2411
2153
  * @publicApi
2412
2154
  */
2413
2155
  class RouterOutlet {
2414
- constructor(parentContexts, location, resolver, name, changeDetector) {
2156
+ constructor(parentContexts, location, name, changeDetector, environmentInjector) {
2415
2157
  this.parentContexts = parentContexts;
2416
2158
  this.location = location;
2417
- this.resolver = resolver;
2418
2159
  this.changeDetector = changeDetector;
2160
+ this.environmentInjector = environmentInjector;
2419
2161
  this.activated = null;
2420
2162
  this._activatedRoute = null;
2421
2163
  this.activateEvents = new EventEmitter();
@@ -2450,7 +2192,7 @@ class RouterOutlet {
2450
2192
  }
2451
2193
  else {
2452
2194
  // otherwise the component defined in the configuration is created
2453
- this.activateWith(context.route, context.resolver || null);
2195
+ this.activateWith(context.route, context.injector);
2454
2196
  }
2455
2197
  }
2456
2198
  }
@@ -2509,34 +2251,40 @@ class RouterOutlet {
2509
2251
  this.deactivateEvents.emit(c);
2510
2252
  }
2511
2253
  }
2512
- activateWith(activatedRoute, resolver) {
2254
+ activateWith(activatedRoute, resolverOrInjector) {
2513
2255
  if (this.isActivated) {
2514
2256
  throw new Error('Cannot activate an already activated outlet');
2515
2257
  }
2516
2258
  this._activatedRoute = activatedRoute;
2259
+ const location = this.location;
2517
2260
  const snapshot = activatedRoute._futureSnapshot;
2518
2261
  const component = snapshot.routeConfig.component;
2519
- resolver = resolver || this.resolver;
2520
- const factory = resolver.resolveComponentFactory(component);
2521
2262
  const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
2522
- const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
2523
- this.activated = this.location.createComponent(factory, this.location.length, injector);
2263
+ const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
2264
+ if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
2265
+ const factory = resolverOrInjector.resolveComponentFactory(component);
2266
+ this.activated = location.createComponent(factory, location.length, injector);
2267
+ }
2268
+ else {
2269
+ const environmentInjector = resolverOrInjector !== null && resolverOrInjector !== void 0 ? resolverOrInjector : this.environmentInjector;
2270
+ this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
2271
+ }
2524
2272
  // Calling `markForCheck` to make sure we will run the change detection when the
2525
2273
  // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
2526
2274
  this.changeDetector.markForCheck();
2527
2275
  this.activateEvents.emit(this.activated.instance);
2528
2276
  }
2529
2277
  }
2530
- RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
2531
- RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.11", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterOutlet, decorators: [{
2278
+ RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
2279
+ RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2280
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterOutlet, decorators: [{
2533
2281
  type: Directive,
2534
2282
  args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
2535
2283
  }], ctorParameters: function () {
2536
- return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: undefined, decorators: [{
2284
+ return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
2537
2285
  type: Attribute,
2538
2286
  args: ['name']
2539
- }] }, { type: i0.ChangeDetectorRef }];
2287
+ }] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
2540
2288
  }, propDecorators: { activateEvents: [{
2541
2289
  type: Output,
2542
2290
  args: ['activate']
@@ -2556,14 +2304,378 @@ class OutletInjector {
2556
2304
  this.childContexts = childContexts;
2557
2305
  this.parent = parent;
2558
2306
  }
2559
- get(token, notFoundValue) {
2560
- if (token === ActivatedRoute) {
2561
- return this.route;
2307
+ get(token, notFoundValue) {
2308
+ if (token === ActivatedRoute) {
2309
+ return this.route;
2310
+ }
2311
+ if (token === ChildrenOutletContexts) {
2312
+ return this.childContexts;
2313
+ }
2314
+ return this.parent.get(token, notFoundValue);
2315
+ }
2316
+ }
2317
+ function isComponentFactoryResolver(item) {
2318
+ return !!item.resolveComponentFactory;
2319
+ }
2320
+
2321
+ /**
2322
+ * @license
2323
+ * Copyright Google LLC All Rights Reserved.
2324
+ *
2325
+ * Use of this source code is governed by an MIT-style license that can be
2326
+ * found in the LICENSE file at https://angular.io/license
2327
+ */
2328
+ /**
2329
+ * This component is used internally within the router to be a placeholder when an empty
2330
+ * router-outlet is needed. For example, with a config such as:
2331
+ *
2332
+ * `{path: 'parent', outlet: 'nav', children: [...]}`
2333
+ *
2334
+ * In order to render, there needs to be a component on this config, which will default
2335
+ * to this `EmptyOutletComponent`.
2336
+ */
2337
+ class ɵEmptyOutletComponent {
2338
+ }
2339
+ ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2340
+ ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.14", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
2341
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2342
+ type: Component,
2343
+ args: [{ template: `<router-outlet></router-outlet>` }]
2344
+ }] });
2345
+
2346
+ /**
2347
+ * @license
2348
+ * Copyright Google LLC All Rights Reserved.
2349
+ *
2350
+ * Use of this source code is governed by an MIT-style license that can be
2351
+ * found in the LICENSE file at https://angular.io/license
2352
+ */
2353
+ function getLoadedRoutes(route) {
2354
+ return route._loadedRoutes;
2355
+ }
2356
+ function getLoadedInjector(route) {
2357
+ return route._loadedInjector;
2358
+ }
2359
+ function getProvidersInjector(route) {
2360
+ return route._injector;
2361
+ }
2362
+ function validateConfig(config, parentPath = '') {
2363
+ // forEach doesn't iterate undefined values
2364
+ for (let i = 0; i < config.length; i++) {
2365
+ const route = config[i];
2366
+ const fullPath = getFullPath(parentPath, route);
2367
+ validateNode(route, fullPath);
2368
+ }
2369
+ }
2370
+ function validateNode(route, fullPath) {
2371
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
2372
+ if (!route) {
2373
+ throw new Error(`
2374
+ Invalid configuration of route '${fullPath}': Encountered undefined route.
2375
+ The reason might be an extra comma.
2376
+
2377
+ Example:
2378
+ const routes: Routes = [
2379
+ { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2380
+ { path: 'dashboard', component: DashboardComponent },, << two commas
2381
+ { path: 'detail/:id', component: HeroDetailComponent }
2382
+ ];
2383
+ `);
2384
+ }
2385
+ if (Array.isArray(route)) {
2386
+ throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2387
+ }
2388
+ if (!route.component && !route.children && !route.loadChildren &&
2389
+ (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2390
+ throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2391
+ }
2392
+ if (route.redirectTo && route.children) {
2393
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2394
+ }
2395
+ if (route.redirectTo && route.loadChildren) {
2396
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2397
+ }
2398
+ if (route.children && route.loadChildren) {
2399
+ throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2400
+ }
2401
+ if (route.redirectTo && route.component) {
2402
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
2403
+ }
2404
+ if (route.redirectTo && route.canActivate) {
2405
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2406
+ `so canActivate will never be executed.`);
2407
+ }
2408
+ if (route.path && route.matcher) {
2409
+ throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2410
+ }
2411
+ if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
2412
+ throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
2413
+ }
2414
+ if (route.path === void 0 && route.matcher === void 0) {
2415
+ throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2416
+ }
2417
+ if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2418
+ throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2419
+ }
2420
+ if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2421
+ const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2422
+ throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2423
+ }
2424
+ }
2425
+ if (route.children) {
2426
+ validateConfig(route.children, fullPath);
2427
+ }
2428
+ }
2429
+ function getFullPath(parentPath, currentRoute) {
2430
+ if (!currentRoute) {
2431
+ return parentPath;
2432
+ }
2433
+ if (!parentPath && !currentRoute.path) {
2434
+ return '';
2435
+ }
2436
+ else if (parentPath && !currentRoute.path) {
2437
+ return `${parentPath}/`;
2438
+ }
2439
+ else if (!parentPath && currentRoute.path) {
2440
+ return currentRoute.path;
2441
+ }
2442
+ else {
2443
+ return `${parentPath}/${currentRoute.path}`;
2444
+ }
2445
+ }
2446
+ /**
2447
+ * Makes a copy of the config and adds any default required properties.
2448
+ */
2449
+ function standardizeConfig(r) {
2450
+ const children = r.children && r.children.map(standardizeConfig);
2451
+ const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2452
+ if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2453
+ c.component = ɵEmptyOutletComponent;
2454
+ }
2455
+ return c;
2456
+ }
2457
+ /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2458
+ function getOutlet(route) {
2459
+ return route.outlet || PRIMARY_OUTLET;
2460
+ }
2461
+ /**
2462
+ * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2463
+ * The order of the configs is otherwise preserved.
2464
+ */
2465
+ function sortByMatchingOutlets(routes, outletName) {
2466
+ const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2467
+ sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2468
+ return sortedConfig;
2469
+ }
2470
+ /**
2471
+ * Gets the first injector in the snapshot's parent tree.
2472
+ *
2473
+ * If the `Route` has a static list of providers, the returned injector will be the one created from
2474
+ * those. If it does not exist, the returned injector may come from the parents, which may be from a
2475
+ * loaded config or their static providers.
2476
+ *
2477
+ * Returns `null` if there is neither this nor any parents have a stored injector.
2478
+ *
2479
+ * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
2480
+ * also used for getting the correct injector to use for creating components.
2481
+ */
2482
+ function getClosestRouteInjector(snapshot) {
2483
+ var _a;
2484
+ if (!snapshot)
2485
+ return null;
2486
+ // If the current route has its own injector, which is created from the static providers on the
2487
+ // route itself, we should use that. Otherwise, we start at the parent since we do not want to
2488
+ // include the lazy loaded injector from this route.
2489
+ if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
2490
+ return snapshot.routeConfig._injector;
2491
+ }
2492
+ for (let s = snapshot.parent; s; s = s.parent) {
2493
+ const route = s.routeConfig;
2494
+ // Note that the order here is important. `_loadedInjector` stored on the route with
2495
+ // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
2496
+ // is created from the static providers on that parent route, so it applies to the children as
2497
+ // well, but only if there is no lazy loaded NgModuleRef injector.
2498
+ if (route === null || route === void 0 ? void 0 : route._loadedInjector)
2499
+ return route._loadedInjector;
2500
+ if (route === null || route === void 0 ? void 0 : route._injector)
2501
+ return route._injector;
2502
+ }
2503
+ return null;
2504
+ }
2505
+
2506
+ /**
2507
+ * @license
2508
+ * Copyright Google LLC All Rights Reserved.
2509
+ *
2510
+ * Use of this source code is governed by an MIT-style license that can be
2511
+ * found in the LICENSE file at https://angular.io/license
2512
+ */
2513
+ const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2514
+ new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2515
+ .activate(rootContexts);
2516
+ return t;
2517
+ });
2518
+ class ActivateRoutes {
2519
+ constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2520
+ this.routeReuseStrategy = routeReuseStrategy;
2521
+ this.futureState = futureState;
2522
+ this.currState = currState;
2523
+ this.forwardEvent = forwardEvent;
2524
+ }
2525
+ activate(parentContexts) {
2526
+ const futureRoot = this.futureState._root;
2527
+ const currRoot = this.currState ? this.currState._root : null;
2528
+ this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2529
+ advanceActivatedRoute(this.futureState.root);
2530
+ this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2531
+ }
2532
+ // De-activate the child route that are not re-used for the future state
2533
+ deactivateChildRoutes(futureNode, currNode, contexts) {
2534
+ const children = nodeChildrenAsMap(currNode);
2535
+ // Recurse on the routes active in the future state to de-activate deeper children
2536
+ futureNode.children.forEach(futureChild => {
2537
+ const childOutletName = futureChild.value.outlet;
2538
+ this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2539
+ delete children[childOutletName];
2540
+ });
2541
+ // De-activate the routes that will not be re-used
2542
+ forEach(children, (v, childName) => {
2543
+ this.deactivateRouteAndItsChildren(v, contexts);
2544
+ });
2545
+ }
2546
+ deactivateRoutes(futureNode, currNode, parentContext) {
2547
+ const future = futureNode.value;
2548
+ const curr = currNode ? currNode.value : null;
2549
+ if (future === curr) {
2550
+ // Reusing the node, check to see if the children need to be de-activated
2551
+ if (future.component) {
2552
+ // If we have a normal route, we need to go through an outlet.
2553
+ const context = parentContext.getContext(future.outlet);
2554
+ if (context) {
2555
+ this.deactivateChildRoutes(futureNode, currNode, context.children);
2556
+ }
2557
+ }
2558
+ else {
2559
+ // if we have a componentless route, we recurse but keep the same outlet map.
2560
+ this.deactivateChildRoutes(futureNode, currNode, parentContext);
2561
+ }
2562
+ }
2563
+ else {
2564
+ if (curr) {
2565
+ // Deactivate the current route which will not be re-used
2566
+ this.deactivateRouteAndItsChildren(currNode, parentContext);
2567
+ }
2568
+ }
2569
+ }
2570
+ deactivateRouteAndItsChildren(route, parentContexts) {
2571
+ // If there is no component, the Route is never attached to an outlet (because there is no
2572
+ // component to attach).
2573
+ if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2574
+ this.detachAndStoreRouteSubtree(route, parentContexts);
2575
+ }
2576
+ else {
2577
+ this.deactivateRouteAndOutlet(route, parentContexts);
2578
+ }
2579
+ }
2580
+ detachAndStoreRouteSubtree(route, parentContexts) {
2581
+ const context = parentContexts.getContext(route.value.outlet);
2582
+ const contexts = context && route.value.component ? context.children : parentContexts;
2583
+ const children = nodeChildrenAsMap(route);
2584
+ for (const childOutlet of Object.keys(children)) {
2585
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2586
+ }
2587
+ if (context && context.outlet) {
2588
+ const componentRef = context.outlet.detach();
2589
+ const contexts = context.children.onOutletDeactivated();
2590
+ this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2591
+ }
2592
+ }
2593
+ deactivateRouteAndOutlet(route, parentContexts) {
2594
+ const context = parentContexts.getContext(route.value.outlet);
2595
+ // The context could be `null` if we are on a componentless route but there may still be
2596
+ // children that need deactivating.
2597
+ const contexts = context && route.value.component ? context.children : parentContexts;
2598
+ const children = nodeChildrenAsMap(route);
2599
+ for (const childOutlet of Object.keys(children)) {
2600
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2601
+ }
2602
+ if (context && context.outlet) {
2603
+ // Destroy the component
2604
+ context.outlet.deactivate();
2605
+ // Destroy the contexts for all the outlets that were in the component
2606
+ context.children.onOutletDeactivated();
2607
+ // Clear the information about the attached component on the context but keep the reference to
2608
+ // the outlet.
2609
+ context.attachRef = null;
2610
+ context.resolver = null;
2611
+ context.route = null;
2612
+ }
2613
+ }
2614
+ activateChildRoutes(futureNode, currNode, contexts) {
2615
+ const children = nodeChildrenAsMap(currNode);
2616
+ futureNode.children.forEach(c => {
2617
+ this.activateRoutes(c, children[c.value.outlet], contexts);
2618
+ this.forwardEvent(new ActivationEnd(c.value.snapshot));
2619
+ });
2620
+ if (futureNode.children.length) {
2621
+ this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2622
+ }
2623
+ }
2624
+ activateRoutes(futureNode, currNode, parentContexts) {
2625
+ var _a;
2626
+ const future = futureNode.value;
2627
+ const curr = currNode ? currNode.value : null;
2628
+ advanceActivatedRoute(future);
2629
+ // reusing the node
2630
+ if (future === curr) {
2631
+ if (future.component) {
2632
+ // If we have a normal route, we need to go through an outlet.
2633
+ const context = parentContexts.getOrCreateContext(future.outlet);
2634
+ this.activateChildRoutes(futureNode, currNode, context.children);
2635
+ }
2636
+ else {
2637
+ // if we have a componentless route, we recurse but keep the same outlet map.
2638
+ this.activateChildRoutes(futureNode, currNode, parentContexts);
2639
+ }
2562
2640
  }
2563
- if (token === ChildrenOutletContexts) {
2564
- return this.childContexts;
2641
+ else {
2642
+ if (future.component) {
2643
+ // if we have a normal route, we need to place the component into the outlet and recurse.
2644
+ const context = parentContexts.getOrCreateContext(future.outlet);
2645
+ if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2646
+ const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2647
+ this.routeReuseStrategy.store(future.snapshot, null);
2648
+ context.children.onOutletReAttached(stored.contexts);
2649
+ context.attachRef = stored.componentRef;
2650
+ context.route = stored.route.value;
2651
+ if (context.outlet) {
2652
+ // Attach right away when the outlet has already been instantiated
2653
+ // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2654
+ context.outlet.attach(stored.componentRef, stored.route.value);
2655
+ }
2656
+ advanceActivatedRoute(stored.route.value);
2657
+ this.activateChildRoutes(futureNode, null, context.children);
2658
+ }
2659
+ else {
2660
+ const injector = getClosestRouteInjector(future.snapshot);
2661
+ const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
2662
+ context.attachRef = null;
2663
+ context.route = future;
2664
+ context.resolver = cmpFactoryResolver;
2665
+ context.injector = injector;
2666
+ if (context.outlet) {
2667
+ // Activate the outlet when it has already been instantiated
2668
+ // Otherwise it will get activated from its `ngOnInit` when instantiated
2669
+ context.outlet.activateWith(future, context.injector);
2670
+ }
2671
+ this.activateChildRoutes(futureNode, null, context.children);
2672
+ }
2673
+ }
2674
+ else {
2675
+ // if we have a componentless route, we recurse but keep the same outlet map.
2676
+ this.activateChildRoutes(futureNode, null, parentContexts);
2677
+ }
2565
2678
  }
2566
- return this.parent.get(token, notFoundValue);
2567
2679
  }
2568
2680
  }
2569
2681
 
@@ -2575,22 +2687,39 @@ class OutletInjector {
2575
2687
  * found in the LICENSE file at https://angular.io/license
2576
2688
  */
2577
2689
  /**
2578
- * This component is used internally within the router to be a placeholder when an empty
2579
- * router-outlet is needed. For example, with a config such as:
2690
+ * Simple function check, but generic so type inference will flow. Example:
2580
2691
  *
2581
- * `{path: 'parent', outlet: 'nav', children: [...]}`
2692
+ * function product(a: number, b: number) {
2693
+ * return a * b;
2694
+ * }
2582
2695
  *
2583
- * In order to render, there needs to be a component on this config, which will default
2584
- * to this `EmptyOutletComponent`.
2696
+ * if (isFunction<product>(fn)) {
2697
+ * return fn(1, 2);
2698
+ * } else {
2699
+ * throw "Must provide the `product` function";
2700
+ * }
2585
2701
  */
2586
- class ɵEmptyOutletComponent {
2702
+ function isFunction(v) {
2703
+ return typeof v === 'function';
2704
+ }
2705
+ function isBoolean(v) {
2706
+ return typeof v === 'boolean';
2707
+ }
2708
+ function isUrlTree(v) {
2709
+ return v instanceof UrlTree;
2710
+ }
2711
+ function isCanLoad(guard) {
2712
+ return guard && isFunction(guard.canLoad);
2713
+ }
2714
+ function isCanActivate(guard) {
2715
+ return guard && isFunction(guard.canActivate);
2716
+ }
2717
+ function isCanActivateChild(guard) {
2718
+ return guard && isFunction(guard.canActivateChild);
2719
+ }
2720
+ function isCanDeactivate(guard) {
2721
+ return guard && isFunction(guard.canDeactivate);
2587
2722
  }
2588
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2589
- ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.11", type: ɵEmptyOutletComponent, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, directives: [{ type: RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
2590
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2591
- type: Component,
2592
- args: [{ template: `<router-outlet></router-outlet>` }]
2593
- }] });
2594
2723
 
2595
2724
  /**
2596
2725
  * @license
@@ -2599,113 +2728,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11",
2599
2728
  * Use of this source code is governed by an MIT-style license that can be
2600
2729
  * found in the LICENSE file at https://angular.io/license
2601
2730
  */
2602
- function validateConfig(config, parentPath = '') {
2603
- // forEach doesn't iterate undefined values
2604
- for (let i = 0; i < config.length; i++) {
2605
- const route = config[i];
2606
- const fullPath = getFullPath(parentPath, route);
2607
- validateNode(route, fullPath);
2608
- }
2609
- }
2610
- function validateNode(route, fullPath) {
2611
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
2612
- if (!route) {
2613
- throw new Error(`
2614
- Invalid configuration of route '${fullPath}': Encountered undefined route.
2615
- The reason might be an extra comma.
2616
-
2617
- Example:
2618
- const routes: Routes = [
2619
- { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2620
- { path: 'dashboard', component: DashboardComponent },, << two commas
2621
- { path: 'detail/:id', component: HeroDetailComponent }
2622
- ];
2623
- `);
2624
- }
2625
- if (Array.isArray(route)) {
2626
- throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2627
- }
2628
- if (!route.component && !route.children && !route.loadChildren &&
2629
- (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2630
- throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2631
- }
2632
- if (route.redirectTo && route.children) {
2633
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2634
- }
2635
- if (route.redirectTo && route.loadChildren) {
2636
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2637
- }
2638
- if (route.children && route.loadChildren) {
2639
- throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2640
- }
2641
- if (route.redirectTo && route.component) {
2642
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
2643
- }
2644
- if (route.redirectTo && route.canActivate) {
2645
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2646
- `so canActivate will never be executed.`);
2647
- }
2648
- if (route.path && route.matcher) {
2649
- throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2650
- }
2651
- if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
2652
- throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
2653
- }
2654
- if (route.path === void 0 && route.matcher === void 0) {
2655
- throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2656
- }
2657
- if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2658
- throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2659
- }
2660
- if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2661
- const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2662
- throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2663
- }
2664
- }
2665
- if (route.children) {
2666
- validateConfig(route.children, fullPath);
2667
- }
2668
- }
2669
- function getFullPath(parentPath, currentRoute) {
2670
- if (!currentRoute) {
2671
- return parentPath;
2672
- }
2673
- if (!parentPath && !currentRoute.path) {
2674
- return '';
2675
- }
2676
- else if (parentPath && !currentRoute.path) {
2677
- return `${parentPath}/`;
2678
- }
2679
- else if (!parentPath && currentRoute.path) {
2680
- return currentRoute.path;
2681
- }
2682
- else {
2683
- return `${parentPath}/${currentRoute.path}`;
2684
- }
2685
- }
2686
- /**
2687
- * Makes a copy of the config and adds any default required properties.
2688
- */
2689
- function standardizeConfig(r) {
2690
- const children = r.children && r.children.map(standardizeConfig);
2691
- const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2692
- if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2693
- c.component = ɵEmptyOutletComponent;
2694
- }
2695
- return c;
2696
- }
2697
- /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2698
- function getOutlet(route) {
2699
- return route.outlet || PRIMARY_OUTLET;
2700
- }
2701
- /**
2702
- * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2703
- * The order of the configs is otherwise preserved.
2704
- */
2705
- function sortByMatchingOutlets(routes, outletName) {
2706
- const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2707
- sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2708
- return sortedConfig;
2731
+ const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2732
+ function prioritizedGuardValue() {
2733
+ return switchMap(obs => {
2734
+ return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2735
+ .pipe(scan((acc, list) => {
2736
+ let isPending = false;
2737
+ return list.reduce((innerAcc, val, i) => {
2738
+ if (innerAcc !== INITIAL_VALUE)
2739
+ return innerAcc;
2740
+ // Toggle pending flag if any values haven't been set yet
2741
+ if (val === INITIAL_VALUE)
2742
+ isPending = true;
2743
+ // Any other return values are only valid if we haven't yet hit a pending
2744
+ // call. This guarantees that in the case of a guard at the bottom of the
2745
+ // tree that returns a redirect, we will wait for the higher priority
2746
+ // guard at the top to finish before performing the redirect.
2747
+ if (!isPending) {
2748
+ // Early return when we hit a `false` value as that should always
2749
+ // cancel navigation
2750
+ if (val === false)
2751
+ return val;
2752
+ if (i === list.length - 1 || isUrlTree(val)) {
2753
+ return val;
2754
+ }
2755
+ }
2756
+ return innerAcc;
2757
+ }, acc);
2758
+ }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2759
+ take(1));
2760
+ });
2709
2761
  }
2710
2762
 
2711
2763
  /**
@@ -2783,6 +2835,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
2783
2835
  s._sourceSegment = segmentGroup;
2784
2836
  if (relativeLinkResolution === 'legacy') {
2785
2837
  s._segmentIndexShift = segmentGroup.segments.length;
2838
+ if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
2839
+ s._segmentIndexShiftCorrected = consumedSegments.length;
2840
+ }
2786
2841
  }
2787
2842
  else {
2788
2843
  s._segmentIndexShift = consumedSegments.length;
@@ -2883,17 +2938,17 @@ function canLoadFails(route) {
2883
2938
  *
2884
2939
  * Lazy modules are loaded along the way.
2885
2940
  */
2886
- function applyRedirects$1(moduleInjector, configLoader, urlSerializer, urlTree, config) {
2887
- return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
2941
+ function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
2942
+ return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
2888
2943
  }
2889
2944
  class ApplyRedirects {
2890
- constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
2945
+ constructor(injector, configLoader, urlSerializer, urlTree, config) {
2946
+ this.injector = injector;
2891
2947
  this.configLoader = configLoader;
2892
2948
  this.urlSerializer = urlSerializer;
2893
2949
  this.urlTree = urlTree;
2894
2950
  this.config = config;
2895
2951
  this.allowRedirects = true;
2896
- this.ngModule = moduleInjector.get(NgModuleRef);
2897
2952
  }
2898
2953
  apply() {
2899
2954
  const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
@@ -2904,7 +2959,7 @@ class ApplyRedirects {
2904
2959
  // them. We should be able to remove this logic as a "breaking change" but should do some more
2905
2960
  // investigation into the failures first.
2906
2961
  const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
2907
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, rootSegmentGroup, PRIMARY_OUTLET);
2962
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
2908
2963
  const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
2909
2964
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
2910
2965
  }));
@@ -2923,7 +2978,7 @@ class ApplyRedirects {
2923
2978
  }));
2924
2979
  }
2925
2980
  match(tree) {
2926
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
2981
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
2927
2982
  const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
2928
2983
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
2929
2984
  }));
@@ -2943,15 +2998,15 @@ class ApplyRedirects {
2943
2998
  rootCandidate;
2944
2999
  return new UrlTree(root, queryParams, fragment);
2945
3000
  }
2946
- expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
3001
+ expandSegmentGroup(injector, routes, segmentGroup, outlet) {
2947
3002
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
2948
- return this.expandChildren(ngModule, routes, segmentGroup)
3003
+ return this.expandChildren(injector, routes, segmentGroup)
2949
3004
  .pipe(map((children) => new UrlSegmentGroup([], children)));
2950
3005
  }
2951
- return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
3006
+ return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
2952
3007
  }
2953
3008
  // Recursively expand segment groups for all the child outlets
2954
- expandChildren(ngModule, routes, segmentGroup) {
3009
+ expandChildren(injector, routes, segmentGroup) {
2955
3010
  // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
2956
3011
  // because an absolute redirect from the primary outlet takes precedence.
2957
3012
  const childOutlets = [];
@@ -2970,16 +3025,26 @@ class ApplyRedirects {
2970
3025
  // first, followed by routes for other outlets, which might match if they have an
2971
3026
  // empty path.
2972
3027
  const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
2973
- return this.expandSegmentGroup(ngModule, sortedRoutes, child, childOutlet)
3028
+ return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
2974
3029
  .pipe(map(s => ({ segment: s, outlet: childOutlet })));
2975
3030
  }), scan((children, expandedChild) => {
2976
3031
  children[expandedChild.outlet] = expandedChild.segment;
2977
3032
  return children;
2978
3033
  }, {}), last$1());
2979
3034
  }
2980
- expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
2981
- return from(routes).pipe(concatMap((r) => {
2982
- const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
3035
+ expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
3036
+ return from(routes).pipe(concatMap(r => {
3037
+ var _a;
3038
+ if (r.providers && !r._injector) {
3039
+ r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
3040
+ }
3041
+ // We specifically _do not_ want to include the _loadedInjector here. The loaded injector
3042
+ // only applies to the route's children, not the route itself. Note that this distinction
3043
+ // only applies here to any tokens we try to retrieve during this phase. At the moment,
3044
+ // that only includes `canLoad`, which won't run again once the child module is loaded. As
3045
+ // a result, this makes no difference right now, but could in the future if there are more
3046
+ // actions here that need DI (for example, a canMatch guard).
3047
+ const expanded$ = this.expandSegmentAgainstRoute((_a = r._injector) !== null && _a !== void 0 ? _a : injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
2983
3048
  return expanded$.pipe(catchError((e) => {
2984
3049
  if (e instanceof NoMatch$1) {
2985
3050
  return of(null);
@@ -2996,35 +3061,35 @@ class ApplyRedirects {
2996
3061
  throw e;
2997
3062
  }));
2998
3063
  }
2999
- expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3064
+ expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3000
3065
  if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
3001
3066
  return noMatch(segmentGroup);
3002
3067
  }
3003
3068
  if (route.redirectTo === undefined) {
3004
- return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths, outlet);
3069
+ return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
3005
3070
  }
3006
3071
  if (allowRedirects && this.allowRedirects) {
3007
- return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
3072
+ return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
3008
3073
  }
3009
3074
  return noMatch(segmentGroup);
3010
3075
  }
3011
- expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3076
+ expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3012
3077
  if (route.path === '**') {
3013
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
3078
+ return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3014
3079
  }
3015
- return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
3080
+ return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3016
3081
  }
3017
- expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
3082
+ expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3018
3083
  const newTree = this.applyRedirectCommands([], route.redirectTo, {});
3019
3084
  if (route.redirectTo.startsWith('/')) {
3020
3085
  return absoluteRedirect(newTree);
3021
3086
  }
3022
3087
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3023
3088
  const group = new UrlSegmentGroup(newSegments, {});
3024
- return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
3089
+ return this.expandSegment(injector, group, routes, newSegments, outlet, false);
3025
3090
  }));
3026
3091
  }
3027
- expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3092
+ expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3028
3093
  const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3029
3094
  if (!matched)
3030
3095
  return noMatch(segmentGroup);
@@ -3033,16 +3098,18 @@ class ApplyRedirects {
3033
3098
  return absoluteRedirect(newTree);
3034
3099
  }
3035
3100
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3036
- return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3101
+ return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3037
3102
  }));
3038
3103
  }
3039
- matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments, outlet) {
3104
+ matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
3040
3105
  if (route.path === '**') {
3041
3106
  if (route.loadChildren) {
3042
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
3043
- this.configLoader.load(ngModule.injector, route);
3107
+ const loaded$ = route._loadedRoutes ?
3108
+ of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
3109
+ this.configLoader.load(injector, route);
3044
3110
  return loaded$.pipe(map((cfg) => {
3045
- route._loadedConfig = cfg;
3111
+ route._loadedRoutes = cfg.routes;
3112
+ route._loadedInjector = cfg.injector;
3046
3113
  return new UrlSegmentGroup(segments, {});
3047
3114
  }));
3048
3115
  }
@@ -3051,55 +3118,56 @@ class ApplyRedirects {
3051
3118
  const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
3052
3119
  if (!matched)
3053
3120
  return noMatch(rawSegmentGroup);
3054
- const childConfig$ = this.getChildConfig(ngModule, route, segments);
3121
+ const childConfig$ = this.getChildConfig(injector, route, segments);
3055
3122
  return childConfig$.pipe(mergeMap((routerConfig) => {
3056
- const childModule = routerConfig.module;
3123
+ var _a;
3124
+ const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
3057
3125
  const childConfig = routerConfig.routes;
3058
3126
  const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3059
3127
  // See comment on the other call to `split` about why this is necessary.
3060
3128
  const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3061
3129
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3062
- const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
3130
+ const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3063
3131
  return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3064
3132
  }
3065
3133
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3066
3134
  return of(new UrlSegmentGroup(consumedSegments, {}));
3067
3135
  }
3068
3136
  const matchedOnOutlet = getOutlet(route) === outlet;
3069
- const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3137
+ const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3070
3138
  return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3071
3139
  }));
3072
3140
  }
3073
- getChildConfig(ngModule, route, segments) {
3141
+ getChildConfig(injector, route, segments) {
3074
3142
  if (route.children) {
3075
3143
  // The children belong to the same module
3076
- return of(new LoadedRouterConfig(route.children, ngModule));
3144
+ return of({ routes: route.children, injector });
3077
3145
  }
3078
3146
  if (route.loadChildren) {
3079
3147
  // lazy children belong to the loaded module
3080
- if (route._loadedConfig !== undefined) {
3081
- return of(route._loadedConfig);
3148
+ if (route._loadedRoutes !== undefined) {
3149
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3082
3150
  }
3083
- return this.runCanLoadGuards(ngModule.injector, route, segments)
3151
+ return this.runCanLoadGuards(injector, route, segments)
3084
3152
  .pipe(mergeMap((shouldLoadResult) => {
3085
3153
  if (shouldLoadResult) {
3086
- return this.configLoader.load(ngModule.injector, route)
3087
- .pipe(map((cfg) => {
3088
- route._loadedConfig = cfg;
3154
+ return this.configLoader.load(injector, route).pipe(map((cfg) => {
3155
+ route._loadedRoutes = cfg.routes;
3156
+ route._loadedInjector = cfg.injector;
3089
3157
  return cfg;
3090
3158
  }));
3091
3159
  }
3092
3160
  return canLoadFails(route);
3093
3161
  }));
3094
3162
  }
3095
- return of(new LoadedRouterConfig([], ngModule));
3163
+ return of({ routes: [], injector });
3096
3164
  }
3097
- runCanLoadGuards(moduleInjector, route, segments) {
3165
+ runCanLoadGuards(injector, route, segments) {
3098
3166
  const canLoad = route.canLoad;
3099
3167
  if (!canLoad || canLoad.length === 0)
3100
3168
  return of(true);
3101
3169
  const canLoadObservables = canLoad.map((injectionToken) => {
3102
- const guard = moduleInjector.get(injectionToken);
3170
+ const guard = injector.get(injectionToken);
3103
3171
  let guardVal;
3104
3172
  if (isCanLoad(guard)) {
3105
3173
  guardVal = guard.canLoad(route, segments);
@@ -3227,8 +3295,8 @@ function squashSegmentGroup(segmentGroup) {
3227
3295
  * Use of this source code is governed by an MIT-style license that can be
3228
3296
  * found in the LICENSE file at https://angular.io/license
3229
3297
  */
3230
- function applyRedirects(moduleInjector, configLoader, urlSerializer, config) {
3231
- return switchMap(t => applyRedirects$1(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
3298
+ function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3299
+ return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3232
3300
  .pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
3233
3301
  }
3234
3302
 
@@ -3262,21 +3330,11 @@ function getCanActivateChild(p) {
3262
3330
  return null;
3263
3331
  return { node: p, guards: canActivateChild };
3264
3332
  }
3265
- function getToken(token, snapshot, moduleInjector) {
3266
- const config = getClosestLoadedConfig(snapshot);
3267
- const injector = config ? config.module.injector : moduleInjector;
3333
+ function getToken(token, snapshot, fallbackInjector) {
3334
+ const routeInjector = getClosestRouteInjector(snapshot);
3335
+ const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
3268
3336
  return injector.get(token);
3269
3337
  }
3270
- function getClosestLoadedConfig(snapshot) {
3271
- if (!snapshot)
3272
- return null;
3273
- for (let s = snapshot.parent; s; s = s.parent) {
3274
- const route = s.routeConfig;
3275
- if (route && route._loadedConfig)
3276
- return route._loadedConfig;
3277
- }
3278
- return null;
3279
- }
3280
3338
  function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
3281
3339
  canDeactivateChecks: [],
3282
3340
  canActivateChecks: []
@@ -3520,6 +3578,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
3520
3578
  * Use of this source code is governed by an MIT-style license that can be
3521
3579
  * found in the LICENSE file at https://angular.io/license
3522
3580
  */
3581
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3523
3582
  class NoMatch {
3524
3583
  }
3525
3584
  function newObservableError(e) {
@@ -3635,7 +3694,13 @@ class Recognizer {
3635
3694
  let remainingSegments = [];
3636
3695
  if (route.path === '**') {
3637
3696
  const params = segments.length > 0 ? last(segments).parameters : {};
3638
- snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route));
3697
+ const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
3698
+ snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
3699
+ // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
3700
+ // production bundle size. This value is intended only to surface a warning to users
3701
+ // depending on `relativeLinkResolution: 'legacy'` in dev mode.
3702
+ (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3703
+ pathIndexShift));
3639
3704
  }
3640
3705
  else {
3641
3706
  const result = match(rawSegment, route, segments);
@@ -3644,7 +3709,9 @@ class Recognizer {
3644
3709
  }
3645
3710
  consumedSegments = result.consumedSegments;
3646
3711
  remainingSegments = result.remainingSegments;
3647
- snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
3712
+ const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3713
+ snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
3714
+ pathIndexShift));
3648
3715
  }
3649
3716
  const childConfig = getChildConfig(route);
3650
3717
  const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
@@ -3692,7 +3759,7 @@ function getChildConfig(route) {
3692
3759
  return route.children;
3693
3760
  }
3694
3761
  if (route.loadChildren) {
3695
- return route._loadedConfig.routes;
3762
+ return route._loadedRoutes;
3696
3763
  }
3697
3764
  return [];
3698
3765
  }
@@ -3753,11 +3820,22 @@ function getSourceSegmentGroup(segmentGroup) {
3753
3820
  return s;
3754
3821
  }
3755
3822
  function getPathIndexShift(segmentGroup) {
3823
+ var _a, _b;
3824
+ let s = segmentGroup;
3825
+ let res = (_a = s._segmentIndexShift) !== null && _a !== void 0 ? _a : 0;
3826
+ while (s._sourceSegment) {
3827
+ s = s._sourceSegment;
3828
+ res += (_b = s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
3829
+ }
3830
+ return res - 1;
3831
+ }
3832
+ function getCorrectedPathIndexShift(segmentGroup) {
3833
+ var _a, _b, _c, _d;
3756
3834
  let s = segmentGroup;
3757
- let res = (s._segmentIndexShift ? s._segmentIndexShift : 0);
3835
+ let res = (_b = (_a = s._segmentIndexShiftCorrected) !== null && _a !== void 0 ? _a : s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
3758
3836
  while (s._sourceSegment) {
3759
3837
  s = s._sourceSegment;
3760
- res += (s._segmentIndexShift ? s._segmentIndexShift : 0);
3838
+ res += (_d = (_c = s._segmentIndexShiftCorrected) !== null && _c !== void 0 ? _c : s._segmentIndexShift) !== null && _d !== void 0 ? _d : 0;
3761
3839
  }
3762
3840
  return res - 1;
3763
3841
  }
@@ -3827,16 +3905,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
3827
3905
  }
3828
3906
  const data = {};
3829
3907
  return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
3830
- .pipe(take(1), tap((value) => {
3908
+ .pipe(first(), tap((value) => {
3831
3909
  data[key] = value;
3832
- }))), takeLast(1), mergeMap(() => {
3833
- // Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
3834
- // the chain which will cancel navigation
3835
- if (getDataKeys(data).length === keys.length) {
3836
- return of(data);
3837
- }
3838
- return EMPTY;
3839
- }));
3910
+ }))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
3840
3911
  }
3841
3912
  function getDataKeys(obj) {
3842
3913
  return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
@@ -3945,6 +4016,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3945
4016
  * Use of this source code is governed by an MIT-style license that can be
3946
4017
  * found in the LICENSE file at https://angular.io/license
3947
4018
  */
4019
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3948
4020
  /**
3949
4021
  * The [DI token](guide/glossary/#di-token) for a router configuration.
3950
4022
  *
@@ -3957,15 +4029,17 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3957
4029
  */
3958
4030
  const ROUTES = new InjectionToken('ROUTES');
3959
4031
  class RouterConfigLoader {
3960
- constructor(injector, compiler, onLoadStartListener, onLoadEndListener) {
4032
+ constructor(injector, compiler) {
3961
4033
  this.injector = injector;
3962
4034
  this.compiler = compiler;
3963
- this.onLoadStartListener = onLoadStartListener;
3964
- this.onLoadEndListener = onLoadEndListener;
4035
+ this.routeLoaders = new WeakMap();
3965
4036
  }
3966
4037
  load(parentInjector, route) {
3967
- if (route._loader$) {
3968
- return route._loader$;
4038
+ if (this.routeLoaders.get(route)) {
4039
+ return this.routeLoaders.get(route);
4040
+ }
4041
+ else if (route._loadedRoutes) {
4042
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3969
4043
  }
3970
4044
  if (this.onLoadStartListener) {
3971
4045
  this.onLoadStartListener(route);
@@ -3975,21 +4049,24 @@ class RouterConfigLoader {
3975
4049
  if (this.onLoadEndListener) {
3976
4050
  this.onLoadEndListener(route);
3977
4051
  }
3978
- const module = factory.create(parentInjector);
4052
+ const injector = factory.create(parentInjector).injector;
4053
+ const routes =
3979
4054
  // When loading a module that doesn't provide `RouterModule.forChild()` preloader
3980
4055
  // will get stuck in an infinite loop. The child module's Injector will look to
3981
4056
  // its parent `Injector` when it doesn't find any ROUTES so it will return routes
3982
4057
  // for it's parent module instead.
3983
- return new LoadedRouterConfig(flatten(module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))
3984
- .map(standardizeConfig), module);
3985
- }), catchError((err) => {
3986
- route._loader$ = undefined;
3987
- throw err;
4058
+ flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional))
4059
+ .map(standardizeConfig);
4060
+ NG_DEV_MODE$1 && validateConfig(routes);
4061
+ return { routes, injector };
4062
+ }), finalize(() => {
4063
+ this.routeLoaders.delete(route);
3988
4064
  }));
3989
4065
  // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
3990
- route._loader$ = new ConnectableObservable(loadRunner, () => new Subject())
4066
+ const loader = new ConnectableObservable(loadRunner, () => new Subject())
3991
4067
  .pipe(refCount());
3992
- return route._loader$;
4068
+ this.routeLoaders.set(route, loader);
4069
+ return loader;
3993
4070
  }
3994
4071
  loadModuleFactory(loadChildren) {
3995
4072
  return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
@@ -4002,6 +4079,11 @@ class RouterConfigLoader {
4002
4079
  }));
4003
4080
  }
4004
4081
  }
4082
+ RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4083
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader });
4084
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterConfigLoader, decorators: [{
4085
+ type: Injectable
4086
+ }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
4005
4087
 
4006
4088
  /**
4007
4089
  * @license
@@ -4034,6 +4116,7 @@ class DefaultUrlHandlingStrategy {
4034
4116
  }
4035
4117
  }
4036
4118
 
4119
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
4037
4120
  function defaultErrorHandler(error) {
4038
4121
  throw error;
4039
4122
  }
@@ -4205,6 +4288,9 @@ class Router {
4205
4288
  this.canceledNavigationResolution = 'replace';
4206
4289
  const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
4207
4290
  const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
4291
+ this.configLoader = injector.get(RouterConfigLoader);
4292
+ this.configLoader.onLoadEndListener = onLoadEnd;
4293
+ this.configLoader.onLoadStartListener = onLoadStart;
4208
4294
  this.ngModule = injector.get(NgModuleRef);
4209
4295
  this.console = injector.get(ɵConsole);
4210
4296
  const ngZone = injector.get(NgZone);
@@ -4213,7 +4299,6 @@ class Router {
4213
4299
  this.currentUrlTree = createEmptyUrlTree();
4214
4300
  this.rawUrlTree = this.currentUrlTree;
4215
4301
  this.browserUrlTree = this.currentUrlTree;
4216
- this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
4217
4302
  this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4218
4303
  this.transitions = new BehaviorSubject({
4219
4304
  id: 0,
@@ -4617,7 +4702,7 @@ class Router {
4617
4702
  * ```
4618
4703
  */
4619
4704
  resetConfig(config) {
4620
- validateConfig(config);
4705
+ NG_DEV_MODE && validateConfig(config);
4621
4706
  this.config = config.map(standardizeConfig);
4622
4707
  this.navigated = false;
4623
4708
  this.lastSuccessfulId = -1;
@@ -4975,9 +5060,9 @@ class Router {
4975
5060
  return { navigationId };
4976
5061
  }
4977
5062
  }
4978
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
4979
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: Router });
4980
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: Router, decorators: [{
5063
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5064
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router });
5065
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: Router, decorators: [{
4981
5066
  type: Injectable
4982
5067
  }], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
4983
5068
  function validateCommands(commands) {
@@ -5169,9 +5254,9 @@ class RouterLink {
5169
5254
  });
5170
5255
  }
5171
5256
  }
5172
- RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5173
- RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.11", type: RouterLink, selector: ":not(a):not(area)[routerLink]", inputs: { queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
5174
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLink, decorators: [{
5257
+ RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5258
+ RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLink, selector: ":not(a):not(area)[routerLink]", inputs: { queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
5259
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLink, decorators: [{
5175
5260
  type: Directive,
5176
5261
  args: [{ selector: ':not(a):not(area)[routerLink]' }]
5177
5262
  }], ctorParameters: function () {
@@ -5290,9 +5375,9 @@ class RouterLinkWithHref {
5290
5375
  });
5291
5376
  }
5292
5377
  }
5293
- RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5294
- RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.11", type: RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target", "attr.href": "this.href" } }, usesOnChanges: true, ngImport: i0 });
5295
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5378
+ RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5379
+ RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", state: "state", relativeTo: "relativeTo", routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target", "attr.href": "this.href" } }, usesOnChanges: true, ngImport: i0 });
5380
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5296
5381
  type: Directive,
5297
5382
  args: [{ selector: 'a[routerLink],area[routerLink]' }]
5298
5383
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
@@ -5503,9 +5588,9 @@ class RouterLinkActive {
5503
5588
  this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
5504
5589
  }
5505
5590
  }
5506
- RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }, { token: RouterLinkWithHref, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
5507
- RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.11", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
5508
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterLinkActive, decorators: [{
5591
+ RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }, { token: RouterLinkWithHref, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
5592
+ RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.14", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
5593
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterLinkActive, decorators: [{
5509
5594
  type: Directive,
5510
5595
  args: [{
5511
5596
  selector: '[routerLinkActive]',
@@ -5609,9 +5694,9 @@ class DefaultTitleStrategy extends TitleStrategy {
5609
5694
  }
5610
5695
  }
5611
5696
  }
5612
- DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5613
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5614
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5697
+ DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5698
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5615
5700
  type: Injectable,
5616
5701
  args: [{ providedIn: 'root' }]
5617
5702
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -5675,13 +5760,11 @@ class NoPreloading {
5675
5760
  * @publicApi
5676
5761
  */
5677
5762
  class RouterPreloader {
5678
- constructor(router, compiler, injector, preloadingStrategy) {
5763
+ constructor(router, compiler, injector, preloadingStrategy, loader) {
5679
5764
  this.router = router;
5680
5765
  this.injector = injector;
5681
5766
  this.preloadingStrategy = preloadingStrategy;
5682
- const onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r));
5683
- const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
5684
- this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
5767
+ this.loader = loader;
5685
5768
  }
5686
5769
  setUpPreloading() {
5687
5770
  this.subscription =
@@ -5690,8 +5773,7 @@ class RouterPreloader {
5690
5773
  .subscribe(() => { });
5691
5774
  }
5692
5775
  preload() {
5693
- const ngModule = this.injector.get(NgModuleRef);
5694
- return this.processRoutes(ngModule, this.router.config);
5776
+ return this.processRoutes(this.injector, this.router.config);
5695
5777
  }
5696
5778
  /** @nodoc */
5697
5779
  ngOnDestroy() {
@@ -5699,41 +5781,52 @@ class RouterPreloader {
5699
5781
  this.subscription.unsubscribe();
5700
5782
  }
5701
5783
  }
5702
- processRoutes(ngModule, routes) {
5784
+ processRoutes(injector, routes) {
5785
+ var _a, _b;
5703
5786
  const res = [];
5704
5787
  for (const route of routes) {
5788
+ if (route.providers && !route._injector) {
5789
+ route._injector =
5790
+ createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
5791
+ }
5792
+ const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
5793
+ const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
5705
5794
  // we already have the config loaded, just recurse
5706
- if (route.loadChildren && !route.canLoad && route._loadedConfig) {
5707
- const childConfig = route._loadedConfig;
5708
- res.push(this.processRoutes(childConfig.module, childConfig.routes));
5795
+ if (route.loadChildren && !route.canLoad && route._loadedRoutes) {
5796
+ res.push(this.processRoutes(injectorForChildren, route._loadedRoutes));
5709
5797
  // no config loaded, fetch the config
5710
5798
  }
5711
5799
  else if (route.loadChildren && !route.canLoad) {
5712
- res.push(this.preloadConfig(ngModule, route));
5800
+ res.push(this.preloadConfig(injectorForCurrentRoute, route));
5713
5801
  // recurse into children
5714
5802
  }
5715
5803
  else if (route.children) {
5716
- res.push(this.processRoutes(ngModule, route.children));
5804
+ res.push(this.processRoutes(injectorForChildren, route.children));
5717
5805
  }
5718
5806
  }
5719
5807
  return from(res).pipe(mergeAll(), map((_) => void 0));
5720
5808
  }
5721
- preloadConfig(ngModule, route) {
5809
+ preloadConfig(injector, route) {
5722
5810
  return this.preloadingStrategy.preload(route, () => {
5723
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
5724
- this.loader.load(ngModule.injector, route);
5811
+ const loaded$ = route._loadedRoutes ?
5812
+ of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
5813
+ this.loader.load(injector, route);
5725
5814
  return loaded$.pipe(mergeMap((config) => {
5726
- route._loadedConfig = config;
5727
- return this.processRoutes(config.module, config.routes);
5815
+ var _a;
5816
+ route._loadedRoutes = config.routes;
5817
+ route._loadedInjector = config.injector;
5818
+ // If the loaded config was a module, use that as the module/module injector going forward.
5819
+ // Otherwise, continue using the current module/module injector.
5820
+ return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
5728
5821
  }));
5729
5822
  });
5730
5823
  }
5731
5824
  }
5732
- RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.Injector }, { token: PreloadingStrategy }], target: i0.ɵɵFactoryTarget.Injectable });
5733
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterPreloader });
5734
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterPreloader, decorators: [{
5825
+ RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
5826
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader });
5827
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterPreloader, decorators: [{
5735
5828
  type: Injectable
5736
- }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.Injector }, { type: PreloadingStrategy }]; } });
5829
+ }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
5737
5830
 
5738
5831
  class RouterScroller {
5739
5832
  constructor(router,
@@ -5810,9 +5903,9 @@ class RouterScroller {
5810
5903
  }
5811
5904
  }
5812
5905
  }
5813
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5814
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterScroller });
5815
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterScroller, decorators: [{
5906
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5907
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller });
5908
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterScroller, decorators: [{
5816
5909
  type: Injectable
5817
5910
  }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
5818
5911
 
@@ -5855,6 +5948,7 @@ const ROUTER_PROVIDERS = [
5855
5948
  NoPreloading,
5856
5949
  PreloadAllModules,
5857
5950
  { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
5951
+ RouterConfigLoader,
5858
5952
  ];
5859
5953
  function routerNgProbeToken() {
5860
5954
  return new NgProbeToken('Router', Router);
@@ -5953,10 +6047,10 @@ class RouterModule {
5953
6047
  return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
5954
6048
  }
5955
6049
  }
5956
- RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
5957
- RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
5958
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterModule });
5959
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterModule, decorators: [{
6050
+ RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6051
+ RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
6052
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule });
6053
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterModule, decorators: [{
5960
6054
  type: NgModule,
5961
6055
  args: [{
5962
6056
  declarations: ROUTER_DIRECTIVES,
@@ -6138,9 +6232,9 @@ class RouterInitializer {
6138
6232
  this.destroyed = true;
6139
6233
  }
6140
6234
  }
6141
- RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6142
- RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterInitializer });
6143
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.11", ngImport: i0, type: RouterInitializer, decorators: [{
6235
+ RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6236
+ RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer });
6237
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.14", ngImport: i0, type: RouterInitializer, decorators: [{
6144
6238
  type: Injectable
6145
6239
  }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
6146
6240
  function getAppInitializer(r) {
@@ -6180,7 +6274,7 @@ function provideRouterInitializer() {
6180
6274
  /**
6181
6275
  * @publicApi
6182
6276
  */
6183
- const VERSION = new Version('14.0.0-next.11');
6277
+ const VERSION = new Version('14.0.0-next.14');
6184
6278
 
6185
6279
  /**
6186
6280
  * @license