@angular/router 14.0.0-next.9 → 14.0.0-rc.2

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 (41) hide show
  1. package/esm2020/src/apply_redirects.mjs +52 -48
  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 +22 -4
  6. package/esm2020/src/directives/router_outlet.mjs +25 -16
  7. package/esm2020/src/events.mjs +57 -1
  8. package/esm2020/src/index.mjs +1 -1
  9. package/esm2020/src/models.mjs +2 -7
  10. package/esm2020/src/operators/activate_routes.mjs +7 -14
  11. package/esm2020/src/operators/apply_redirects.mjs +3 -3
  12. package/esm2020/src/operators/resolve_data.mjs +14 -24
  13. package/esm2020/src/page_title_strategy.mjs +3 -3
  14. package/esm2020/src/recognize.mjs +24 -6
  15. package/esm2020/src/router.mjs +43 -25
  16. package/esm2020/src/router_config_loader.mjs +74 -27
  17. package/esm2020/src/router_module.mjs +14 -14
  18. package/esm2020/src/router_outlet_context.mjs +6 -1
  19. package/esm2020/src/router_preloader.mjs +48 -32
  20. package/esm2020/src/router_scroller.mjs +3 -3
  21. package/esm2020/src/router_state.mjs +4 -4
  22. package/esm2020/src/url_tree.mjs +1 -1
  23. package/esm2020/src/utils/config.mjs +86 -11
  24. package/esm2020/src/utils/config_matching.mjs +4 -1
  25. package/esm2020/src/utils/preactivation.mjs +5 -14
  26. package/esm2020/src/version.mjs +1 -1
  27. package/esm2020/testing/src/router_testing_module.mjs +4 -4
  28. package/fesm2015/router.mjs +927 -670
  29. package/fesm2015/router.mjs.map +1 -1
  30. package/fesm2015/testing.mjs +5 -5
  31. package/fesm2015/upgrade.mjs +1 -1
  32. package/fesm2020/router.mjs +912 -673
  33. package/fesm2020/router.mjs.map +1 -1
  34. package/fesm2020/testing.mjs +5 -5
  35. package/fesm2020/upgrade.mjs +1 -1
  36. package/{router.d.ts → index.d.ts} +3858 -3730
  37. package/package.json +9 -9
  38. package/testing/{testing.d.ts → index.d.ts} +65 -64
  39. package/upgrade/{upgrade.d.ts → index.d.ts} +51 -50
  40. package/testing/package.json +0 -9
  41. package/upgrade/package.json +0 -10
@@ -1,13 +1,13 @@
1
1
  /**
2
- * @license Angular v14.0.0-next.9
2
+ * @license Angular v14.0.0-rc.2
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, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, 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, defaultIfEmpty, 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';
@@ -69,6 +69,7 @@ class NavigationStart extends RouterEvent {
69
69
  /** @docsNotRequired */
70
70
  restoredState = null) {
71
71
  super(id, url);
72
+ this.type = 0 /* EventType.NavigationStart */;
72
73
  this.navigationTrigger = navigationTrigger;
73
74
  this.restoredState = restoredState;
74
75
  }
@@ -96,6 +97,7 @@ class NavigationEnd extends RouterEvent {
96
97
  urlAfterRedirects) {
97
98
  super(id, url);
98
99
  this.urlAfterRedirects = urlAfterRedirects;
100
+ this.type = 1 /* EventType.NavigationEnd */;
99
101
  }
100
102
  /** @docsNotRequired */
101
103
  toString() {
@@ -123,6 +125,7 @@ class NavigationCancel extends RouterEvent {
123
125
  reason) {
124
126
  super(id, url);
125
127
  this.reason = reason;
128
+ this.type = 2 /* EventType.NavigationCancel */;
126
129
  }
127
130
  /** @docsNotRequired */
128
131
  toString() {
@@ -148,6 +151,7 @@ class NavigationError extends RouterEvent {
148
151
  error) {
149
152
  super(id, url);
150
153
  this.error = error;
154
+ this.type = 3 /* EventType.NavigationError */;
151
155
  }
152
156
  /** @docsNotRequired */
153
157
  toString() {
@@ -172,6 +176,7 @@ class RoutesRecognized extends RouterEvent {
172
176
  super(id, url);
173
177
  this.urlAfterRedirects = urlAfterRedirects;
174
178
  this.state = state;
179
+ this.type = 4 /* EventType.RoutesRecognized */;
175
180
  }
176
181
  /** @docsNotRequired */
177
182
  toString() {
@@ -198,6 +203,7 @@ class GuardsCheckStart extends RouterEvent {
198
203
  super(id, url);
199
204
  this.urlAfterRedirects = urlAfterRedirects;
200
205
  this.state = state;
206
+ this.type = 7 /* EventType.GuardsCheckStart */;
201
207
  }
202
208
  toString() {
203
209
  return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
@@ -226,6 +232,7 @@ class GuardsCheckEnd extends RouterEvent {
226
232
  this.urlAfterRedirects = urlAfterRedirects;
227
233
  this.state = state;
228
234
  this.shouldActivate = shouldActivate;
235
+ this.type = 8 /* EventType.GuardsCheckEnd */;
229
236
  }
230
237
  toString() {
231
238
  return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
@@ -254,6 +261,7 @@ class ResolveStart extends RouterEvent {
254
261
  super(id, url);
255
262
  this.urlAfterRedirects = urlAfterRedirects;
256
263
  this.state = state;
264
+ this.type = 5 /* EventType.ResolveStart */;
257
265
  }
258
266
  toString() {
259
267
  return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
@@ -278,6 +286,7 @@ class ResolveEnd extends RouterEvent {
278
286
  super(id, url);
279
287
  this.urlAfterRedirects = urlAfterRedirects;
280
288
  this.state = state;
289
+ this.type = 6 /* EventType.ResolveEnd */;
281
290
  }
282
291
  toString() {
283
292
  return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
@@ -295,6 +304,7 @@ class RouteConfigLoadStart {
295
304
  /** @docsNotRequired */
296
305
  route) {
297
306
  this.route = route;
307
+ this.type = 9 /* EventType.RouteConfigLoadStart */;
298
308
  }
299
309
  toString() {
300
310
  return `RouteConfigLoadStart(path: ${this.route.path})`;
@@ -312,6 +322,7 @@ class RouteConfigLoadEnd {
312
322
  /** @docsNotRequired */
313
323
  route) {
314
324
  this.route = route;
325
+ this.type = 10 /* EventType.RouteConfigLoadEnd */;
315
326
  }
316
327
  toString() {
317
328
  return `RouteConfigLoadEnd(path: ${this.route.path})`;
@@ -330,6 +341,7 @@ class ChildActivationStart {
330
341
  /** @docsNotRequired */
331
342
  snapshot) {
332
343
  this.snapshot = snapshot;
344
+ this.type = 11 /* EventType.ChildActivationStart */;
333
345
  }
334
346
  toString() {
335
347
  const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
@@ -348,6 +360,7 @@ class ChildActivationEnd {
348
360
  /** @docsNotRequired */
349
361
  snapshot) {
350
362
  this.snapshot = snapshot;
363
+ this.type = 12 /* EventType.ChildActivationEnd */;
351
364
  }
352
365
  toString() {
353
366
  const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
@@ -367,6 +380,7 @@ class ActivationStart {
367
380
  /** @docsNotRequired */
368
381
  snapshot) {
369
382
  this.snapshot = snapshot;
383
+ this.type = 13 /* EventType.ActivationStart */;
370
384
  }
371
385
  toString() {
372
386
  const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
@@ -386,6 +400,7 @@ class ActivationEnd {
386
400
  /** @docsNotRequired */
387
401
  snapshot) {
388
402
  this.snapshot = snapshot;
403
+ this.type = 14 /* EventType.ActivationEnd */;
389
404
  }
390
405
  toString() {
391
406
  const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
@@ -408,12 +423,54 @@ class Scroll {
408
423
  this.routerEvent = routerEvent;
409
424
  this.position = position;
410
425
  this.anchor = anchor;
426
+ this.type = 15 /* EventType.Scroll */;
411
427
  }
412
428
  toString() {
413
429
  const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
414
430
  return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
415
431
  }
416
432
  }
433
+ function stringifyEvent(routerEvent) {
434
+ var _a, _b, _c, _d;
435
+ if (!('type' in routerEvent)) {
436
+ return `Unknown Router Event: ${routerEvent.constructor.name}`;
437
+ }
438
+ switch (routerEvent.type) {
439
+ case 14 /* EventType.ActivationEnd */:
440
+ return `ActivationEnd(path: '${((_a = routerEvent.snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a.path) || ''}')`;
441
+ case 13 /* EventType.ActivationStart */:
442
+ return `ActivationStart(path: '${((_b = routerEvent.snapshot.routeConfig) === null || _b === void 0 ? void 0 : _b.path) || ''}')`;
443
+ case 12 /* EventType.ChildActivationEnd */:
444
+ return `ChildActivationEnd(path: '${((_c = routerEvent.snapshot.routeConfig) === null || _c === void 0 ? void 0 : _c.path) || ''}')`;
445
+ case 11 /* EventType.ChildActivationStart */:
446
+ return `ChildActivationStart(path: '${((_d = routerEvent.snapshot.routeConfig) === null || _d === void 0 ? void 0 : _d.path) || ''}')`;
447
+ case 8 /* EventType.GuardsCheckEnd */:
448
+ return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
449
+ case 7 /* EventType.GuardsCheckStart */:
450
+ return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
451
+ case 2 /* EventType.NavigationCancel */:
452
+ return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
453
+ case 1 /* EventType.NavigationEnd */:
454
+ return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
455
+ case 3 /* EventType.NavigationError */:
456
+ return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
457
+ case 0 /* EventType.NavigationStart */:
458
+ return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
459
+ case 6 /* EventType.ResolveEnd */:
460
+ return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
461
+ case 5 /* EventType.ResolveStart */:
462
+ return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
463
+ case 10 /* EventType.RouteConfigLoadEnd */:
464
+ return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
465
+ case 9 /* EventType.RouteConfigLoadStart */:
466
+ return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
467
+ case 4 /* EventType.RoutesRecognized */:
468
+ return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
469
+ case 15 /* EventType.Scroll */:
470
+ const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
471
+ return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
472
+ }
473
+ }
417
474
 
418
475
  /**
419
476
  * @license
@@ -1362,7 +1419,6 @@ class ActivatedRoute {
1362
1419
  /** The outlet name of the route, a constant. */
1363
1420
  outlet,
1364
1421
  /** The component of the route, a constant. */
1365
- // TODO(vsavkin): remove |string
1366
1422
  component, futureSnapshot) {
1367
1423
  this.url = url;
1368
1424
  this.params = params;
@@ -1454,9 +1510,10 @@ function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnl
1454
1510
  /** @internal */
1455
1511
  function flattenInherited(pathFromRoot) {
1456
1512
  return pathFromRoot.reduce((res, curr) => {
1513
+ var _a;
1457
1514
  const params = Object.assign(Object.assign({}, res.params), curr.params);
1458
1515
  const data = Object.assign(Object.assign({}, res.data), curr.data);
1459
- const resolve = Object.assign(Object.assign({}, res.resolve), curr._resolvedData);
1516
+ const resolve = Object.assign(Object.assign(Object.assign(Object.assign({}, curr.data), res.resolve), (_a = curr.routeConfig) === null || _a === void 0 ? void 0 : _a.data), curr._resolvedData);
1460
1517
  return { params, data, resolve };
1461
1518
  }, { params: {}, data: {}, resolve: {} });
1462
1519
  }
@@ -1517,7 +1574,7 @@ class ActivatedRouteSnapshot {
1517
1574
  /** The outlet name of the route */
1518
1575
  outlet,
1519
1576
  /** The component of the route */
1520
- component, routeConfig, urlSegment, lastPathIndex, resolve) {
1577
+ component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) {
1521
1578
  this.url = url;
1522
1579
  this.params = params;
1523
1580
  this.queryParams = queryParams;
@@ -1528,6 +1585,7 @@ class ActivatedRouteSnapshot {
1528
1585
  this.routeConfig = routeConfig;
1529
1586
  this._urlSegment = urlSegment;
1530
1587
  this._lastPathIndex = lastPathIndex;
1588
+ this._correctedLastPathIndex = correctedLastPathIndex !== null && correctedLastPathIndex !== void 0 ? correctedLastPathIndex : lastPathIndex;
1531
1589
  this._resolve = resolve;
1532
1590
  }
1533
1591
  /** The root of the router state */
@@ -1712,6 +1770,7 @@ function createActivatedRoute(c) {
1712
1770
  * found in the LICENSE file at https://angular.io/license
1713
1771
  */
1714
1772
  function createUrlTree(route, urlTree, commands, queryParams, fragment) {
1773
+ var _a, _b;
1715
1774
  if (commands.length === 0) {
1716
1775
  return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);
1717
1776
  }
@@ -1719,11 +1778,27 @@ function createUrlTree(route, urlTree, commands, queryParams, fragment) {
1719
1778
  if (nav.toRoot()) {
1720
1779
  return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);
1721
1780
  }
1722
- const startingPosition = findStartingPosition(nav, urlTree, route);
1723
- const segmentGroup = startingPosition.processChildren ?
1724
- updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
1725
- updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
1726
- return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
1781
+ function createTreeUsingPathIndex(lastPathIndex) {
1782
+ var _a;
1783
+ const startingPosition = findStartingPosition(nav, urlTree, (_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._urlSegment, lastPathIndex);
1784
+ const segmentGroup = startingPosition.processChildren ?
1785
+ updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
1786
+ updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
1787
+ return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);
1788
+ }
1789
+ // Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this
1790
+ // may be the case. Since we try to access it at an earlier point before the refactor to add the
1791
+ // warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it
1792
+ // didn't before.
1793
+ const result = createTreeUsingPathIndex((_a = route.snapshot) === null || _a === void 0 ? void 0 : _a._lastPathIndex);
1794
+ // Check if application is relying on `relativeLinkResolution: 'legacy'`
1795
+ if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
1796
+ const correctedResult = createTreeUsingPathIndex((_b = route.snapshot) === null || _b === void 0 ? void 0 : _b._correctedLastPathIndex);
1797
+ if (correctedResult.toString() !== result.toString()) {
1798
+ 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.`);
1799
+ }
1800
+ }
1801
+ return result;
1727
1802
  }
1728
1803
  function isMatrixParams(command) {
1729
1804
  return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
@@ -1828,12 +1903,11 @@ class Position {
1828
1903
  this.index = index;
1829
1904
  }
1830
1905
  }
1831
- function findStartingPosition(nav, tree, route) {
1906
+ function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) {
1832
1907
  if (nav.isAbsolute) {
1833
1908
  return new Position(tree.root, true, 0);
1834
1909
  }
1835
- if (route.snapshot._lastPathIndex === -1) {
1836
- const segmentGroup = route.snapshot._urlSegment;
1910
+ if (lastPathIndex === -1) {
1837
1911
  // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children
1838
1912
  // see issue #26224, #13011, #35687
1839
1913
  // However, if the ActivatedRoute is the root we should process children like above.
@@ -1841,8 +1915,8 @@ function findStartingPosition(nav, tree, route) {
1841
1915
  return new Position(segmentGroup, processChildren, 0);
1842
1916
  }
1843
1917
  const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
1844
- const index = route.snapshot._lastPathIndex + modifier;
1845
- return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
1918
+ const index = lastPathIndex + modifier;
1919
+ return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);
1846
1920
  }
1847
1921
  function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
1848
1922
  let g = group;
@@ -2005,181 +2079,76 @@ function compare(path, params, segment) {
2005
2079
  * Use of this source code is governed by an MIT-style license that can be
2006
2080
  * found in the LICENSE file at https://angular.io/license
2007
2081
  */
2008
- const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2009
- new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2010
- .activate(rootContexts);
2011
- return t;
2012
- });
2013
- class ActivateRoutes {
2014
- constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2015
- this.routeReuseStrategy = routeReuseStrategy;
2016
- this.futureState = futureState;
2017
- this.currState = currState;
2018
- this.forwardEvent = forwardEvent;
2019
- }
2020
- activate(parentContexts) {
2021
- const futureRoot = this.futureState._root;
2022
- const currRoot = this.currState ? this.currState._root : null;
2023
- this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2024
- advanceActivatedRoute(this.futureState.root);
2025
- this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2026
- }
2027
- // De-activate the child route that are not re-used for the future state
2028
- deactivateChildRoutes(futureNode, currNode, contexts) {
2029
- const children = nodeChildrenAsMap(currNode);
2030
- // Recurse on the routes active in the future state to de-activate deeper children
2031
- futureNode.children.forEach(futureChild => {
2032
- const childOutletName = futureChild.value.outlet;
2033
- this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2034
- delete children[childOutletName];
2035
- });
2036
- // De-activate the routes that will not be re-used
2037
- forEach(children, (v, childName) => {
2038
- this.deactivateRouteAndItsChildren(v, contexts);
2039
- });
2040
- }
2041
- deactivateRoutes(futureNode, currNode, parentContext) {
2042
- const future = futureNode.value;
2043
- const curr = currNode ? currNode.value : null;
2044
- if (future === curr) {
2045
- // Reusing the node, check to see if the children need to be de-activated
2046
- if (future.component) {
2047
- // If we have a normal route, we need to go through an outlet.
2048
- const context = parentContext.getContext(future.outlet);
2049
- if (context) {
2050
- this.deactivateChildRoutes(futureNode, currNode, context.children);
2051
- }
2052
- }
2053
- else {
2054
- // if we have a componentless route, we recurse but keep the same outlet map.
2055
- this.deactivateChildRoutes(futureNode, currNode, parentContext);
2056
- }
2057
- }
2058
- else {
2059
- if (curr) {
2060
- // Deactivate the current route which will not be re-used
2061
- this.deactivateRouteAndItsChildren(currNode, parentContext);
2062
- }
2063
- }
2082
+ /**
2083
+ * Store contextual information about a `RouterOutlet`
2084
+ *
2085
+ * @publicApi
2086
+ */
2087
+ class OutletContext {
2088
+ constructor() {
2089
+ this.outlet = null;
2090
+ this.route = null;
2091
+ /**
2092
+ * @deprecated Passing a resolver to retrieve a component factory is not required and is
2093
+ * deprecated since v14.
2094
+ */
2095
+ this.resolver = null;
2096
+ this.injector = null;
2097
+ this.children = new ChildrenOutletContexts();
2098
+ this.attachRef = null;
2064
2099
  }
2065
- deactivateRouteAndItsChildren(route, parentContexts) {
2066
- // If there is no component, the Route is never attached to an outlet (because there is no
2067
- // component to attach).
2068
- if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2069
- this.detachAndStoreRouteSubtree(route, parentContexts);
2070
- }
2071
- else {
2072
- this.deactivateRouteAndOutlet(route, parentContexts);
2073
- }
2100
+ }
2101
+ /**
2102
+ * Store contextual information about the children (= nested) `RouterOutlet`
2103
+ *
2104
+ * @publicApi
2105
+ */
2106
+ class ChildrenOutletContexts {
2107
+ constructor() {
2108
+ // contexts for child outlets, by name.
2109
+ this.contexts = new Map();
2074
2110
  }
2075
- detachAndStoreRouteSubtree(route, parentContexts) {
2076
- const context = parentContexts.getContext(route.value.outlet);
2077
- const contexts = context && route.value.component ? context.children : parentContexts;
2078
- const children = nodeChildrenAsMap(route);
2079
- for (const childOutlet of Object.keys(children)) {
2080
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2081
- }
2082
- if (context && context.outlet) {
2083
- const componentRef = context.outlet.detach();
2084
- const contexts = context.children.onOutletDeactivated();
2085
- this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2086
- }
2111
+ /** Called when a `RouterOutlet` directive is instantiated */
2112
+ onChildOutletCreated(childName, outlet) {
2113
+ const context = this.getOrCreateContext(childName);
2114
+ context.outlet = outlet;
2115
+ this.contexts.set(childName, context);
2087
2116
  }
2088
- deactivateRouteAndOutlet(route, parentContexts) {
2089
- const context = parentContexts.getContext(route.value.outlet);
2090
- // The context could be `null` if we are on a componentless route but there may still be
2091
- // children that need deactivating.
2092
- const contexts = context && route.value.component ? context.children : parentContexts;
2093
- const children = nodeChildrenAsMap(route);
2094
- for (const childOutlet of Object.keys(children)) {
2095
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2096
- }
2097
- if (context && context.outlet) {
2098
- // Destroy the component
2099
- context.outlet.deactivate();
2100
- // Destroy the contexts for all the outlets that were in the component
2101
- context.children.onOutletDeactivated();
2102
- // Clear the information about the attached component on the context but keep the reference to
2103
- // the outlet.
2117
+ /**
2118
+ * Called when a `RouterOutlet` directive is destroyed.
2119
+ * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2120
+ * re-created later.
2121
+ */
2122
+ onChildOutletDestroyed(childName) {
2123
+ const context = this.getContext(childName);
2124
+ if (context) {
2125
+ context.outlet = null;
2104
2126
  context.attachRef = null;
2105
- context.resolver = null;
2106
- context.route = null;
2107
2127
  }
2108
2128
  }
2109
- activateChildRoutes(futureNode, currNode, contexts) {
2110
- const children = nodeChildrenAsMap(currNode);
2111
- futureNode.children.forEach(c => {
2112
- this.activateRoutes(c, children[c.value.outlet], contexts);
2113
- this.forwardEvent(new ActivationEnd(c.value.snapshot));
2114
- });
2115
- if (futureNode.children.length) {
2116
- this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2117
- }
2129
+ /**
2130
+ * Called when the corresponding route is deactivated during navigation.
2131
+ * Because the component get destroyed, all children outlet are destroyed.
2132
+ */
2133
+ onOutletDeactivated() {
2134
+ const contexts = this.contexts;
2135
+ this.contexts = new Map();
2136
+ return contexts;
2118
2137
  }
2119
- activateRoutes(futureNode, currNode, parentContexts) {
2120
- const future = futureNode.value;
2121
- const curr = currNode ? currNode.value : null;
2122
- advanceActivatedRoute(future);
2123
- // reusing the node
2124
- if (future === curr) {
2125
- if (future.component) {
2126
- // If we have a normal route, we need to go through an outlet.
2127
- const context = parentContexts.getOrCreateContext(future.outlet);
2128
- this.activateChildRoutes(futureNode, currNode, context.children);
2129
- }
2130
- else {
2131
- // if we have a componentless route, we recurse but keep the same outlet map.
2132
- this.activateChildRoutes(futureNode, currNode, parentContexts);
2133
- }
2134
- }
2135
- else {
2136
- if (future.component) {
2137
- // if we have a normal route, we need to place the component into the outlet and recurse.
2138
- const context = parentContexts.getOrCreateContext(future.outlet);
2139
- if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2140
- const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2141
- this.routeReuseStrategy.store(future.snapshot, null);
2142
- context.children.onOutletReAttached(stored.contexts);
2143
- context.attachRef = stored.componentRef;
2144
- context.route = stored.route.value;
2145
- if (context.outlet) {
2146
- // Attach right away when the outlet has already been instantiated
2147
- // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2148
- context.outlet.attach(stored.componentRef, stored.route.value);
2149
- }
2150
- advanceActivatedRoute(stored.route.value);
2151
- this.activateChildRoutes(futureNode, null, context.children);
2152
- }
2153
- else {
2154
- const config = parentLoadedConfig(future.snapshot);
2155
- const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
2156
- context.attachRef = null;
2157
- context.route = future;
2158
- context.resolver = cmpFactoryResolver;
2159
- if (context.outlet) {
2160
- // Activate the outlet when it has already been instantiated
2161
- // Otherwise it will get activated from its `ngOnInit` when instantiated
2162
- context.outlet.activateWith(future, cmpFactoryResolver);
2163
- }
2164
- this.activateChildRoutes(futureNode, null, context.children);
2165
- }
2166
- }
2167
- else {
2168
- // if we have a componentless route, we recurse but keep the same outlet map.
2169
- this.activateChildRoutes(futureNode, null, parentContexts);
2170
- }
2138
+ onOutletReAttached(contexts) {
2139
+ this.contexts = contexts;
2140
+ }
2141
+ getOrCreateContext(childName) {
2142
+ let context = this.getContext(childName);
2143
+ if (!context) {
2144
+ context = new OutletContext();
2145
+ this.contexts.set(childName, context);
2171
2146
  }
2147
+ return context;
2172
2148
  }
2173
- }
2174
- function parentLoadedConfig(snapshot) {
2175
- for (let s = snapshot.parent; s; s = s.parent) {
2176
- const route = s.routeConfig;
2177
- if (route && route._loadedConfig)
2178
- return route._loadedConfig;
2179
- if (route && route.component)
2180
- return null;
2149
+ getContext(childName) {
2150
+ return this.contexts.get(childName) || null;
2181
2151
  }
2182
- return null;
2183
2152
  }
2184
2153
 
2185
2154
  /**
@@ -2189,182 +2158,13 @@ function parentLoadedConfig(snapshot) {
2189
2158
  * Use of this source code is governed by an MIT-style license that can be
2190
2159
  * found in the LICENSE file at https://angular.io/license
2191
2160
  */
2192
- class LoadedRouterConfig {
2193
- constructor(routes, module) {
2194
- this.routes = routes;
2195
- this.module = module;
2196
- }
2197
- }
2198
-
2199
2161
  /**
2200
- * @license
2201
- * Copyright Google LLC All Rights Reserved.
2162
+ * @description
2202
2163
  *
2203
- * Use of this source code is governed by an MIT-style license that can be
2204
- * found in the LICENSE file at https://angular.io/license
2205
- */
2206
- /**
2207
- * Simple function check, but generic so type inference will flow. Example:
2164
+ * Acts as a placeholder that Angular dynamically fills based on the current router state.
2208
2165
  *
2209
- * function product(a: number, b: number) {
2210
- * return a * b;
2211
- * }
2212
- *
2213
- * if (isFunction<product>(fn)) {
2214
- * return fn(1, 2);
2215
- * } else {
2216
- * throw "Must provide the `product` function";
2217
- * }
2218
- */
2219
- function isFunction(v) {
2220
- return typeof v === 'function';
2221
- }
2222
- function isBoolean(v) {
2223
- return typeof v === 'boolean';
2224
- }
2225
- function isUrlTree(v) {
2226
- return v instanceof UrlTree;
2227
- }
2228
- function isCanLoad(guard) {
2229
- return guard && isFunction(guard.canLoad);
2230
- }
2231
- function isCanActivate(guard) {
2232
- return guard && isFunction(guard.canActivate);
2233
- }
2234
- function isCanActivateChild(guard) {
2235
- return guard && isFunction(guard.canActivateChild);
2236
- }
2237
- function isCanDeactivate(guard) {
2238
- return guard && isFunction(guard.canDeactivate);
2239
- }
2240
-
2241
- /**
2242
- * @license
2243
- * Copyright Google LLC All Rights Reserved.
2244
- *
2245
- * Use of this source code is governed by an MIT-style license that can be
2246
- * found in the LICENSE file at https://angular.io/license
2247
- */
2248
- const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2249
- function prioritizedGuardValue() {
2250
- return switchMap(obs => {
2251
- return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2252
- .pipe(scan((acc, list) => {
2253
- let isPending = false;
2254
- return list.reduce((innerAcc, val, i) => {
2255
- if (innerAcc !== INITIAL_VALUE)
2256
- return innerAcc;
2257
- // Toggle pending flag if any values haven't been set yet
2258
- if (val === INITIAL_VALUE)
2259
- isPending = true;
2260
- // Any other return values are only valid if we haven't yet hit a pending
2261
- // call. This guarantees that in the case of a guard at the bottom of the
2262
- // tree that returns a redirect, we will wait for the higher priority
2263
- // guard at the top to finish before performing the redirect.
2264
- if (!isPending) {
2265
- // Early return when we hit a `false` value as that should always
2266
- // cancel navigation
2267
- if (val === false)
2268
- return val;
2269
- if (i === list.length - 1 || isUrlTree(val)) {
2270
- return val;
2271
- }
2272
- }
2273
- return innerAcc;
2274
- }, acc);
2275
- }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2276
- take(1));
2277
- });
2278
- }
2279
-
2280
- /**
2281
- * @license
2282
- * Copyright Google LLC All Rights Reserved.
2283
- *
2284
- * Use of this source code is governed by an MIT-style license that can be
2285
- * found in the LICENSE file at https://angular.io/license
2286
- */
2287
- /**
2288
- * Store contextual information about a `RouterOutlet`
2289
- *
2290
- * @publicApi
2291
- */
2292
- class OutletContext {
2293
- constructor() {
2294
- this.outlet = null;
2295
- this.route = null;
2296
- this.resolver = null;
2297
- this.children = new ChildrenOutletContexts();
2298
- this.attachRef = null;
2299
- }
2300
- }
2301
- /**
2302
- * Store contextual information about the children (= nested) `RouterOutlet`
2303
- *
2304
- * @publicApi
2305
- */
2306
- class ChildrenOutletContexts {
2307
- constructor() {
2308
- // contexts for child outlets, by name.
2309
- this.contexts = new Map();
2310
- }
2311
- /** Called when a `RouterOutlet` directive is instantiated */
2312
- onChildOutletCreated(childName, outlet) {
2313
- const context = this.getOrCreateContext(childName);
2314
- context.outlet = outlet;
2315
- this.contexts.set(childName, context);
2316
- }
2317
- /**
2318
- * Called when a `RouterOutlet` directive is destroyed.
2319
- * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2320
- * re-created later.
2321
- */
2322
- onChildOutletDestroyed(childName) {
2323
- const context = this.getContext(childName);
2324
- if (context) {
2325
- context.outlet = null;
2326
- context.attachRef = null;
2327
- }
2328
- }
2329
- /**
2330
- * Called when the corresponding route is deactivated during navigation.
2331
- * Because the component get destroyed, all children outlet are destroyed.
2332
- */
2333
- onOutletDeactivated() {
2334
- const contexts = this.contexts;
2335
- this.contexts = new Map();
2336
- return contexts;
2337
- }
2338
- onOutletReAttached(contexts) {
2339
- this.contexts = contexts;
2340
- }
2341
- getOrCreateContext(childName) {
2342
- let context = this.getContext(childName);
2343
- if (!context) {
2344
- context = new OutletContext();
2345
- this.contexts.set(childName, context);
2346
- }
2347
- return context;
2348
- }
2349
- getContext(childName) {
2350
- return this.contexts.get(childName) || null;
2351
- }
2352
- }
2353
-
2354
- /**
2355
- * @license
2356
- * Copyright Google LLC All Rights Reserved.
2357
- *
2358
- * Use of this source code is governed by an MIT-style license that can be
2359
- * found in the LICENSE file at https://angular.io/license
2360
- */
2361
- /**
2362
- * @description
2363
- *
2364
- * Acts as a placeholder that Angular dynamically fills based on the current router state.
2365
- *
2366
- * Each outlet can have a unique name, determined by the optional `name` attribute.
2367
- * The name cannot be set or changed dynamically. If not set, default value is "primary".
2166
+ * Each outlet can have a unique name, determined by the optional `name` attribute.
2167
+ * The name cannot be set or changed dynamically. If not set, default value is "primary".
2368
2168
  *
2369
2169
  * ```
2370
2170
  * <router-outlet></router-outlet>
@@ -2410,11 +2210,11 @@ class ChildrenOutletContexts {
2410
2210
  * @publicApi
2411
2211
  */
2412
2212
  class RouterOutlet {
2413
- constructor(parentContexts, location, resolver, name, changeDetector) {
2213
+ constructor(parentContexts, location, name, changeDetector, environmentInjector) {
2414
2214
  this.parentContexts = parentContexts;
2415
2215
  this.location = location;
2416
- this.resolver = resolver;
2417
2216
  this.changeDetector = changeDetector;
2217
+ this.environmentInjector = environmentInjector;
2418
2218
  this.activated = null;
2419
2219
  this._activatedRoute = null;
2420
2220
  this.activateEvents = new EventEmitter();
@@ -2449,7 +2249,7 @@ class RouterOutlet {
2449
2249
  }
2450
2250
  else {
2451
2251
  // otherwise the component defined in the configuration is created
2452
- this.activateWith(context.route, context.resolver || null);
2252
+ this.activateWith(context.route, context.injector);
2453
2253
  }
2454
2254
  }
2455
2255
  }
@@ -2508,34 +2308,40 @@ class RouterOutlet {
2508
2308
  this.deactivateEvents.emit(c);
2509
2309
  }
2510
2310
  }
2511
- activateWith(activatedRoute, resolver) {
2311
+ activateWith(activatedRoute, resolverOrInjector) {
2512
2312
  if (this.isActivated) {
2513
2313
  throw new Error('Cannot activate an already activated outlet');
2514
2314
  }
2515
2315
  this._activatedRoute = activatedRoute;
2316
+ const location = this.location;
2516
2317
  const snapshot = activatedRoute._futureSnapshot;
2517
- const component = snapshot.routeConfig.component;
2518
- resolver = resolver || this.resolver;
2519
- const factory = resolver.resolveComponentFactory(component);
2318
+ const component = snapshot.component;
2520
2319
  const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
2521
- const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
2522
- this.activated = this.location.createComponent(factory, this.location.length, injector);
2320
+ const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
2321
+ if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
2322
+ const factory = resolverOrInjector.resolveComponentFactory(component);
2323
+ this.activated = location.createComponent(factory, location.length, injector);
2324
+ }
2325
+ else {
2326
+ const environmentInjector = resolverOrInjector !== null && resolverOrInjector !== void 0 ? resolverOrInjector : this.environmentInjector;
2327
+ this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
2328
+ }
2523
2329
  // Calling `markForCheck` to make sure we will run the change detection when the
2524
2330
  // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
2525
2331
  this.changeDetector.markForCheck();
2526
2332
  this.activateEvents.emit(this.activated.instance);
2527
2333
  }
2528
2334
  }
2529
- RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
2530
- RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2531
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterOutlet, decorators: [{
2335
+ RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
2336
+ RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterOutlet, decorators: [{
2532
2338
  type: Directive,
2533
2339
  args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
2534
2340
  }], ctorParameters: function () {
2535
- return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: undefined, decorators: [{
2341
+ return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
2536
2342
  type: Attribute,
2537
2343
  args: ['name']
2538
- }] }, { type: i0.ChangeDetectorRef }];
2344
+ }] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
2539
2345
  }, propDecorators: { activateEvents: [{
2540
2346
  type: Output,
2541
2347
  args: ['activate']
@@ -2562,7 +2368,403 @@ class OutletInjector {
2562
2368
  if (token === ChildrenOutletContexts) {
2563
2369
  return this.childContexts;
2564
2370
  }
2565
- return this.parent.get(token, notFoundValue);
2371
+ return this.parent.get(token, notFoundValue);
2372
+ }
2373
+ }
2374
+ function isComponentFactoryResolver(item) {
2375
+ return !!item.resolveComponentFactory;
2376
+ }
2377
+
2378
+ /**
2379
+ * @license
2380
+ * Copyright Google LLC All Rights Reserved.
2381
+ *
2382
+ * Use of this source code is governed by an MIT-style license that can be
2383
+ * found in the LICENSE file at https://angular.io/license
2384
+ */
2385
+ /**
2386
+ * This component is used internally within the router to be a placeholder when an empty
2387
+ * router-outlet is needed. For example, with a config such as:
2388
+ *
2389
+ * `{path: 'parent', outlet: 'nav', children: [...]}`
2390
+ *
2391
+ * In order to render, there needs to be a component on this config, which will default
2392
+ * to this `EmptyOutletComponent`.
2393
+ */
2394
+ class ɵEmptyOutletComponent {
2395
+ }
2396
+ ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2397
+ ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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"] }] });
2398
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2399
+ type: Component,
2400
+ args: [{ template: `<router-outlet></router-outlet>` }]
2401
+ }] });
2402
+
2403
+ /**
2404
+ * @license
2405
+ * Copyright Google LLC All Rights Reserved.
2406
+ *
2407
+ * Use of this source code is governed by an MIT-style license that can be
2408
+ * found in the LICENSE file at https://angular.io/license
2409
+ */
2410
+ /**
2411
+ * Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist
2412
+ * and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the
2413
+ * `currentInjector`.
2414
+ *
2415
+ * @param route The route that might have providers
2416
+ * @param currentInjector The parent injector of the `Route`
2417
+ */
2418
+ function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
2419
+ var _a;
2420
+ if (route.providers && !route._injector) {
2421
+ route._injector =
2422
+ createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
2423
+ }
2424
+ return (_a = route._injector) !== null && _a !== void 0 ? _a : currentInjector;
2425
+ }
2426
+ function getLoadedRoutes(route) {
2427
+ return route._loadedRoutes;
2428
+ }
2429
+ function getLoadedInjector(route) {
2430
+ return route._loadedInjector;
2431
+ }
2432
+ function getLoadedComponent(route) {
2433
+ return route._loadedComponent;
2434
+ }
2435
+ function getProvidersInjector(route) {
2436
+ return route._injector;
2437
+ }
2438
+ function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
2439
+ // forEach doesn't iterate undefined values
2440
+ for (let i = 0; i < config.length; i++) {
2441
+ const route = config[i];
2442
+ const fullPath = getFullPath(parentPath, route);
2443
+ validateNode(route, fullPath, requireStandaloneComponents);
2444
+ }
2445
+ }
2446
+ function assertStandalone(fullPath, component) {
2447
+ if (component && !ɵisStandalone(component)) {
2448
+ throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
2449
+ }
2450
+ }
2451
+ function validateNode(route, fullPath, requireStandaloneComponents) {
2452
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
2453
+ if (!route) {
2454
+ throw new Error(`
2455
+ Invalid configuration of route '${fullPath}': Encountered undefined route.
2456
+ The reason might be an extra comma.
2457
+
2458
+ Example:
2459
+ const routes: Routes = [
2460
+ { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2461
+ { path: 'dashboard', component: DashboardComponent },, << two commas
2462
+ { path: 'detail/:id', component: HeroDetailComponent }
2463
+ ];
2464
+ `);
2465
+ }
2466
+ if (Array.isArray(route)) {
2467
+ throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2468
+ }
2469
+ if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
2470
+ (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2471
+ throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2472
+ }
2473
+ if (route.redirectTo && route.children) {
2474
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2475
+ }
2476
+ if (route.redirectTo && route.loadChildren) {
2477
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2478
+ }
2479
+ if (route.children && route.loadChildren) {
2480
+ throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2481
+ }
2482
+ if (route.redirectTo && (route.component || route.loadComponent)) {
2483
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
2484
+ }
2485
+ if (route.component && route.loadComponent) {
2486
+ throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
2487
+ }
2488
+ if (route.redirectTo && route.canActivate) {
2489
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2490
+ `so canActivate will never be executed.`);
2491
+ }
2492
+ if (route.path && route.matcher) {
2493
+ throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2494
+ }
2495
+ if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
2496
+ !route.children && !route.loadChildren) {
2497
+ throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
2498
+ }
2499
+ if (route.path === void 0 && route.matcher === void 0) {
2500
+ throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2501
+ }
2502
+ if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2503
+ throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2504
+ }
2505
+ if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2506
+ const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2507
+ throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2508
+ }
2509
+ if (requireStandaloneComponents) {
2510
+ assertStandalone(fullPath, route.component);
2511
+ }
2512
+ }
2513
+ if (route.children) {
2514
+ validateConfig(route.children, fullPath, requireStandaloneComponents);
2515
+ }
2516
+ }
2517
+ function getFullPath(parentPath, currentRoute) {
2518
+ if (!currentRoute) {
2519
+ return parentPath;
2520
+ }
2521
+ if (!parentPath && !currentRoute.path) {
2522
+ return '';
2523
+ }
2524
+ else if (parentPath && !currentRoute.path) {
2525
+ return `${parentPath}/`;
2526
+ }
2527
+ else if (!parentPath && currentRoute.path) {
2528
+ return currentRoute.path;
2529
+ }
2530
+ else {
2531
+ return `${parentPath}/${currentRoute.path}`;
2532
+ }
2533
+ }
2534
+ /**
2535
+ * Makes a copy of the config and adds any default required properties.
2536
+ */
2537
+ function standardizeConfig(r) {
2538
+ const children = r.children && r.children.map(standardizeConfig);
2539
+ const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2540
+ if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
2541
+ (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2542
+ c.component = ɵEmptyOutletComponent;
2543
+ }
2544
+ return c;
2545
+ }
2546
+ /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2547
+ function getOutlet(route) {
2548
+ return route.outlet || PRIMARY_OUTLET;
2549
+ }
2550
+ /**
2551
+ * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2552
+ * The order of the configs is otherwise preserved.
2553
+ */
2554
+ function sortByMatchingOutlets(routes, outletName) {
2555
+ const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2556
+ sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2557
+ return sortedConfig;
2558
+ }
2559
+ /**
2560
+ * Gets the first injector in the snapshot's parent tree.
2561
+ *
2562
+ * If the `Route` has a static list of providers, the returned injector will be the one created from
2563
+ * those. If it does not exist, the returned injector may come from the parents, which may be from a
2564
+ * loaded config or their static providers.
2565
+ *
2566
+ * Returns `null` if there is neither this nor any parents have a stored injector.
2567
+ *
2568
+ * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
2569
+ * also used for getting the correct injector to use for creating components.
2570
+ */
2571
+ function getClosestRouteInjector(snapshot) {
2572
+ var _a;
2573
+ if (!snapshot)
2574
+ return null;
2575
+ // If the current route has its own injector, which is created from the static providers on the
2576
+ // route itself, we should use that. Otherwise, we start at the parent since we do not want to
2577
+ // include the lazy loaded injector from this route.
2578
+ if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
2579
+ return snapshot.routeConfig._injector;
2580
+ }
2581
+ for (let s = snapshot.parent; s; s = s.parent) {
2582
+ const route = s.routeConfig;
2583
+ // Note that the order here is important. `_loadedInjector` stored on the route with
2584
+ // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
2585
+ // is created from the static providers on that parent route, so it applies to the children as
2586
+ // well, but only if there is no lazy loaded NgModuleRef injector.
2587
+ if (route === null || route === void 0 ? void 0 : route._loadedInjector)
2588
+ return route._loadedInjector;
2589
+ if (route === null || route === void 0 ? void 0 : route._injector)
2590
+ return route._injector;
2591
+ }
2592
+ return null;
2593
+ }
2594
+
2595
+ /**
2596
+ * @license
2597
+ * Copyright Google LLC All Rights Reserved.
2598
+ *
2599
+ * Use of this source code is governed by an MIT-style license that can be
2600
+ * found in the LICENSE file at https://angular.io/license
2601
+ */
2602
+ const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2603
+ new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2604
+ .activate(rootContexts);
2605
+ return t;
2606
+ });
2607
+ class ActivateRoutes {
2608
+ constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2609
+ this.routeReuseStrategy = routeReuseStrategy;
2610
+ this.futureState = futureState;
2611
+ this.currState = currState;
2612
+ this.forwardEvent = forwardEvent;
2613
+ }
2614
+ activate(parentContexts) {
2615
+ const futureRoot = this.futureState._root;
2616
+ const currRoot = this.currState ? this.currState._root : null;
2617
+ this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2618
+ advanceActivatedRoute(this.futureState.root);
2619
+ this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2620
+ }
2621
+ // De-activate the child route that are not re-used for the future state
2622
+ deactivateChildRoutes(futureNode, currNode, contexts) {
2623
+ const children = nodeChildrenAsMap(currNode);
2624
+ // Recurse on the routes active in the future state to de-activate deeper children
2625
+ futureNode.children.forEach(futureChild => {
2626
+ const childOutletName = futureChild.value.outlet;
2627
+ this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2628
+ delete children[childOutletName];
2629
+ });
2630
+ // De-activate the routes that will not be re-used
2631
+ forEach(children, (v, childName) => {
2632
+ this.deactivateRouteAndItsChildren(v, contexts);
2633
+ });
2634
+ }
2635
+ deactivateRoutes(futureNode, currNode, parentContext) {
2636
+ const future = futureNode.value;
2637
+ const curr = currNode ? currNode.value : null;
2638
+ if (future === curr) {
2639
+ // Reusing the node, check to see if the children need to be de-activated
2640
+ if (future.component) {
2641
+ // If we have a normal route, we need to go through an outlet.
2642
+ const context = parentContext.getContext(future.outlet);
2643
+ if (context) {
2644
+ this.deactivateChildRoutes(futureNode, currNode, context.children);
2645
+ }
2646
+ }
2647
+ else {
2648
+ // if we have a componentless route, we recurse but keep the same outlet map.
2649
+ this.deactivateChildRoutes(futureNode, currNode, parentContext);
2650
+ }
2651
+ }
2652
+ else {
2653
+ if (curr) {
2654
+ // Deactivate the current route which will not be re-used
2655
+ this.deactivateRouteAndItsChildren(currNode, parentContext);
2656
+ }
2657
+ }
2658
+ }
2659
+ deactivateRouteAndItsChildren(route, parentContexts) {
2660
+ // If there is no component, the Route is never attached to an outlet (because there is no
2661
+ // component to attach).
2662
+ if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2663
+ this.detachAndStoreRouteSubtree(route, parentContexts);
2664
+ }
2665
+ else {
2666
+ this.deactivateRouteAndOutlet(route, parentContexts);
2667
+ }
2668
+ }
2669
+ detachAndStoreRouteSubtree(route, parentContexts) {
2670
+ const context = parentContexts.getContext(route.value.outlet);
2671
+ const contexts = context && route.value.component ? context.children : parentContexts;
2672
+ const children = nodeChildrenAsMap(route);
2673
+ for (const childOutlet of Object.keys(children)) {
2674
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2675
+ }
2676
+ if (context && context.outlet) {
2677
+ const componentRef = context.outlet.detach();
2678
+ const contexts = context.children.onOutletDeactivated();
2679
+ this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2680
+ }
2681
+ }
2682
+ deactivateRouteAndOutlet(route, parentContexts) {
2683
+ const context = parentContexts.getContext(route.value.outlet);
2684
+ // The context could be `null` if we are on a componentless route but there may still be
2685
+ // children that need deactivating.
2686
+ const contexts = context && route.value.component ? context.children : parentContexts;
2687
+ const children = nodeChildrenAsMap(route);
2688
+ for (const childOutlet of Object.keys(children)) {
2689
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2690
+ }
2691
+ if (context && context.outlet) {
2692
+ // Destroy the component
2693
+ context.outlet.deactivate();
2694
+ // Destroy the contexts for all the outlets that were in the component
2695
+ context.children.onOutletDeactivated();
2696
+ // Clear the information about the attached component on the context but keep the reference to
2697
+ // the outlet.
2698
+ context.attachRef = null;
2699
+ context.resolver = null;
2700
+ context.route = null;
2701
+ }
2702
+ }
2703
+ activateChildRoutes(futureNode, currNode, contexts) {
2704
+ const children = nodeChildrenAsMap(currNode);
2705
+ futureNode.children.forEach(c => {
2706
+ this.activateRoutes(c, children[c.value.outlet], contexts);
2707
+ this.forwardEvent(new ActivationEnd(c.value.snapshot));
2708
+ });
2709
+ if (futureNode.children.length) {
2710
+ this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2711
+ }
2712
+ }
2713
+ activateRoutes(futureNode, currNode, parentContexts) {
2714
+ var _a;
2715
+ const future = futureNode.value;
2716
+ const curr = currNode ? currNode.value : null;
2717
+ advanceActivatedRoute(future);
2718
+ // reusing the node
2719
+ if (future === curr) {
2720
+ if (future.component) {
2721
+ // If we have a normal route, we need to go through an outlet.
2722
+ const context = parentContexts.getOrCreateContext(future.outlet);
2723
+ this.activateChildRoutes(futureNode, currNode, context.children);
2724
+ }
2725
+ else {
2726
+ // if we have a componentless route, we recurse but keep the same outlet map.
2727
+ this.activateChildRoutes(futureNode, currNode, parentContexts);
2728
+ }
2729
+ }
2730
+ else {
2731
+ if (future.component) {
2732
+ // if we have a normal route, we need to place the component into the outlet and recurse.
2733
+ const context = parentContexts.getOrCreateContext(future.outlet);
2734
+ if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2735
+ const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2736
+ this.routeReuseStrategy.store(future.snapshot, null);
2737
+ context.children.onOutletReAttached(stored.contexts);
2738
+ context.attachRef = stored.componentRef;
2739
+ context.route = stored.route.value;
2740
+ if (context.outlet) {
2741
+ // Attach right away when the outlet has already been instantiated
2742
+ // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2743
+ context.outlet.attach(stored.componentRef, stored.route.value);
2744
+ }
2745
+ advanceActivatedRoute(stored.route.value);
2746
+ this.activateChildRoutes(futureNode, null, context.children);
2747
+ }
2748
+ else {
2749
+ const injector = getClosestRouteInjector(future.snapshot);
2750
+ const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
2751
+ context.attachRef = null;
2752
+ context.route = future;
2753
+ context.resolver = cmpFactoryResolver;
2754
+ context.injector = injector;
2755
+ if (context.outlet) {
2756
+ // Activate the outlet when it has already been instantiated
2757
+ // Otherwise it will get activated from its `ngOnInit` when instantiated
2758
+ context.outlet.activateWith(future, context.injector);
2759
+ }
2760
+ this.activateChildRoutes(futureNode, null, context.children);
2761
+ }
2762
+ }
2763
+ else {
2764
+ // if we have a componentless route, we recurse but keep the same outlet map.
2765
+ this.activateChildRoutes(futureNode, null, parentContexts);
2766
+ }
2767
+ }
2566
2768
  }
2567
2769
  }
2568
2770
 
@@ -2574,22 +2776,39 @@ class OutletInjector {
2574
2776
  * found in the LICENSE file at https://angular.io/license
2575
2777
  */
2576
2778
  /**
2577
- * This component is used internally within the router to be a placeholder when an empty
2578
- * router-outlet is needed. For example, with a config such as:
2779
+ * Simple function check, but generic so type inference will flow. Example:
2579
2780
  *
2580
- * `{path: 'parent', outlet: 'nav', children: [...]}`
2781
+ * function product(a: number, b: number) {
2782
+ * return a * b;
2783
+ * }
2581
2784
  *
2582
- * In order to render, there needs to be a component on this config, which will default
2583
- * to this `EmptyOutletComponent`.
2785
+ * if (isFunction<product>(fn)) {
2786
+ * return fn(1, 2);
2787
+ * } else {
2788
+ * throw "Must provide the `product` function";
2789
+ * }
2584
2790
  */
2585
- class ɵEmptyOutletComponent {
2791
+ function isFunction(v) {
2792
+ return typeof v === 'function';
2793
+ }
2794
+ function isBoolean(v) {
2795
+ return typeof v === 'boolean';
2796
+ }
2797
+ function isUrlTree(v) {
2798
+ return v instanceof UrlTree;
2799
+ }
2800
+ function isCanLoad(guard) {
2801
+ return guard && isFunction(guard.canLoad);
2802
+ }
2803
+ function isCanActivate(guard) {
2804
+ return guard && isFunction(guard.canActivate);
2805
+ }
2806
+ function isCanActivateChild(guard) {
2807
+ return guard && isFunction(guard.canActivateChild);
2808
+ }
2809
+ function isCanDeactivate(guard) {
2810
+ return guard && isFunction(guard.canDeactivate);
2586
2811
  }
2587
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2588
- ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.9", 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"] }] });
2589
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2590
- type: Component,
2591
- args: [{ template: `<router-outlet></router-outlet>` }]
2592
- }] });
2593
2812
 
2594
2813
  /**
2595
2814
  * @license
@@ -2598,113 +2817,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
2598
2817
  * Use of this source code is governed by an MIT-style license that can be
2599
2818
  * found in the LICENSE file at https://angular.io/license
2600
2819
  */
2601
- function validateConfig(config, parentPath = '') {
2602
- // forEach doesn't iterate undefined values
2603
- for (let i = 0; i < config.length; i++) {
2604
- const route = config[i];
2605
- const fullPath = getFullPath(parentPath, route);
2606
- validateNode(route, fullPath);
2607
- }
2608
- }
2609
- function validateNode(route, fullPath) {
2610
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
2611
- if (!route) {
2612
- throw new Error(`
2613
- Invalid configuration of route '${fullPath}': Encountered undefined route.
2614
- The reason might be an extra comma.
2615
-
2616
- Example:
2617
- const routes: Routes = [
2618
- { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2619
- { path: 'dashboard', component: DashboardComponent },, << two commas
2620
- { path: 'detail/:id', component: HeroDetailComponent }
2621
- ];
2622
- `);
2623
- }
2624
- if (Array.isArray(route)) {
2625
- throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2626
- }
2627
- if (!route.component && !route.children && !route.loadChildren &&
2628
- (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2629
- throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2630
- }
2631
- if (route.redirectTo && route.children) {
2632
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2633
- }
2634
- if (route.redirectTo && route.loadChildren) {
2635
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2636
- }
2637
- if (route.children && route.loadChildren) {
2638
- throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2639
- }
2640
- if (route.redirectTo && route.component) {
2641
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
2642
- }
2643
- if (route.redirectTo && route.canActivate) {
2644
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2645
- `so canActivate will never be executed.`);
2646
- }
2647
- if (route.path && route.matcher) {
2648
- throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2649
- }
2650
- if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
2651
- throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
2652
- }
2653
- if (route.path === void 0 && route.matcher === void 0) {
2654
- throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2655
- }
2656
- if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2657
- throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2658
- }
2659
- if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2660
- const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2661
- throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2662
- }
2663
- }
2664
- if (route.children) {
2665
- validateConfig(route.children, fullPath);
2666
- }
2667
- }
2668
- function getFullPath(parentPath, currentRoute) {
2669
- if (!currentRoute) {
2670
- return parentPath;
2671
- }
2672
- if (!parentPath && !currentRoute.path) {
2673
- return '';
2674
- }
2675
- else if (parentPath && !currentRoute.path) {
2676
- return `${parentPath}/`;
2677
- }
2678
- else if (!parentPath && currentRoute.path) {
2679
- return currentRoute.path;
2680
- }
2681
- else {
2682
- return `${parentPath}/${currentRoute.path}`;
2683
- }
2684
- }
2685
- /**
2686
- * Makes a copy of the config and adds any default required properties.
2687
- */
2688
- function standardizeConfig(r) {
2689
- const children = r.children && r.children.map(standardizeConfig);
2690
- const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2691
- if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2692
- c.component = ɵEmptyOutletComponent;
2693
- }
2694
- return c;
2695
- }
2696
- /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2697
- function getOutlet(route) {
2698
- return route.outlet || PRIMARY_OUTLET;
2699
- }
2700
- /**
2701
- * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2702
- * The order of the configs is otherwise preserved.
2703
- */
2704
- function sortByMatchingOutlets(routes, outletName) {
2705
- const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2706
- sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2707
- return sortedConfig;
2820
+ const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2821
+ function prioritizedGuardValue() {
2822
+ return switchMap(obs => {
2823
+ return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2824
+ .pipe(scan((acc, list) => {
2825
+ let isPending = false;
2826
+ return list.reduce((innerAcc, val, i) => {
2827
+ if (innerAcc !== INITIAL_VALUE)
2828
+ return innerAcc;
2829
+ // Toggle pending flag if any values haven't been set yet
2830
+ if (val === INITIAL_VALUE)
2831
+ isPending = true;
2832
+ // Any other return values are only valid if we haven't yet hit a pending
2833
+ // call. This guarantees that in the case of a guard at the bottom of the
2834
+ // tree that returns a redirect, we will wait for the higher priority
2835
+ // guard at the top to finish before performing the redirect.
2836
+ if (!isPending) {
2837
+ // Early return when we hit a `false` value as that should always
2838
+ // cancel navigation
2839
+ if (val === false)
2840
+ return val;
2841
+ if (i === list.length - 1 || isUrlTree(val)) {
2842
+ return val;
2843
+ }
2844
+ }
2845
+ return innerAcc;
2846
+ }, acc);
2847
+ }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2848
+ take(1));
2849
+ });
2708
2850
  }
2709
2851
 
2710
2852
  /**
@@ -2782,6 +2924,9 @@ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedS
2782
2924
  s._sourceSegment = segmentGroup;
2783
2925
  if (relativeLinkResolution === 'legacy') {
2784
2926
  s._segmentIndexShift = segmentGroup.segments.length;
2927
+ if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
2928
+ s._segmentIndexShiftCorrected = consumedSegments.length;
2929
+ }
2785
2930
  }
2786
2931
  else {
2787
2932
  s._segmentIndexShift = consumedSegments.length;
@@ -2882,17 +3027,17 @@ function canLoadFails(route) {
2882
3027
  *
2883
3028
  * Lazy modules are loaded along the way.
2884
3029
  */
2885
- function applyRedirects$1(moduleInjector, configLoader, urlSerializer, urlTree, config) {
2886
- return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
3030
+ function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
3031
+ return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
2887
3032
  }
2888
3033
  class ApplyRedirects {
2889
- constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
3034
+ constructor(injector, configLoader, urlSerializer, urlTree, config) {
3035
+ this.injector = injector;
2890
3036
  this.configLoader = configLoader;
2891
3037
  this.urlSerializer = urlSerializer;
2892
3038
  this.urlTree = urlTree;
2893
3039
  this.config = config;
2894
3040
  this.allowRedirects = true;
2895
- this.ngModule = moduleInjector.get(NgModuleRef);
2896
3041
  }
2897
3042
  apply() {
2898
3043
  const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
@@ -2903,7 +3048,7 @@ class ApplyRedirects {
2903
3048
  // them. We should be able to remove this logic as a "breaking change" but should do some more
2904
3049
  // investigation into the failures first.
2905
3050
  const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
2906
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, rootSegmentGroup, PRIMARY_OUTLET);
3051
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
2907
3052
  const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
2908
3053
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
2909
3054
  }));
@@ -2922,7 +3067,7 @@ class ApplyRedirects {
2922
3067
  }));
2923
3068
  }
2924
3069
  match(tree) {
2925
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
3070
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
2926
3071
  const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
2927
3072
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
2928
3073
  }));
@@ -2942,15 +3087,15 @@ class ApplyRedirects {
2942
3087
  rootCandidate;
2943
3088
  return new UrlTree(root, queryParams, fragment);
2944
3089
  }
2945
- expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
3090
+ expandSegmentGroup(injector, routes, segmentGroup, outlet) {
2946
3091
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
2947
- return this.expandChildren(ngModule, routes, segmentGroup)
3092
+ return this.expandChildren(injector, routes, segmentGroup)
2948
3093
  .pipe(map((children) => new UrlSegmentGroup([], children)));
2949
3094
  }
2950
- return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
3095
+ return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
2951
3096
  }
2952
3097
  // Recursively expand segment groups for all the child outlets
2953
- expandChildren(ngModule, routes, segmentGroup) {
3098
+ expandChildren(injector, routes, segmentGroup) {
2954
3099
  // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
2955
3100
  // because an absolute redirect from the primary outlet takes precedence.
2956
3101
  const childOutlets = [];
@@ -2969,16 +3114,16 @@ class ApplyRedirects {
2969
3114
  // first, followed by routes for other outlets, which might match if they have an
2970
3115
  // empty path.
2971
3116
  const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
2972
- return this.expandSegmentGroup(ngModule, sortedRoutes, child, childOutlet)
3117
+ return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
2973
3118
  .pipe(map(s => ({ segment: s, outlet: childOutlet })));
2974
3119
  }), scan((children, expandedChild) => {
2975
3120
  children[expandedChild.outlet] = expandedChild.segment;
2976
3121
  return children;
2977
3122
  }, {}), last$1());
2978
3123
  }
2979
- expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
2980
- return from(routes).pipe(concatMap((r) => {
2981
- const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
3124
+ expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
3125
+ return from(routes).pipe(concatMap(r => {
3126
+ const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
2982
3127
  return expanded$.pipe(catchError((e) => {
2983
3128
  if (e instanceof NoMatch$1) {
2984
3129
  return of(null);
@@ -2995,35 +3140,35 @@ class ApplyRedirects {
2995
3140
  throw e;
2996
3141
  }));
2997
3142
  }
2998
- expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3143
+ expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
2999
3144
  if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
3000
3145
  return noMatch(segmentGroup);
3001
3146
  }
3002
3147
  if (route.redirectTo === undefined) {
3003
- return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths, outlet);
3148
+ return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
3004
3149
  }
3005
3150
  if (allowRedirects && this.allowRedirects) {
3006
- return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
3151
+ return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
3007
3152
  }
3008
3153
  return noMatch(segmentGroup);
3009
3154
  }
3010
- expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3155
+ expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3011
3156
  if (route.path === '**') {
3012
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
3157
+ return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3013
3158
  }
3014
- return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
3159
+ return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3015
3160
  }
3016
- expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
3161
+ expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3017
3162
  const newTree = this.applyRedirectCommands([], route.redirectTo, {});
3018
3163
  if (route.redirectTo.startsWith('/')) {
3019
3164
  return absoluteRedirect(newTree);
3020
3165
  }
3021
3166
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3022
3167
  const group = new UrlSegmentGroup(newSegments, {});
3023
- return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
3168
+ return this.expandSegment(injector, group, routes, newSegments, outlet, false);
3024
3169
  }));
3025
3170
  }
3026
- expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3171
+ expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3027
3172
  const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3028
3173
  if (!matched)
3029
3174
  return noMatch(segmentGroup);
@@ -3032,16 +3177,20 @@ class ApplyRedirects {
3032
3177
  return absoluteRedirect(newTree);
3033
3178
  }
3034
3179
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3035
- return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3180
+ return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3036
3181
  }));
3037
3182
  }
3038
- matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments, outlet) {
3183
+ matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
3039
3184
  if (route.path === '**') {
3185
+ // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
3186
+ injector = getOrCreateRouteInjectorIfNeeded(route, injector);
3040
3187
  if (route.loadChildren) {
3041
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
3042
- this.configLoader.load(ngModule.injector, route);
3188
+ const loaded$ = route._loadedRoutes ?
3189
+ of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
3190
+ this.configLoader.loadChildren(injector, route);
3043
3191
  return loaded$.pipe(map((cfg) => {
3044
- route._loadedConfig = cfg;
3192
+ route._loadedRoutes = cfg.routes;
3193
+ route._loadedInjector = cfg.injector;
3045
3194
  return new UrlSegmentGroup(segments, {});
3046
3195
  }));
3047
3196
  }
@@ -3050,55 +3199,58 @@ class ApplyRedirects {
3050
3199
  const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
3051
3200
  if (!matched)
3052
3201
  return noMatch(rawSegmentGroup);
3053
- const childConfig$ = this.getChildConfig(ngModule, route, segments);
3202
+ // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
3203
+ injector = getOrCreateRouteInjectorIfNeeded(route, injector);
3204
+ const childConfig$ = this.getChildConfig(injector, route, segments);
3054
3205
  return childConfig$.pipe(mergeMap((routerConfig) => {
3055
- const childModule = routerConfig.module;
3206
+ var _a;
3207
+ const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
3056
3208
  const childConfig = routerConfig.routes;
3057
3209
  const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3058
3210
  // See comment on the other call to `split` about why this is necessary.
3059
3211
  const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3060
3212
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3061
- const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
3213
+ const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3062
3214
  return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3063
3215
  }
3064
3216
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3065
3217
  return of(new UrlSegmentGroup(consumedSegments, {}));
3066
3218
  }
3067
3219
  const matchedOnOutlet = getOutlet(route) === outlet;
3068
- const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3220
+ const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3069
3221
  return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3070
3222
  }));
3071
3223
  }
3072
- getChildConfig(ngModule, route, segments) {
3224
+ getChildConfig(injector, route, segments) {
3073
3225
  if (route.children) {
3074
3226
  // The children belong to the same module
3075
- return of(new LoadedRouterConfig(route.children, ngModule));
3227
+ return of({ routes: route.children, injector });
3076
3228
  }
3077
3229
  if (route.loadChildren) {
3078
3230
  // lazy children belong to the loaded module
3079
- if (route._loadedConfig !== undefined) {
3080
- return of(route._loadedConfig);
3231
+ if (route._loadedRoutes !== undefined) {
3232
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3081
3233
  }
3082
- return this.runCanLoadGuards(ngModule.injector, route, segments)
3234
+ return this.runCanLoadGuards(injector, route, segments)
3083
3235
  .pipe(mergeMap((shouldLoadResult) => {
3084
3236
  if (shouldLoadResult) {
3085
- return this.configLoader.load(ngModule.injector, route)
3086
- .pipe(map((cfg) => {
3087
- route._loadedConfig = cfg;
3088
- return cfg;
3237
+ return this.configLoader.loadChildren(injector, route)
3238
+ .pipe(tap((cfg) => {
3239
+ route._loadedRoutes = cfg.routes;
3240
+ route._loadedInjector = cfg.injector;
3089
3241
  }));
3090
3242
  }
3091
3243
  return canLoadFails(route);
3092
3244
  }));
3093
3245
  }
3094
- return of(new LoadedRouterConfig([], ngModule));
3246
+ return of({ routes: [], injector });
3095
3247
  }
3096
- runCanLoadGuards(moduleInjector, route, segments) {
3248
+ runCanLoadGuards(injector, route, segments) {
3097
3249
  const canLoad = route.canLoad;
3098
3250
  if (!canLoad || canLoad.length === 0)
3099
3251
  return of(true);
3100
3252
  const canLoadObservables = canLoad.map((injectionToken) => {
3101
- const guard = moduleInjector.get(injectionToken);
3253
+ const guard = injector.get(injectionToken);
3102
3254
  let guardVal;
3103
3255
  if (isCanLoad(guard)) {
3104
3256
  guardVal = guard.canLoad(route, segments);
@@ -3226,8 +3378,8 @@ function squashSegmentGroup(segmentGroup) {
3226
3378
  * Use of this source code is governed by an MIT-style license that can be
3227
3379
  * found in the LICENSE file at https://angular.io/license
3228
3380
  */
3229
- function applyRedirects(moduleInjector, configLoader, urlSerializer, config) {
3230
- return switchMap(t => applyRedirects$1(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
3381
+ function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3382
+ return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3231
3383
  .pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
3232
3384
  }
3233
3385
 
@@ -3261,21 +3413,11 @@ function getCanActivateChild(p) {
3261
3413
  return null;
3262
3414
  return { node: p, guards: canActivateChild };
3263
3415
  }
3264
- function getToken(token, snapshot, moduleInjector) {
3265
- const config = getClosestLoadedConfig(snapshot);
3266
- const injector = config ? config.module.injector : moduleInjector;
3416
+ function getToken(token, snapshot, fallbackInjector) {
3417
+ const routeInjector = getClosestRouteInjector(snapshot);
3418
+ const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
3267
3419
  return injector.get(token);
3268
3420
  }
3269
- function getClosestLoadedConfig(snapshot) {
3270
- if (!snapshot)
3271
- return null;
3272
- for (let s = snapshot.parent; s; s = s.parent) {
3273
- const route = s.routeConfig;
3274
- if (route && route._loadedConfig)
3275
- return route._loadedConfig;
3276
- }
3277
- return null;
3278
- }
3279
3421
  function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
3280
3422
  canDeactivateChecks: [],
3281
3423
  canActivateChecks: []
@@ -3519,6 +3661,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
3519
3661
  * Use of this source code is governed by an MIT-style license that can be
3520
3662
  * found in the LICENSE file at https://angular.io/license
3521
3663
  */
3664
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3522
3665
  class NoMatch {
3523
3666
  }
3524
3667
  function newObservableError(e) {
@@ -3627,6 +3770,7 @@ class Recognizer {
3627
3770
  return null;
3628
3771
  }
3629
3772
  processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
3773
+ var _a, _b, _c, _d;
3630
3774
  if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet))
3631
3775
  return null;
3632
3776
  let snapshot;
@@ -3634,7 +3778,13 @@ class Recognizer {
3634
3778
  let remainingSegments = [];
3635
3779
  if (route.path === '**') {
3636
3780
  const params = segments.length > 0 ? last(segments).parameters : {};
3637
- 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));
3781
+ const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
3782
+ snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), (_b = (_a = route.component) !== null && _a !== void 0 ? _a : route._loadedComponent) !== null && _b !== void 0 ? _b : null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
3783
+ // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
3784
+ // production bundle size. This value is intended only to surface a warning to users
3785
+ // depending on `relativeLinkResolution: 'legacy'` in dev mode.
3786
+ (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3787
+ pathIndexShift));
3638
3788
  }
3639
3789
  else {
3640
3790
  const result = match(rawSegment, route, segments);
@@ -3643,7 +3793,9 @@ class Recognizer {
3643
3793
  }
3644
3794
  consumedSegments = result.consumedSegments;
3645
3795
  remainingSegments = result.remainingSegments;
3646
- 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));
3796
+ const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3797
+ snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), (_d = (_c = route.component) !== null && _c !== void 0 ? _c : route._loadedComponent) !== null && _d !== void 0 ? _d : null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
3798
+ pathIndexShift));
3647
3799
  }
3648
3800
  const childConfig = getChildConfig(route);
3649
3801
  const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
@@ -3691,7 +3843,7 @@ function getChildConfig(route) {
3691
3843
  return route.children;
3692
3844
  }
3693
3845
  if (route.loadChildren) {
3694
- return route._loadedConfig.routes;
3846
+ return route._loadedRoutes;
3695
3847
  }
3696
3848
  return [];
3697
3849
  }
@@ -3752,11 +3904,22 @@ function getSourceSegmentGroup(segmentGroup) {
3752
3904
  return s;
3753
3905
  }
3754
3906
  function getPathIndexShift(segmentGroup) {
3907
+ var _a, _b;
3908
+ let s = segmentGroup;
3909
+ let res = (_a = s._segmentIndexShift) !== null && _a !== void 0 ? _a : 0;
3910
+ while (s._sourceSegment) {
3911
+ s = s._sourceSegment;
3912
+ res += (_b = s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
3913
+ }
3914
+ return res - 1;
3915
+ }
3916
+ function getCorrectedPathIndexShift(segmentGroup) {
3917
+ var _a, _b, _c, _d;
3755
3918
  let s = segmentGroup;
3756
- let res = (s._segmentIndexShift ? s._segmentIndexShift : 0);
3919
+ let res = (_b = (_a = s._segmentIndexShiftCorrected) !== null && _a !== void 0 ? _a : s._segmentIndexShift) !== null && _b !== void 0 ? _b : 0;
3757
3920
  while (s._sourceSegment) {
3758
3921
  s = s._sourceSegment;
3759
- res += (s._segmentIndexShift ? s._segmentIndexShift : 0);
3922
+ res += (_d = (_c = s._segmentIndexShiftCorrected) !== null && _c !== void 0 ? _c : s._segmentIndexShift) !== null && _d !== void 0 ? _d : 0;
3760
3923
  }
3761
3924
  return res - 1;
3762
3925
  }
@@ -3806,19 +3969,16 @@ function resolveData(paramsInheritanceStrategy, moduleInjector) {
3806
3969
  function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
3807
3970
  const config = futureARS.routeConfig;
3808
3971
  const resolve = futureARS._resolve;
3809
- const data = Object.assign({}, futureARS.data);
3810
- if ((config === null || config === void 0 ? void 0 : config.title) !== undefined) {
3811
- if (typeof config.title === 'string' || config.title === null) {
3812
- data[RouteTitle] = config.title;
3813
- }
3814
- else {
3815
- resolve[RouteTitle] = config.title;
3816
- }
3972
+ if ((config === null || config === void 0 ? void 0 : config.title) !== undefined && !hasStaticTitle(config)) {
3973
+ resolve[RouteTitle] = config.title;
3817
3974
  }
3818
3975
  return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
3819
3976
  .pipe(map((resolvedData) => {
3820
3977
  futureARS._resolvedData = resolvedData;
3821
- futureARS.data = Object.assign(Object.assign({}, data), inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve);
3978
+ futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;
3979
+ if (config && hasStaticTitle(config)) {
3980
+ futureARS.data[RouteTitle] = config.title;
3981
+ }
3822
3982
  return null;
3823
3983
  }));
3824
3984
  }
@@ -3829,16 +3989,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
3829
3989
  }
3830
3990
  const data = {};
3831
3991
  return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
3832
- .pipe(take(1), tap((value) => {
3992
+ .pipe(first(), tap((value) => {
3833
3993
  data[key] = value;
3834
- }))), takeLast(1), mergeMap(() => {
3835
- // Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
3836
- // the chain which will cancel navigation
3837
- if (getDataKeys(data).length === keys.length) {
3838
- return of(data);
3839
- }
3840
- return EMPTY;
3841
- }));
3994
+ }))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
3842
3995
  }
3843
3996
  function getDataKeys(obj) {
3844
3997
  return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
@@ -3848,6 +4001,9 @@ function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
3848
4001
  return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
3849
4002
  wrapIntoObservable(resolver(futureARS, futureRSS));
3850
4003
  }
4004
+ function hasStaticTitle(config) {
4005
+ return typeof config.title === 'string' || config.title === null;
4006
+ }
3851
4007
 
3852
4008
  /**
3853
4009
  * @license
@@ -3944,6 +4100,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3944
4100
  * Use of this source code is governed by an MIT-style license that can be
3945
4101
  * found in the LICENSE file at https://angular.io/license
3946
4102
  */
4103
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3947
4104
  /**
3948
4105
  * The [DI token](guide/glossary/#di-token) for a router configuration.
3949
4106
  *
@@ -3956,43 +4113,85 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3956
4113
  */
3957
4114
  const ROUTES = new InjectionToken('ROUTES');
3958
4115
  class RouterConfigLoader {
3959
- constructor(injector, compiler, onLoadStartListener, onLoadEndListener) {
4116
+ constructor(injector, compiler) {
3960
4117
  this.injector = injector;
3961
4118
  this.compiler = compiler;
3962
- this.onLoadStartListener = onLoadStartListener;
3963
- this.onLoadEndListener = onLoadEndListener;
4119
+ this.componentLoaders = new WeakMap();
4120
+ this.childrenLoaders = new WeakMap();
4121
+ }
4122
+ loadComponent(route) {
4123
+ if (this.componentLoaders.get(route)) {
4124
+ return this.componentLoaders.get(route);
4125
+ }
4126
+ else if (route._loadedComponent) {
4127
+ return of(route._loadedComponent);
4128
+ }
4129
+ if (this.onLoadStartListener) {
4130
+ this.onLoadStartListener(route);
4131
+ }
4132
+ const loadRunner = wrapIntoObservable(route.loadComponent())
4133
+ .pipe(tap(component => {
4134
+ var _a;
4135
+ if (this.onLoadEndListener) {
4136
+ this.onLoadEndListener(route);
4137
+ }
4138
+ NG_DEV_MODE$1 && assertStandalone((_a = route.path) !== null && _a !== void 0 ? _a : '', component);
4139
+ route._loadedComponent = component;
4140
+ }), finalize(() => {
4141
+ this.componentLoaders.delete(route);
4142
+ }));
4143
+ // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
4144
+ const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
4145
+ this.componentLoaders.set(route, loader);
4146
+ return loader;
3964
4147
  }
3965
- load(parentInjector, route) {
3966
- if (route._loader$) {
3967
- return route._loader$;
4148
+ loadChildren(parentInjector, route) {
4149
+ if (this.childrenLoaders.get(route)) {
4150
+ return this.childrenLoaders.get(route);
4151
+ }
4152
+ else if (route._loadedRoutes) {
4153
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3968
4154
  }
3969
4155
  if (this.onLoadStartListener) {
3970
4156
  this.onLoadStartListener(route);
3971
4157
  }
3972
- const moduleFactory$ = this.loadModuleFactory(route.loadChildren);
3973
- const loadRunner = moduleFactory$.pipe(map((factory) => {
4158
+ const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
4159
+ const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
3974
4160
  if (this.onLoadEndListener) {
3975
4161
  this.onLoadEndListener(route);
3976
4162
  }
3977
- const module = factory.create(parentInjector);
3978
- // When loading a module that doesn't provide `RouterModule.forChild()` preloader
3979
- // will get stuck in an infinite loop. The child module's Injector will look to
3980
- // its parent `Injector` when it doesn't find any ROUTES so it will return routes
3981
- // for it's parent module instead.
3982
- return new LoadedRouterConfig(flatten(module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))
3983
- .map(standardizeConfig), module);
3984
- }), catchError((err) => {
3985
- route._loader$ = undefined;
3986
- throw err;
4163
+ // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
4164
+ // injector associated with lazy loading a `Route` array.
4165
+ let injector;
4166
+ let rawRoutes;
4167
+ let requireStandaloneComponents = false;
4168
+ if (Array.isArray(factoryOrRoutes)) {
4169
+ rawRoutes = factoryOrRoutes;
4170
+ requireStandaloneComponents = true;
4171
+ }
4172
+ else {
4173
+ injector = factoryOrRoutes.create(parentInjector).injector;
4174
+ // When loading a module that doesn't provide `RouterModule.forChild()` preloader
4175
+ // will get stuck in an infinite loop. The child module's Injector will look to
4176
+ // its parent `Injector` when it doesn't find any ROUTES so it will return routes
4177
+ // for it's parent module instead.
4178
+ rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
4179
+ }
4180
+ const routes = rawRoutes.map(standardizeConfig);
4181
+ NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
4182
+ return { routes, injector };
4183
+ }), finalize(() => {
4184
+ this.childrenLoaders.delete(route);
3987
4185
  }));
3988
4186
  // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
3989
- route._loader$ = new ConnectableObservable(loadRunner, () => new Subject())
4187
+ const loader = new ConnectableObservable(loadRunner, () => new Subject())
3990
4188
  .pipe(refCount());
3991
- return route._loader$;
4189
+ this.childrenLoaders.set(route, loader);
4190
+ return loader;
3992
4191
  }
3993
- loadModuleFactory(loadChildren) {
4192
+ loadModuleFactoryOrRoutes(loadChildren) {
3994
4193
  return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
3995
- if (t instanceof NgModuleFactory) {
4194
+ if (t instanceof NgModuleFactory || Array.isArray(t)) {
3996
4195
  return of(t);
3997
4196
  }
3998
4197
  else {
@@ -4001,6 +4200,11 @@ class RouterConfigLoader {
4001
4200
  }));
4002
4201
  }
4003
4202
  }
4203
+ RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4204
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader });
4205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
4206
+ type: Injectable
4207
+ }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
4004
4208
 
4005
4209
  /**
4006
4210
  * @license
@@ -4033,6 +4237,7 @@ class DefaultUrlHandlingStrategy {
4033
4237
  }
4034
4238
  }
4035
4239
 
4240
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
4036
4241
  function defaultErrorHandler(error) {
4037
4242
  throw error;
4038
4243
  }
@@ -4175,6 +4380,8 @@ class Router {
4175
4380
  /**
4176
4381
  * Enables a bug fix that corrects relative link resolution in components with empty paths.
4177
4382
  * @see `RouterModule`
4383
+ *
4384
+ * @deprecated
4178
4385
  */
4179
4386
  this.relativeLinkResolution = 'corrected';
4180
4387
  /**
@@ -4202,6 +4409,9 @@ class Router {
4202
4409
  this.canceledNavigationResolution = 'replace';
4203
4410
  const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
4204
4411
  const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
4412
+ this.configLoader = injector.get(RouterConfigLoader);
4413
+ this.configLoader.onLoadEndListener = onLoadEnd;
4414
+ this.configLoader.onLoadStartListener = onLoadStart;
4205
4415
  this.ngModule = injector.get(NgModuleRef);
4206
4416
  this.console = injector.get(ɵConsole);
4207
4417
  const ngZone = injector.get(NgZone);
@@ -4210,7 +4420,6 @@ class Router {
4210
4420
  this.currentUrlTree = createEmptyUrlTree();
4211
4421
  this.rawUrlTree = this.currentUrlTree;
4212
4422
  this.browserUrlTree = this.currentUrlTree;
4213
- this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
4214
4423
  this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4215
4424
  this.transitions = new BehaviorSubject({
4216
4425
  id: 0,
@@ -4408,6 +4617,26 @@ class Router {
4408
4617
  skipLocationChange: !!skipLocationChange,
4409
4618
  replaceUrl: !!replaceUrl,
4410
4619
  });
4620
+ }),
4621
+ // --- LOAD COMPONENTS ---
4622
+ switchTap((t) => {
4623
+ const loadComponents = (route) => {
4624
+ var _a;
4625
+ const loaders = [];
4626
+ if (((_a = route.routeConfig) === null || _a === void 0 ? void 0 : _a.loadComponent) &&
4627
+ !route.routeConfig._loadedComponent) {
4628
+ loaders.push(this.configLoader.loadComponent(route.routeConfig)
4629
+ .pipe(tap(loadedComponent => {
4630
+ route.component = loadedComponent;
4631
+ }), map(() => void 0)));
4632
+ }
4633
+ for (const child of route.children) {
4634
+ loaders.push(...loadComponents(child));
4635
+ }
4636
+ return loaders;
4637
+ };
4638
+ return combineLatest(loadComponents(t.targetSnapshot.root))
4639
+ .pipe(defaultIfEmpty(), take(1));
4411
4640
  }), map((t) => {
4412
4641
  const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4413
4642
  return (Object.assign(Object.assign({}, t), { targetRouterState }));
@@ -4487,23 +4716,17 @@ class Router {
4487
4716
  t.resolve(false);
4488
4717
  }
4489
4718
  else {
4490
- // setTimeout is required so this navigation finishes with
4491
- // the return EMPTY below. If it isn't allowed to finish
4492
- // processing, there can be multiple navigations to the same
4493
- // URL.
4494
- setTimeout(() => {
4495
- const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4496
- const extras = {
4497
- skipLocationChange: t.extras.skipLocationChange,
4498
- // The URL is already updated at this point if we have 'eager' URL
4499
- // updates or if the navigation was triggered by the browser (back
4500
- // button, URL bar, etc). We want to replace that item in history if
4501
- // the navigation is rejected.
4502
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
4503
- isBrowserTriggeredNavigation(t.source)
4504
- };
4505
- this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4506
- }, 0);
4719
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4720
+ const extras = {
4721
+ skipLocationChange: t.extras.skipLocationChange,
4722
+ // The URL is already updated at this point if we have 'eager' URL
4723
+ // updates or if the navigation was triggered by the browser (back
4724
+ // button, URL bar, etc). We want to replace that item in history if
4725
+ // the navigation is rejected.
4726
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
4727
+ isBrowserTriggeredNavigation(t.source)
4728
+ };
4729
+ this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4507
4730
  }
4508
4731
  /* All other errors should reset to the router's internal URL reference to
4509
4732
  * the pre-error state. */
@@ -4614,7 +4837,7 @@ class Router {
4614
4837
  * ```
4615
4838
  */
4616
4839
  resetConfig(config) {
4617
- validateConfig(config);
4840
+ NG_DEV_MODE && validateConfig(config);
4618
4841
  this.config = config.map(standardizeConfig);
4619
4842
  this.navigated = false;
4620
4843
  this.lastSuccessfulId = -1;
@@ -4972,9 +5195,9 @@ class Router {
4972
5195
  return { navigationId };
4973
5196
  }
4974
5197
  }
4975
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
4976
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: Router });
4977
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: Router, decorators: [{
5198
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5199
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router });
5200
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: Router, decorators: [{
4978
5201
  type: Injectable
4979
5202
  }], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
4980
5203
  function validateCommands(commands) {
@@ -5166,9 +5389,9 @@ class RouterLink {
5166
5389
  });
5167
5390
  }
5168
5391
  }
5169
- RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5170
- RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", 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 });
5171
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterLink, decorators: [{
5392
+ RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5393
+ RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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 });
5394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLink, decorators: [{
5172
5395
  type: Directive,
5173
5396
  args: [{ selector: ':not(a):not(area)[routerLink]' }]
5174
5397
  }], ctorParameters: function () {
@@ -5287,9 +5510,9 @@ class RouterLinkWithHref {
5287
5510
  });
5288
5511
  }
5289
5512
  }
5290
- RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5291
- RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", 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 });
5292
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5513
+ RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5514
+ RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", 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 });
5515
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5293
5516
  type: Directive,
5294
5517
  args: [{ selector: 'a[routerLink],area[routerLink]' }]
5295
5518
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
@@ -5386,6 +5609,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
5386
5609
  * </div>
5387
5610
  * ```
5388
5611
  *
5612
+ * The `RouterLinkActive` directive can also be used to set the aria-current attribute
5613
+ * to provide an alternative distinction for active elements to visually impaired users.
5614
+ *
5615
+ * For example, the following code adds the 'active' class to the Home Page link when it is
5616
+ * indeed active and in such case also sets its aria-current attribute to 'page':
5617
+ *
5618
+ * ```
5619
+ * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
5620
+ * ```
5621
+ *
5389
5622
  * @ngModule RouterModule
5390
5623
  *
5391
5624
  * @publicApi
@@ -5481,6 +5714,12 @@ class RouterLinkActive {
5481
5714
  this.renderer.removeClass(this.element.nativeElement, c);
5482
5715
  }
5483
5716
  });
5717
+ if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
5718
+ this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
5719
+ }
5720
+ else {
5721
+ this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
5722
+ }
5484
5723
  // Emit on isActiveChange after classes are updated
5485
5724
  this.isActiveChange.emit(hasActiveLinks);
5486
5725
  }
@@ -5500,9 +5739,9 @@ class RouterLinkActive {
5500
5739
  this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
5501
5740
  }
5502
5741
  }
5503
- RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", 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 });
5504
- RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", 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 });
5505
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterLinkActive, decorators: [{
5742
+ RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", 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 });
5743
+ RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-rc.2", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }, { propertyName: "linksWithHrefs", predicate: RouterLinkWithHref, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
5744
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterLinkActive, decorators: [{
5506
5745
  type: Directive,
5507
5746
  args: [{
5508
5747
  selector: '[routerLinkActive]',
@@ -5522,6 +5761,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9",
5522
5761
  args: [RouterLinkWithHref, { descendants: true }]
5523
5762
  }], routerLinkActiveOptions: [{
5524
5763
  type: Input
5764
+ }], ariaCurrentWhenActive: [{
5765
+ type: Input
5525
5766
  }], isActiveChange: [{
5526
5767
  type: Output
5527
5768
  }], routerLinkActive: [{
@@ -5606,9 +5847,9 @@ class DefaultTitleStrategy extends TitleStrategy {
5606
5847
  }
5607
5848
  }
5608
5849
  }
5609
- DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5610
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5611
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5850
+ DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5851
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5852
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5612
5853
  type: Injectable,
5613
5854
  args: [{ providedIn: 'root' }]
5614
5855
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -5672,13 +5913,11 @@ class NoPreloading {
5672
5913
  * @publicApi
5673
5914
  */
5674
5915
  class RouterPreloader {
5675
- constructor(router, compiler, injector, preloadingStrategy) {
5916
+ constructor(router, compiler, injector, preloadingStrategy, loader) {
5676
5917
  this.router = router;
5677
5918
  this.injector = injector;
5678
5919
  this.preloadingStrategy = preloadingStrategy;
5679
- const onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r));
5680
- const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
5681
- this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
5920
+ this.loader = loader;
5682
5921
  }
5683
5922
  setUpPreloading() {
5684
5923
  this.subscription =
@@ -5687,8 +5926,7 @@ class RouterPreloader {
5687
5926
  .subscribe(() => { });
5688
5927
  }
5689
5928
  preload() {
5690
- const ngModule = this.injector.get(NgModuleRef);
5691
- return this.processRoutes(ngModule, this.router.config);
5929
+ return this.processRoutes(this.injector, this.router.config);
5692
5930
  }
5693
5931
  /** @nodoc */
5694
5932
  ngOnDestroy() {
@@ -5696,41 +5934,61 @@ class RouterPreloader {
5696
5934
  this.subscription.unsubscribe();
5697
5935
  }
5698
5936
  }
5699
- processRoutes(ngModule, routes) {
5937
+ processRoutes(injector, routes) {
5938
+ var _a, _b, _c;
5700
5939
  const res = [];
5701
5940
  for (const route of routes) {
5702
- // we already have the config loaded, just recurse
5703
- if (route.loadChildren && !route.canLoad && route._loadedConfig) {
5704
- const childConfig = route._loadedConfig;
5705
- res.push(this.processRoutes(childConfig.module, childConfig.routes));
5706
- // no config loaded, fetch the config
5941
+ if (route.providers && !route._injector) {
5942
+ route._injector =
5943
+ createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
5707
5944
  }
5708
- else if (route.loadChildren && !route.canLoad) {
5709
- res.push(this.preloadConfig(ngModule, route));
5710
- // recurse into children
5945
+ const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
5946
+ const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
5947
+ if ((route.loadChildren && !route._loadedRoutes) ||
5948
+ (route.loadComponent && !route._loadedComponent)) {
5949
+ res.push(this.preloadConfig(injectorForCurrentRoute, route));
5711
5950
  }
5712
- else if (route.children) {
5713
- res.push(this.processRoutes(ngModule, route.children));
5951
+ else if (route.children || route._loadedRoutes) {
5952
+ res.push(this.processRoutes(injectorForChildren, ((_c = route.children) !== null && _c !== void 0 ? _c : route._loadedRoutes)));
5714
5953
  }
5715
5954
  }
5716
- return from(res).pipe(mergeAll(), map((_) => void 0));
5955
+ return from(res).pipe(mergeAll());
5717
5956
  }
5718
- preloadConfig(ngModule, route) {
5957
+ preloadConfig(injector, route) {
5719
5958
  return this.preloadingStrategy.preload(route, () => {
5720
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
5721
- this.loader.load(ngModule.injector, route);
5722
- return loaded$.pipe(mergeMap((config) => {
5723
- route._loadedConfig = config;
5724
- return this.processRoutes(config.module, config.routes);
5959
+ let loadedChildren$;
5960
+ if (route.loadChildren && route.canLoad === undefined) {
5961
+ loadedChildren$ = this.loader.loadChildren(injector, route);
5962
+ }
5963
+ else {
5964
+ loadedChildren$ = of(null);
5965
+ }
5966
+ const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
5967
+ var _a;
5968
+ if (config === null) {
5969
+ return of(void 0);
5970
+ }
5971
+ route._loadedRoutes = config.routes;
5972
+ route._loadedInjector = config.injector;
5973
+ // If the loaded config was a module, use that as the module/module injector going
5974
+ // forward. Otherwise, continue using the current module/module injector.
5975
+ return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
5725
5976
  }));
5977
+ if (route.loadComponent && !route._loadedComponent) {
5978
+ const loadComponent$ = this.loader.loadComponent(route);
5979
+ return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
5980
+ }
5981
+ else {
5982
+ return recursiveLoadChildren$;
5983
+ }
5726
5984
  });
5727
5985
  }
5728
5986
  }
5729
- RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.Injector }, { token: PreloadingStrategy }], target: i0.ɵɵFactoryTarget.Injectable });
5730
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterPreloader });
5731
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterPreloader, decorators: [{
5987
+ RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
5988
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader });
5989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterPreloader, decorators: [{
5732
5990
  type: Injectable
5733
- }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.Injector }, { type: PreloadingStrategy }]; } });
5991
+ }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
5734
5992
 
5735
5993
  class RouterScroller {
5736
5994
  constructor(router,
@@ -5807,9 +6065,9 @@ class RouterScroller {
5807
6065
  }
5808
6066
  }
5809
6067
  }
5810
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5811
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterScroller });
5812
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterScroller, decorators: [{
6068
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6069
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller });
6070
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterScroller, decorators: [{
5813
6071
  type: Injectable
5814
6072
  }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
5815
6073
 
@@ -5852,6 +6110,7 @@ const ROUTER_PROVIDERS = [
5852
6110
  NoPreloading,
5853
6111
  PreloadAllModules,
5854
6112
  { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
6113
+ RouterConfigLoader,
5855
6114
  ];
5856
6115
  function routerNgProbeToken() {
5857
6116
  return new NgProbeToken('Router', Router);
@@ -5950,10 +6209,10 @@ class RouterModule {
5950
6209
  return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
5951
6210
  }
5952
6211
  }
5953
- RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
5954
- RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
5955
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterModule });
5956
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterModule, decorators: [{
6212
+ RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6213
+ RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
6214
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule });
6215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterModule, decorators: [{
5957
6216
  type: NgModule,
5958
6217
  args: [{
5959
6218
  declarations: ROUTER_DIRECTIVES,
@@ -6017,12 +6276,12 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
6017
6276
  }
6018
6277
  router.titleStrategy = titleStrategy !== null && titleStrategy !== void 0 ? titleStrategy : defaultTitleStrategy;
6019
6278
  assignExtraOptionsToRouter(opts, router);
6020
- if (opts.enableTracing) {
6279
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
6021
6280
  router.events.subscribe((e) => {
6022
6281
  var _a, _b;
6023
6282
  // tslint:disable:no-console
6024
6283
  (_a = console.group) === null || _a === void 0 ? void 0 : _a.call(console, `Router Event: ${e.constructor.name}`);
6025
- console.log(e.toString());
6284
+ console.log(stringifyEvent(e));
6026
6285
  console.log(e);
6027
6286
  (_b = console.groupEnd) === null || _b === void 0 ? void 0 : _b.call(console);
6028
6287
  // tslint:enable:no-console
@@ -6089,9 +6348,7 @@ class RouterInitializer {
6089
6348
  router.setUpLocationChangeListener();
6090
6349
  resolve(true);
6091
6350
  }
6092
- else if (
6093
- // TODO: enabled is deprecated as of v11, can be removed in v13
6094
- opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
6351
+ else if (opts.initialNavigation === 'enabledBlocking') {
6095
6352
  router.hooks.afterPreactivation = () => {
6096
6353
  // only the initial navigation should be delayed
6097
6354
  if (!this.initNavigation) {
@@ -6135,9 +6392,9 @@ class RouterInitializer {
6135
6392
  this.destroyed = true;
6136
6393
  }
6137
6394
  }
6138
- RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6139
- RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterInitializer });
6140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: RouterInitializer, decorators: [{
6395
+ RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6396
+ RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer });
6397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-rc.2", ngImport: i0, type: RouterInitializer, decorators: [{
6141
6398
  type: Injectable
6142
6399
  }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
6143
6400
  function getAppInitializer(r) {
@@ -6177,7 +6434,7 @@ function provideRouterInitializer() {
6177
6434
  /**
6178
6435
  * @publicApi
6179
6436
  */
6180
- const VERSION = new Version('14.0.0-next.9');
6437
+ const VERSION = new Version('14.0.0-rc.2');
6181
6438
 
6182
6439
  /**
6183
6440
  * @license