@angular/router 14.0.0-next.13 → 14.0.0-next.16

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 (38) hide show
  1. package/esm2020/src/apply_redirects.mjs +57 -47
  2. package/esm2020/src/components/empty_outlet.mjs +3 -3
  3. package/esm2020/src/directives/router_link.mjs +6 -6
  4. package/esm2020/src/directives/router_link_active.mjs +22 -4
  5. package/esm2020/src/directives/router_outlet.mjs +25 -16
  6. package/esm2020/src/events.mjs +57 -1
  7. package/esm2020/src/index.mjs +1 -1
  8. package/esm2020/src/models.mjs +2 -7
  9. package/esm2020/src/operators/activate_routes.mjs +7 -14
  10. package/esm2020/src/operators/apply_redirects.mjs +3 -3
  11. package/esm2020/src/operators/resolve_data.mjs +5 -12
  12. package/esm2020/src/page_title_strategy.mjs +3 -3
  13. package/esm2020/src/recognize.mjs +4 -4
  14. package/esm2020/src/router.mjs +41 -25
  15. package/esm2020/src/router_config_loader.mjs +74 -27
  16. package/esm2020/src/router_module.mjs +14 -14
  17. package/esm2020/src/router_outlet_context.mjs +6 -1
  18. package/esm2020/src/router_preloader.mjs +48 -32
  19. package/esm2020/src/router_scroller.mjs +3 -3
  20. package/esm2020/src/router_state.mjs +1 -2
  21. package/esm2020/src/utils/config.mjs +71 -11
  22. package/esm2020/src/utils/preactivation.mjs +5 -14
  23. package/esm2020/src/version.mjs +1 -1
  24. package/esm2020/testing/src/router_testing_module.mjs +4 -4
  25. package/fesm2015/router.mjs +855 -651
  26. package/fesm2015/router.mjs.map +1 -1
  27. package/fesm2015/testing.mjs +5 -5
  28. package/fesm2015/upgrade.mjs +1 -1
  29. package/fesm2020/router.mjs +845 -651
  30. package/fesm2020/router.mjs.map +1 -1
  31. package/fesm2020/testing.mjs +5 -5
  32. package/fesm2020/upgrade.mjs +1 -1
  33. package/{router.d.ts → index.d.ts} +3858 -3734
  34. package/package.json +8 -8
  35. package/testing/{testing.d.ts → index.d.ts} +65 -64
  36. package/upgrade/{upgrade.d.ts → index.d.ts} +51 -50
  37. package/testing/package.json +0 -9
  38. package/upgrade/package.json +0 -10
@@ -1,13 +1,13 @@
1
1
  /**
2
- * @license Angular v14.0.0-next.13
2
+ * @license Angular v14.0.0-next.16
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, ɵisStandalone, ComponentFactoryResolver, createEnvironmentInjector, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
9
9
  import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
10
- import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, refCount, finalize, mergeAll } from 'rxjs/operators';
10
+ import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, mapTo, finalize, refCount, 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;
@@ -2023,181 +2079,76 @@ function compare(path, params, segment) {
2023
2079
  * Use of this source code is governed by an MIT-style license that can be
2024
2080
  * found in the LICENSE file at https://angular.io/license
2025
2081
  */
2026
- const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2027
- new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2028
- .activate(rootContexts);
2029
- return t;
2030
- });
2031
- class ActivateRoutes {
2032
- constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2033
- this.routeReuseStrategy = routeReuseStrategy;
2034
- this.futureState = futureState;
2035
- this.currState = currState;
2036
- this.forwardEvent = forwardEvent;
2037
- }
2038
- activate(parentContexts) {
2039
- const futureRoot = this.futureState._root;
2040
- const currRoot = this.currState ? this.currState._root : null;
2041
- this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2042
- advanceActivatedRoute(this.futureState.root);
2043
- this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2044
- }
2045
- // De-activate the child route that are not re-used for the future state
2046
- deactivateChildRoutes(futureNode, currNode, contexts) {
2047
- const children = nodeChildrenAsMap(currNode);
2048
- // Recurse on the routes active in the future state to de-activate deeper children
2049
- futureNode.children.forEach(futureChild => {
2050
- const childOutletName = futureChild.value.outlet;
2051
- this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2052
- delete children[childOutletName];
2053
- });
2054
- // De-activate the routes that will not be re-used
2055
- forEach(children, (v, childName) => {
2056
- this.deactivateRouteAndItsChildren(v, contexts);
2057
- });
2058
- }
2059
- deactivateRoutes(futureNode, currNode, parentContext) {
2060
- const future = futureNode.value;
2061
- const curr = currNode ? currNode.value : null;
2062
- if (future === curr) {
2063
- // Reusing the node, check to see if the children need to be de-activated
2064
- if (future.component) {
2065
- // If we have a normal route, we need to go through an outlet.
2066
- const context = parentContext.getContext(future.outlet);
2067
- if (context) {
2068
- this.deactivateChildRoutes(futureNode, currNode, context.children);
2069
- }
2070
- }
2071
- else {
2072
- // if we have a componentless route, we recurse but keep the same outlet map.
2073
- this.deactivateChildRoutes(futureNode, currNode, parentContext);
2074
- }
2075
- }
2076
- else {
2077
- if (curr) {
2078
- // Deactivate the current route which will not be re-used
2079
- this.deactivateRouteAndItsChildren(currNode, parentContext);
2080
- }
2081
- }
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;
2082
2099
  }
2083
- deactivateRouteAndItsChildren(route, parentContexts) {
2084
- // If there is no component, the Route is never attached to an outlet (because there is no
2085
- // component to attach).
2086
- if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2087
- this.detachAndStoreRouteSubtree(route, parentContexts);
2088
- }
2089
- else {
2090
- this.deactivateRouteAndOutlet(route, parentContexts);
2091
- }
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();
2092
2110
  }
2093
- detachAndStoreRouteSubtree(route, parentContexts) {
2094
- const context = parentContexts.getContext(route.value.outlet);
2095
- const contexts = context && route.value.component ? context.children : parentContexts;
2096
- const children = nodeChildrenAsMap(route);
2097
- for (const childOutlet of Object.keys(children)) {
2098
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2099
- }
2100
- if (context && context.outlet) {
2101
- const componentRef = context.outlet.detach();
2102
- const contexts = context.children.onOutletDeactivated();
2103
- this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2104
- }
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);
2105
2116
  }
2106
- deactivateRouteAndOutlet(route, parentContexts) {
2107
- const context = parentContexts.getContext(route.value.outlet);
2108
- // The context could be `null` if we are on a componentless route but there may still be
2109
- // children that need deactivating.
2110
- const contexts = context && route.value.component ? context.children : parentContexts;
2111
- const children = nodeChildrenAsMap(route);
2112
- for (const childOutlet of Object.keys(children)) {
2113
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2114
- }
2115
- if (context && context.outlet) {
2116
- // Destroy the component
2117
- context.outlet.deactivate();
2118
- // Destroy the contexts for all the outlets that were in the component
2119
- context.children.onOutletDeactivated();
2120
- // Clear the information about the attached component on the context but keep the reference to
2121
- // 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;
2122
2126
  context.attachRef = null;
2123
- context.resolver = null;
2124
- context.route = null;
2125
2127
  }
2126
2128
  }
2127
- activateChildRoutes(futureNode, currNode, contexts) {
2128
- const children = nodeChildrenAsMap(currNode);
2129
- futureNode.children.forEach(c => {
2130
- this.activateRoutes(c, children[c.value.outlet], contexts);
2131
- this.forwardEvent(new ActivationEnd(c.value.snapshot));
2132
- });
2133
- if (futureNode.children.length) {
2134
- this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2135
- }
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;
2136
2137
  }
2137
- activateRoutes(futureNode, currNode, parentContexts) {
2138
- const future = futureNode.value;
2139
- const curr = currNode ? currNode.value : null;
2140
- advanceActivatedRoute(future);
2141
- // reusing the node
2142
- if (future === curr) {
2143
- if (future.component) {
2144
- // If we have a normal route, we need to go through an outlet.
2145
- const context = parentContexts.getOrCreateContext(future.outlet);
2146
- this.activateChildRoutes(futureNode, currNode, context.children);
2147
- }
2148
- else {
2149
- // if we have a componentless route, we recurse but keep the same outlet map.
2150
- this.activateChildRoutes(futureNode, currNode, parentContexts);
2151
- }
2152
- }
2153
- else {
2154
- if (future.component) {
2155
- // if we have a normal route, we need to place the component into the outlet and recurse.
2156
- const context = parentContexts.getOrCreateContext(future.outlet);
2157
- if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2158
- const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2159
- this.routeReuseStrategy.store(future.snapshot, null);
2160
- context.children.onOutletReAttached(stored.contexts);
2161
- context.attachRef = stored.componentRef;
2162
- context.route = stored.route.value;
2163
- if (context.outlet) {
2164
- // Attach right away when the outlet has already been instantiated
2165
- // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2166
- context.outlet.attach(stored.componentRef, stored.route.value);
2167
- }
2168
- advanceActivatedRoute(stored.route.value);
2169
- this.activateChildRoutes(futureNode, null, context.children);
2170
- }
2171
- else {
2172
- const config = parentLoadedConfig(future.snapshot);
2173
- const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
2174
- context.attachRef = null;
2175
- context.route = future;
2176
- context.resolver = cmpFactoryResolver;
2177
- if (context.outlet) {
2178
- // Activate the outlet when it has already been instantiated
2179
- // Otherwise it will get activated from its `ngOnInit` when instantiated
2180
- context.outlet.activateWith(future, cmpFactoryResolver);
2181
- }
2182
- this.activateChildRoutes(futureNode, null, context.children);
2183
- }
2184
- }
2185
- else {
2186
- // if we have a componentless route, we recurse but keep the same outlet map.
2187
- this.activateChildRoutes(futureNode, null, parentContexts);
2188
- }
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);
2189
2146
  }
2147
+ return context;
2190
2148
  }
2191
- }
2192
- function parentLoadedConfig(snapshot) {
2193
- for (let s = snapshot.parent; s; s = s.parent) {
2194
- const route = s.routeConfig;
2195
- if (route && route._loadedConfig)
2196
- return route._loadedConfig;
2197
- if (route && route.component)
2198
- return null;
2149
+ getContext(childName) {
2150
+ return this.contexts.get(childName) || null;
2199
2151
  }
2200
- return null;
2201
2152
  }
2202
2153
 
2203
2154
  /**
@@ -2207,182 +2158,13 @@ function parentLoadedConfig(snapshot) {
2207
2158
  * Use of this source code is governed by an MIT-style license that can be
2208
2159
  * found in the LICENSE file at https://angular.io/license
2209
2160
  */
2210
- class LoadedRouterConfig {
2211
- constructor(routes, module) {
2212
- this.routes = routes;
2213
- this.module = module;
2214
- }
2215
- }
2216
-
2217
2161
  /**
2218
- * @license
2219
- * Copyright Google LLC All Rights Reserved.
2162
+ * @description
2220
2163
  *
2221
- * Use of this source code is governed by an MIT-style license that can be
2222
- * found in the LICENSE file at https://angular.io/license
2223
- */
2224
- /**
2225
- * 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.
2226
2165
  *
2227
- * function product(a: number, b: number) {
2228
- * return a * b;
2229
- * }
2230
- *
2231
- * if (isFunction<product>(fn)) {
2232
- * return fn(1, 2);
2233
- * } else {
2234
- * throw "Must provide the `product` function";
2235
- * }
2236
- */
2237
- function isFunction(v) {
2238
- return typeof v === 'function';
2239
- }
2240
- function isBoolean(v) {
2241
- return typeof v === 'boolean';
2242
- }
2243
- function isUrlTree(v) {
2244
- return v instanceof UrlTree;
2245
- }
2246
- function isCanLoad(guard) {
2247
- return guard && isFunction(guard.canLoad);
2248
- }
2249
- function isCanActivate(guard) {
2250
- return guard && isFunction(guard.canActivate);
2251
- }
2252
- function isCanActivateChild(guard) {
2253
- return guard && isFunction(guard.canActivateChild);
2254
- }
2255
- function isCanDeactivate(guard) {
2256
- return guard && isFunction(guard.canDeactivate);
2257
- }
2258
-
2259
- /**
2260
- * @license
2261
- * Copyright Google LLC All Rights Reserved.
2262
- *
2263
- * Use of this source code is governed by an MIT-style license that can be
2264
- * found in the LICENSE file at https://angular.io/license
2265
- */
2266
- const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2267
- function prioritizedGuardValue() {
2268
- return switchMap(obs => {
2269
- return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2270
- .pipe(scan((acc, list) => {
2271
- let isPending = false;
2272
- return list.reduce((innerAcc, val, i) => {
2273
- if (innerAcc !== INITIAL_VALUE)
2274
- return innerAcc;
2275
- // Toggle pending flag if any values haven't been set yet
2276
- if (val === INITIAL_VALUE)
2277
- isPending = true;
2278
- // Any other return values are only valid if we haven't yet hit a pending
2279
- // call. This guarantees that in the case of a guard at the bottom of the
2280
- // tree that returns a redirect, we will wait for the higher priority
2281
- // guard at the top to finish before performing the redirect.
2282
- if (!isPending) {
2283
- // Early return when we hit a `false` value as that should always
2284
- // cancel navigation
2285
- if (val === false)
2286
- return val;
2287
- if (i === list.length - 1 || isUrlTree(val)) {
2288
- return val;
2289
- }
2290
- }
2291
- return innerAcc;
2292
- }, acc);
2293
- }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2294
- take(1));
2295
- });
2296
- }
2297
-
2298
- /**
2299
- * @license
2300
- * Copyright Google LLC All Rights Reserved.
2301
- *
2302
- * Use of this source code is governed by an MIT-style license that can be
2303
- * found in the LICENSE file at https://angular.io/license
2304
- */
2305
- /**
2306
- * Store contextual information about a `RouterOutlet`
2307
- *
2308
- * @publicApi
2309
- */
2310
- class OutletContext {
2311
- constructor() {
2312
- this.outlet = null;
2313
- this.route = null;
2314
- this.resolver = null;
2315
- this.children = new ChildrenOutletContexts();
2316
- this.attachRef = null;
2317
- }
2318
- }
2319
- /**
2320
- * Store contextual information about the children (= nested) `RouterOutlet`
2321
- *
2322
- * @publicApi
2323
- */
2324
- class ChildrenOutletContexts {
2325
- constructor() {
2326
- // contexts for child outlets, by name.
2327
- this.contexts = new Map();
2328
- }
2329
- /** Called when a `RouterOutlet` directive is instantiated */
2330
- onChildOutletCreated(childName, outlet) {
2331
- const context = this.getOrCreateContext(childName);
2332
- context.outlet = outlet;
2333
- this.contexts.set(childName, context);
2334
- }
2335
- /**
2336
- * Called when a `RouterOutlet` directive is destroyed.
2337
- * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2338
- * re-created later.
2339
- */
2340
- onChildOutletDestroyed(childName) {
2341
- const context = this.getContext(childName);
2342
- if (context) {
2343
- context.outlet = null;
2344
- context.attachRef = null;
2345
- }
2346
- }
2347
- /**
2348
- * Called when the corresponding route is deactivated during navigation.
2349
- * Because the component get destroyed, all children outlet are destroyed.
2350
- */
2351
- onOutletDeactivated() {
2352
- const contexts = this.contexts;
2353
- this.contexts = new Map();
2354
- return contexts;
2355
- }
2356
- onOutletReAttached(contexts) {
2357
- this.contexts = contexts;
2358
- }
2359
- getOrCreateContext(childName) {
2360
- let context = this.getContext(childName);
2361
- if (!context) {
2362
- context = new OutletContext();
2363
- this.contexts.set(childName, context);
2364
- }
2365
- return context;
2366
- }
2367
- getContext(childName) {
2368
- return this.contexts.get(childName) || null;
2369
- }
2370
- }
2371
-
2372
- /**
2373
- * @license
2374
- * Copyright Google LLC All Rights Reserved.
2375
- *
2376
- * Use of this source code is governed by an MIT-style license that can be
2377
- * found in the LICENSE file at https://angular.io/license
2378
- */
2379
- /**
2380
- * @description
2381
- *
2382
- * Acts as a placeholder that Angular dynamically fills based on the current router state.
2383
- *
2384
- * Each outlet can have a unique name, determined by the optional `name` attribute.
2385
- * 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".
2386
2168
  *
2387
2169
  * ```
2388
2170
  * <router-outlet></router-outlet>
@@ -2428,11 +2210,11 @@ class ChildrenOutletContexts {
2428
2210
  * @publicApi
2429
2211
  */
2430
2212
  class RouterOutlet {
2431
- constructor(parentContexts, location, resolver, name, changeDetector) {
2213
+ constructor(parentContexts, location, name, changeDetector, environmentInjector) {
2432
2214
  this.parentContexts = parentContexts;
2433
2215
  this.location = location;
2434
- this.resolver = resolver;
2435
2216
  this.changeDetector = changeDetector;
2217
+ this.environmentInjector = environmentInjector;
2436
2218
  this.activated = null;
2437
2219
  this._activatedRoute = null;
2438
2220
  this.activateEvents = new EventEmitter();
@@ -2467,7 +2249,7 @@ class RouterOutlet {
2467
2249
  }
2468
2250
  else {
2469
2251
  // otherwise the component defined in the configuration is created
2470
- this.activateWith(context.route, context.resolver || null);
2252
+ this.activateWith(context.route, context.injector);
2471
2253
  }
2472
2254
  }
2473
2255
  }
@@ -2526,34 +2308,40 @@ class RouterOutlet {
2526
2308
  this.deactivateEvents.emit(c);
2527
2309
  }
2528
2310
  }
2529
- activateWith(activatedRoute, resolver) {
2311
+ activateWith(activatedRoute, resolverOrInjector) {
2530
2312
  if (this.isActivated) {
2531
2313
  throw new Error('Cannot activate an already activated outlet');
2532
2314
  }
2533
2315
  this._activatedRoute = activatedRoute;
2316
+ const location = this.location;
2534
2317
  const snapshot = activatedRoute._futureSnapshot;
2535
- const component = snapshot.routeConfig.component;
2536
- resolver = resolver || this.resolver;
2537
- const factory = resolver.resolveComponentFactory(component);
2318
+ const component = snapshot.component;
2538
2319
  const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
2539
- const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
2540
- 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
+ }
2541
2329
  // Calling `markForCheck` to make sure we will run the change detection when the
2542
2330
  // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
2543
2331
  this.changeDetector.markForCheck();
2544
2332
  this.activateEvents.emit(this.activated.instance);
2545
2333
  }
2546
2334
  }
2547
- RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
2548
- RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.13", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2549
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterOutlet, decorators: [{
2335
+ RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", 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-next.16", 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-next.16", ngImport: i0, type: RouterOutlet, decorators: [{
2550
2338
  type: Directive,
2551
2339
  args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
2552
2340
  }], ctorParameters: function () {
2553
- return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: undefined, decorators: [{
2341
+ return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
2554
2342
  type: Attribute,
2555
2343
  args: ['name']
2556
- }] }, { type: i0.ChangeDetectorRef }];
2344
+ }] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }];
2557
2345
  }, propDecorators: { activateEvents: [{
2558
2346
  type: Output,
2559
2347
  args: ['activate']
@@ -2577,10 +2365,390 @@ class OutletInjector {
2577
2365
  if (token === ActivatedRoute) {
2578
2366
  return this.route;
2579
2367
  }
2580
- if (token === ChildrenOutletContexts) {
2581
- return this.childContexts;
2368
+ if (token === ChildrenOutletContexts) {
2369
+ return this.childContexts;
2370
+ }
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-next.16", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2397
+ ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0-next.16", 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-next.16", 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
+ function getLoadedRoutes(route) {
2411
+ return route._loadedRoutes;
2412
+ }
2413
+ function getLoadedInjector(route) {
2414
+ return route._loadedInjector;
2415
+ }
2416
+ function getLoadedComponent(route) {
2417
+ return route._loadedComponent;
2418
+ }
2419
+ function getProvidersInjector(route) {
2420
+ return route._injector;
2421
+ }
2422
+ function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
2423
+ // forEach doesn't iterate undefined values
2424
+ for (let i = 0; i < config.length; i++) {
2425
+ const route = config[i];
2426
+ const fullPath = getFullPath(parentPath, route);
2427
+ validateNode(route, fullPath, requireStandaloneComponents);
2428
+ }
2429
+ }
2430
+ function assertStandalone(fullPath, component) {
2431
+ if (component && !ɵisStandalone(component)) {
2432
+ throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
2433
+ }
2434
+ }
2435
+ function validateNode(route, fullPath, requireStandaloneComponents) {
2436
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
2437
+ if (!route) {
2438
+ throw new Error(`
2439
+ Invalid configuration of route '${fullPath}': Encountered undefined route.
2440
+ The reason might be an extra comma.
2441
+
2442
+ Example:
2443
+ const routes: Routes = [
2444
+ { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2445
+ { path: 'dashboard', component: DashboardComponent },, << two commas
2446
+ { path: 'detail/:id', component: HeroDetailComponent }
2447
+ ];
2448
+ `);
2449
+ }
2450
+ if (Array.isArray(route)) {
2451
+ throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2452
+ }
2453
+ if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
2454
+ (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2455
+ throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2456
+ }
2457
+ if (route.redirectTo && route.children) {
2458
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2459
+ }
2460
+ if (route.redirectTo && route.loadChildren) {
2461
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2462
+ }
2463
+ if (route.children && route.loadChildren) {
2464
+ throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2465
+ }
2466
+ if (route.redirectTo && (route.component || route.loadComponent)) {
2467
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
2468
+ }
2469
+ if (route.component && route.loadComponent) {
2470
+ throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
2471
+ }
2472
+ if (route.redirectTo && route.canActivate) {
2473
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2474
+ `so canActivate will never be executed.`);
2475
+ }
2476
+ if (route.path && route.matcher) {
2477
+ throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2478
+ }
2479
+ if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
2480
+ !route.children && !route.loadChildren) {
2481
+ throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
2482
+ }
2483
+ if (route.path === void 0 && route.matcher === void 0) {
2484
+ throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2485
+ }
2486
+ if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2487
+ throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2488
+ }
2489
+ if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2490
+ const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2491
+ throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2492
+ }
2493
+ if (requireStandaloneComponents) {
2494
+ assertStandalone(fullPath, route.component);
2495
+ }
2496
+ }
2497
+ if (route.children) {
2498
+ validateConfig(route.children, fullPath, requireStandaloneComponents);
2499
+ }
2500
+ }
2501
+ function getFullPath(parentPath, currentRoute) {
2502
+ if (!currentRoute) {
2503
+ return parentPath;
2504
+ }
2505
+ if (!parentPath && !currentRoute.path) {
2506
+ return '';
2507
+ }
2508
+ else if (parentPath && !currentRoute.path) {
2509
+ return `${parentPath}/`;
2510
+ }
2511
+ else if (!parentPath && currentRoute.path) {
2512
+ return currentRoute.path;
2513
+ }
2514
+ else {
2515
+ return `${parentPath}/${currentRoute.path}`;
2516
+ }
2517
+ }
2518
+ /**
2519
+ * Makes a copy of the config and adds any default required properties.
2520
+ */
2521
+ function standardizeConfig(r) {
2522
+ const children = r.children && r.children.map(standardizeConfig);
2523
+ const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2524
+ if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
2525
+ (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2526
+ c.component = ɵEmptyOutletComponent;
2527
+ }
2528
+ return c;
2529
+ }
2530
+ /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2531
+ function getOutlet(route) {
2532
+ return route.outlet || PRIMARY_OUTLET;
2533
+ }
2534
+ /**
2535
+ * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2536
+ * The order of the configs is otherwise preserved.
2537
+ */
2538
+ function sortByMatchingOutlets(routes, outletName) {
2539
+ const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2540
+ sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2541
+ return sortedConfig;
2542
+ }
2543
+ /**
2544
+ * Gets the first injector in the snapshot's parent tree.
2545
+ *
2546
+ * If the `Route` has a static list of providers, the returned injector will be the one created from
2547
+ * those. If it does not exist, the returned injector may come from the parents, which may be from a
2548
+ * loaded config or their static providers.
2549
+ *
2550
+ * Returns `null` if there is neither this nor any parents have a stored injector.
2551
+ *
2552
+ * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
2553
+ * also used for getting the correct injector to use for creating components.
2554
+ */
2555
+ function getClosestRouteInjector(snapshot) {
2556
+ var _a;
2557
+ if (!snapshot)
2558
+ return null;
2559
+ // If the current route has its own injector, which is created from the static providers on the
2560
+ // route itself, we should use that. Otherwise, we start at the parent since we do not want to
2561
+ // include the lazy loaded injector from this route.
2562
+ if ((_a = snapshot.routeConfig) === null || _a === void 0 ? void 0 : _a._injector) {
2563
+ return snapshot.routeConfig._injector;
2564
+ }
2565
+ for (let s = snapshot.parent; s; s = s.parent) {
2566
+ const route = s.routeConfig;
2567
+ // Note that the order here is important. `_loadedInjector` stored on the route with
2568
+ // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
2569
+ // is created from the static providers on that parent route, so it applies to the children as
2570
+ // well, but only if there is no lazy loaded NgModuleRef injector.
2571
+ if (route === null || route === void 0 ? void 0 : route._loadedInjector)
2572
+ return route._loadedInjector;
2573
+ if (route === null || route === void 0 ? void 0 : route._injector)
2574
+ return route._injector;
2575
+ }
2576
+ return null;
2577
+ }
2578
+
2579
+ /**
2580
+ * @license
2581
+ * Copyright Google LLC All Rights Reserved.
2582
+ *
2583
+ * Use of this source code is governed by an MIT-style license that can be
2584
+ * found in the LICENSE file at https://angular.io/license
2585
+ */
2586
+ const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2587
+ new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2588
+ .activate(rootContexts);
2589
+ return t;
2590
+ });
2591
+ class ActivateRoutes {
2592
+ constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2593
+ this.routeReuseStrategy = routeReuseStrategy;
2594
+ this.futureState = futureState;
2595
+ this.currState = currState;
2596
+ this.forwardEvent = forwardEvent;
2597
+ }
2598
+ activate(parentContexts) {
2599
+ const futureRoot = this.futureState._root;
2600
+ const currRoot = this.currState ? this.currState._root : null;
2601
+ this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2602
+ advanceActivatedRoute(this.futureState.root);
2603
+ this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2604
+ }
2605
+ // De-activate the child route that are not re-used for the future state
2606
+ deactivateChildRoutes(futureNode, currNode, contexts) {
2607
+ const children = nodeChildrenAsMap(currNode);
2608
+ // Recurse on the routes active in the future state to de-activate deeper children
2609
+ futureNode.children.forEach(futureChild => {
2610
+ const childOutletName = futureChild.value.outlet;
2611
+ this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2612
+ delete children[childOutletName];
2613
+ });
2614
+ // De-activate the routes that will not be re-used
2615
+ forEach(children, (v, childName) => {
2616
+ this.deactivateRouteAndItsChildren(v, contexts);
2617
+ });
2618
+ }
2619
+ deactivateRoutes(futureNode, currNode, parentContext) {
2620
+ const future = futureNode.value;
2621
+ const curr = currNode ? currNode.value : null;
2622
+ if (future === curr) {
2623
+ // Reusing the node, check to see if the children need to be de-activated
2624
+ if (future.component) {
2625
+ // If we have a normal route, we need to go through an outlet.
2626
+ const context = parentContext.getContext(future.outlet);
2627
+ if (context) {
2628
+ this.deactivateChildRoutes(futureNode, currNode, context.children);
2629
+ }
2630
+ }
2631
+ else {
2632
+ // if we have a componentless route, we recurse but keep the same outlet map.
2633
+ this.deactivateChildRoutes(futureNode, currNode, parentContext);
2634
+ }
2635
+ }
2636
+ else {
2637
+ if (curr) {
2638
+ // Deactivate the current route which will not be re-used
2639
+ this.deactivateRouteAndItsChildren(currNode, parentContext);
2640
+ }
2641
+ }
2642
+ }
2643
+ deactivateRouteAndItsChildren(route, parentContexts) {
2644
+ // If there is no component, the Route is never attached to an outlet (because there is no
2645
+ // component to attach).
2646
+ if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2647
+ this.detachAndStoreRouteSubtree(route, parentContexts);
2648
+ }
2649
+ else {
2650
+ this.deactivateRouteAndOutlet(route, parentContexts);
2651
+ }
2652
+ }
2653
+ detachAndStoreRouteSubtree(route, parentContexts) {
2654
+ const context = parentContexts.getContext(route.value.outlet);
2655
+ const contexts = context && route.value.component ? context.children : parentContexts;
2656
+ const children = nodeChildrenAsMap(route);
2657
+ for (const childOutlet of Object.keys(children)) {
2658
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2659
+ }
2660
+ if (context && context.outlet) {
2661
+ const componentRef = context.outlet.detach();
2662
+ const contexts = context.children.onOutletDeactivated();
2663
+ this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2664
+ }
2665
+ }
2666
+ deactivateRouteAndOutlet(route, parentContexts) {
2667
+ const context = parentContexts.getContext(route.value.outlet);
2668
+ // The context could be `null` if we are on a componentless route but there may still be
2669
+ // children that need deactivating.
2670
+ const contexts = context && route.value.component ? context.children : parentContexts;
2671
+ const children = nodeChildrenAsMap(route);
2672
+ for (const childOutlet of Object.keys(children)) {
2673
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2674
+ }
2675
+ if (context && context.outlet) {
2676
+ // Destroy the component
2677
+ context.outlet.deactivate();
2678
+ // Destroy the contexts for all the outlets that were in the component
2679
+ context.children.onOutletDeactivated();
2680
+ // Clear the information about the attached component on the context but keep the reference to
2681
+ // the outlet.
2682
+ context.attachRef = null;
2683
+ context.resolver = null;
2684
+ context.route = null;
2685
+ }
2686
+ }
2687
+ activateChildRoutes(futureNode, currNode, contexts) {
2688
+ const children = nodeChildrenAsMap(currNode);
2689
+ futureNode.children.forEach(c => {
2690
+ this.activateRoutes(c, children[c.value.outlet], contexts);
2691
+ this.forwardEvent(new ActivationEnd(c.value.snapshot));
2692
+ });
2693
+ if (futureNode.children.length) {
2694
+ this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2695
+ }
2696
+ }
2697
+ activateRoutes(futureNode, currNode, parentContexts) {
2698
+ var _a;
2699
+ const future = futureNode.value;
2700
+ const curr = currNode ? currNode.value : null;
2701
+ advanceActivatedRoute(future);
2702
+ // reusing the node
2703
+ if (future === curr) {
2704
+ if (future.component) {
2705
+ // If we have a normal route, we need to go through an outlet.
2706
+ const context = parentContexts.getOrCreateContext(future.outlet);
2707
+ this.activateChildRoutes(futureNode, currNode, context.children);
2708
+ }
2709
+ else {
2710
+ // if we have a componentless route, we recurse but keep the same outlet map.
2711
+ this.activateChildRoutes(futureNode, currNode, parentContexts);
2712
+ }
2713
+ }
2714
+ else {
2715
+ if (future.component) {
2716
+ // if we have a normal route, we need to place the component into the outlet and recurse.
2717
+ const context = parentContexts.getOrCreateContext(future.outlet);
2718
+ if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2719
+ const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2720
+ this.routeReuseStrategy.store(future.snapshot, null);
2721
+ context.children.onOutletReAttached(stored.contexts);
2722
+ context.attachRef = stored.componentRef;
2723
+ context.route = stored.route.value;
2724
+ if (context.outlet) {
2725
+ // Attach right away when the outlet has already been instantiated
2726
+ // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2727
+ context.outlet.attach(stored.componentRef, stored.route.value);
2728
+ }
2729
+ advanceActivatedRoute(stored.route.value);
2730
+ this.activateChildRoutes(futureNode, null, context.children);
2731
+ }
2732
+ else {
2733
+ const injector = getClosestRouteInjector(future.snapshot);
2734
+ const cmpFactoryResolver = (_a = injector === null || injector === void 0 ? void 0 : injector.get(ComponentFactoryResolver)) !== null && _a !== void 0 ? _a : null;
2735
+ context.attachRef = null;
2736
+ context.route = future;
2737
+ context.resolver = cmpFactoryResolver;
2738
+ context.injector = injector;
2739
+ if (context.outlet) {
2740
+ // Activate the outlet when it has already been instantiated
2741
+ // Otherwise it will get activated from its `ngOnInit` when instantiated
2742
+ context.outlet.activateWith(future, context.injector);
2743
+ }
2744
+ this.activateChildRoutes(futureNode, null, context.children);
2745
+ }
2746
+ }
2747
+ else {
2748
+ // if we have a componentless route, we recurse but keep the same outlet map.
2749
+ this.activateChildRoutes(futureNode, null, parentContexts);
2750
+ }
2582
2751
  }
2583
- return this.parent.get(token, notFoundValue);
2584
2752
  }
2585
2753
  }
2586
2754
 
@@ -2592,22 +2760,39 @@ class OutletInjector {
2592
2760
  * found in the LICENSE file at https://angular.io/license
2593
2761
  */
2594
2762
  /**
2595
- * This component is used internally within the router to be a placeholder when an empty
2596
- * router-outlet is needed. For example, with a config such as:
2763
+ * Simple function check, but generic so type inference will flow. Example:
2597
2764
  *
2598
- * `{path: 'parent', outlet: 'nav', children: [...]}`
2765
+ * function product(a: number, b: number) {
2766
+ * return a * b;
2767
+ * }
2599
2768
  *
2600
- * In order to render, there needs to be a component on this config, which will default
2601
- * to this `EmptyOutletComponent`.
2769
+ * if (isFunction<product>(fn)) {
2770
+ * return fn(1, 2);
2771
+ * } else {
2772
+ * throw "Must provide the `product` function";
2773
+ * }
2602
2774
  */
2603
- class ɵEmptyOutletComponent {
2775
+ function isFunction(v) {
2776
+ return typeof v === 'function';
2777
+ }
2778
+ function isBoolean(v) {
2779
+ return typeof v === 'boolean';
2780
+ }
2781
+ function isUrlTree(v) {
2782
+ return v instanceof UrlTree;
2783
+ }
2784
+ function isCanLoad(guard) {
2785
+ return guard && isFunction(guard.canLoad);
2786
+ }
2787
+ function isCanActivate(guard) {
2788
+ return guard && isFunction(guard.canActivate);
2789
+ }
2790
+ function isCanActivateChild(guard) {
2791
+ return guard && isFunction(guard.canActivateChild);
2792
+ }
2793
+ function isCanDeactivate(guard) {
2794
+ return guard && isFunction(guard.canDeactivate);
2604
2795
  }
2605
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2606
- ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "14.0.0-next.13", 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"] }] });
2607
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2608
- type: Component,
2609
- args: [{ template: `<router-outlet></router-outlet>` }]
2610
- }] });
2611
2796
 
2612
2797
  /**
2613
2798
  * @license
@@ -2616,113 +2801,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
2616
2801
  * Use of this source code is governed by an MIT-style license that can be
2617
2802
  * found in the LICENSE file at https://angular.io/license
2618
2803
  */
2619
- function validateConfig(config, parentPath = '') {
2620
- // forEach doesn't iterate undefined values
2621
- for (let i = 0; i < config.length; i++) {
2622
- const route = config[i];
2623
- const fullPath = getFullPath(parentPath, route);
2624
- validateNode(route, fullPath);
2625
- }
2626
- }
2627
- function validateNode(route, fullPath) {
2628
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
2629
- if (!route) {
2630
- throw new Error(`
2631
- Invalid configuration of route '${fullPath}': Encountered undefined route.
2632
- The reason might be an extra comma.
2633
-
2634
- Example:
2635
- const routes: Routes = [
2636
- { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2637
- { path: 'dashboard', component: DashboardComponent },, << two commas
2638
- { path: 'detail/:id', component: HeroDetailComponent }
2639
- ];
2640
- `);
2641
- }
2642
- if (Array.isArray(route)) {
2643
- throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2644
- }
2645
- if (!route.component && !route.children && !route.loadChildren &&
2646
- (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2647
- throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2648
- }
2649
- if (route.redirectTo && route.children) {
2650
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2651
- }
2652
- if (route.redirectTo && route.loadChildren) {
2653
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2654
- }
2655
- if (route.children && route.loadChildren) {
2656
- throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2657
- }
2658
- if (route.redirectTo && route.component) {
2659
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
2660
- }
2661
- if (route.redirectTo && route.canActivate) {
2662
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2663
- `so canActivate will never be executed.`);
2664
- }
2665
- if (route.path && route.matcher) {
2666
- throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2667
- }
2668
- if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
2669
- throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
2670
- }
2671
- if (route.path === void 0 && route.matcher === void 0) {
2672
- throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2673
- }
2674
- if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2675
- throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2676
- }
2677
- if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2678
- const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2679
- throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2680
- }
2681
- }
2682
- if (route.children) {
2683
- validateConfig(route.children, fullPath);
2684
- }
2685
- }
2686
- function getFullPath(parentPath, currentRoute) {
2687
- if (!currentRoute) {
2688
- return parentPath;
2689
- }
2690
- if (!parentPath && !currentRoute.path) {
2691
- return '';
2692
- }
2693
- else if (parentPath && !currentRoute.path) {
2694
- return `${parentPath}/`;
2695
- }
2696
- else if (!parentPath && currentRoute.path) {
2697
- return currentRoute.path;
2698
- }
2699
- else {
2700
- return `${parentPath}/${currentRoute.path}`;
2701
- }
2702
- }
2703
- /**
2704
- * Makes a copy of the config and adds any default required properties.
2705
- */
2706
- function standardizeConfig(r) {
2707
- const children = r.children && r.children.map(standardizeConfig);
2708
- const c = children ? Object.assign(Object.assign({}, r), { children }) : Object.assign({}, r);
2709
- if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2710
- c.component = ɵEmptyOutletComponent;
2711
- }
2712
- return c;
2713
- }
2714
- /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2715
- function getOutlet(route) {
2716
- return route.outlet || PRIMARY_OUTLET;
2717
- }
2718
- /**
2719
- * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2720
- * The order of the configs is otherwise preserved.
2721
- */
2722
- function sortByMatchingOutlets(routes, outletName) {
2723
- const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2724
- sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2725
- return sortedConfig;
2804
+ const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2805
+ function prioritizedGuardValue() {
2806
+ return switchMap(obs => {
2807
+ return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2808
+ .pipe(scan((acc, list) => {
2809
+ let isPending = false;
2810
+ return list.reduce((innerAcc, val, i) => {
2811
+ if (innerAcc !== INITIAL_VALUE)
2812
+ return innerAcc;
2813
+ // Toggle pending flag if any values haven't been set yet
2814
+ if (val === INITIAL_VALUE)
2815
+ isPending = true;
2816
+ // Any other return values are only valid if we haven't yet hit a pending
2817
+ // call. This guarantees that in the case of a guard at the bottom of the
2818
+ // tree that returns a redirect, we will wait for the higher priority
2819
+ // guard at the top to finish before performing the redirect.
2820
+ if (!isPending) {
2821
+ // Early return when we hit a `false` value as that should always
2822
+ // cancel navigation
2823
+ if (val === false)
2824
+ return val;
2825
+ if (i === list.length - 1 || isUrlTree(val)) {
2826
+ return val;
2827
+ }
2828
+ }
2829
+ return innerAcc;
2830
+ }, acc);
2831
+ }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2832
+ take(1));
2833
+ });
2726
2834
  }
2727
2835
 
2728
2836
  /**
@@ -2903,17 +3011,17 @@ function canLoadFails(route) {
2903
3011
  *
2904
3012
  * Lazy modules are loaded along the way.
2905
3013
  */
2906
- function applyRedirects$1(moduleInjector, configLoader, urlSerializer, urlTree, config) {
2907
- return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
3014
+ function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
3015
+ return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
2908
3016
  }
2909
3017
  class ApplyRedirects {
2910
- constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
3018
+ constructor(injector, configLoader, urlSerializer, urlTree, config) {
3019
+ this.injector = injector;
2911
3020
  this.configLoader = configLoader;
2912
3021
  this.urlSerializer = urlSerializer;
2913
3022
  this.urlTree = urlTree;
2914
3023
  this.config = config;
2915
3024
  this.allowRedirects = true;
2916
- this.ngModule = moduleInjector.get(NgModuleRef);
2917
3025
  }
2918
3026
  apply() {
2919
3027
  const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
@@ -2924,7 +3032,7 @@ class ApplyRedirects {
2924
3032
  // them. We should be able to remove this logic as a "breaking change" but should do some more
2925
3033
  // investigation into the failures first.
2926
3034
  const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
2927
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, rootSegmentGroup, PRIMARY_OUTLET);
3035
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
2928
3036
  const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
2929
3037
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
2930
3038
  }));
@@ -2943,7 +3051,7 @@ class ApplyRedirects {
2943
3051
  }));
2944
3052
  }
2945
3053
  match(tree) {
2946
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
3054
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
2947
3055
  const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
2948
3056
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
2949
3057
  }));
@@ -2963,15 +3071,15 @@ class ApplyRedirects {
2963
3071
  rootCandidate;
2964
3072
  return new UrlTree(root, queryParams, fragment);
2965
3073
  }
2966
- expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
3074
+ expandSegmentGroup(injector, routes, segmentGroup, outlet) {
2967
3075
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
2968
- return this.expandChildren(ngModule, routes, segmentGroup)
3076
+ return this.expandChildren(injector, routes, segmentGroup)
2969
3077
  .pipe(map((children) => new UrlSegmentGroup([], children)));
2970
3078
  }
2971
- return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
3079
+ return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
2972
3080
  }
2973
3081
  // Recursively expand segment groups for all the child outlets
2974
- expandChildren(ngModule, routes, segmentGroup) {
3082
+ expandChildren(injector, routes, segmentGroup) {
2975
3083
  // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
2976
3084
  // because an absolute redirect from the primary outlet takes precedence.
2977
3085
  const childOutlets = [];
@@ -2990,16 +3098,26 @@ class ApplyRedirects {
2990
3098
  // first, followed by routes for other outlets, which might match if they have an
2991
3099
  // empty path.
2992
3100
  const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
2993
- return this.expandSegmentGroup(ngModule, sortedRoutes, child, childOutlet)
3101
+ return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
2994
3102
  .pipe(map(s => ({ segment: s, outlet: childOutlet })));
2995
3103
  }), scan((children, expandedChild) => {
2996
3104
  children[expandedChild.outlet] = expandedChild.segment;
2997
3105
  return children;
2998
3106
  }, {}), last$1());
2999
3107
  }
3000
- expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
3001
- return from(routes).pipe(concatMap((r) => {
3002
- const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
3108
+ expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
3109
+ return from(routes).pipe(concatMap(r => {
3110
+ var _a;
3111
+ if (r.providers && !r._injector) {
3112
+ r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
3113
+ }
3114
+ // We specifically _do not_ want to include the _loadedInjector here. The loaded injector
3115
+ // only applies to the route's children, not the route itself. Note that this distinction
3116
+ // only applies here to any tokens we try to retrieve during this phase. At the moment,
3117
+ // that only includes `canLoad`, which won't run again once the child module is loaded. As
3118
+ // a result, this makes no difference right now, but could in the future if there are more
3119
+ // actions here that need DI (for example, a canMatch guard).
3120
+ const expanded$ = this.expandSegmentAgainstRoute((_a = r._injector) !== null && _a !== void 0 ? _a : injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
3003
3121
  return expanded$.pipe(catchError((e) => {
3004
3122
  if (e instanceof NoMatch$1) {
3005
3123
  return of(null);
@@ -3016,35 +3134,35 @@ class ApplyRedirects {
3016
3134
  throw e;
3017
3135
  }));
3018
3136
  }
3019
- expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3137
+ expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3020
3138
  if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
3021
3139
  return noMatch(segmentGroup);
3022
3140
  }
3023
3141
  if (route.redirectTo === undefined) {
3024
- return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths, outlet);
3142
+ return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
3025
3143
  }
3026
3144
  if (allowRedirects && this.allowRedirects) {
3027
- return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
3145
+ return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
3028
3146
  }
3029
3147
  return noMatch(segmentGroup);
3030
3148
  }
3031
- expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3149
+ expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3032
3150
  if (route.path === '**') {
3033
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
3151
+ return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3034
3152
  }
3035
- return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
3153
+ return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3036
3154
  }
3037
- expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
3155
+ expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3038
3156
  const newTree = this.applyRedirectCommands([], route.redirectTo, {});
3039
3157
  if (route.redirectTo.startsWith('/')) {
3040
3158
  return absoluteRedirect(newTree);
3041
3159
  }
3042
3160
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3043
3161
  const group = new UrlSegmentGroup(newSegments, {});
3044
- return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
3162
+ return this.expandSegment(injector, group, routes, newSegments, outlet, false);
3045
3163
  }));
3046
3164
  }
3047
- expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3165
+ expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3048
3166
  const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3049
3167
  if (!matched)
3050
3168
  return noMatch(segmentGroup);
@@ -3053,16 +3171,18 @@ class ApplyRedirects {
3053
3171
  return absoluteRedirect(newTree);
3054
3172
  }
3055
3173
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3056
- return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3174
+ return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3057
3175
  }));
3058
3176
  }
3059
- matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments, outlet) {
3177
+ matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
3060
3178
  if (route.path === '**') {
3061
3179
  if (route.loadChildren) {
3062
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
3063
- this.configLoader.load(ngModule.injector, route);
3180
+ const loaded$ = route._loadedRoutes ?
3181
+ of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
3182
+ this.configLoader.loadChildren(injector, route);
3064
3183
  return loaded$.pipe(map((cfg) => {
3065
- route._loadedConfig = cfg;
3184
+ route._loadedRoutes = cfg.routes;
3185
+ route._loadedInjector = cfg.injector;
3066
3186
  return new UrlSegmentGroup(segments, {});
3067
3187
  }));
3068
3188
  }
@@ -3071,55 +3191,56 @@ class ApplyRedirects {
3071
3191
  const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
3072
3192
  if (!matched)
3073
3193
  return noMatch(rawSegmentGroup);
3074
- const childConfig$ = this.getChildConfig(ngModule, route, segments);
3194
+ const childConfig$ = this.getChildConfig(injector, route, segments);
3075
3195
  return childConfig$.pipe(mergeMap((routerConfig) => {
3076
- const childModule = routerConfig.module;
3196
+ var _a;
3197
+ const childInjector = (_a = routerConfig.injector) !== null && _a !== void 0 ? _a : injector;
3077
3198
  const childConfig = routerConfig.routes;
3078
3199
  const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3079
3200
  // See comment on the other call to `split` about why this is necessary.
3080
3201
  const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3081
3202
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3082
- const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
3203
+ const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3083
3204
  return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3084
3205
  }
3085
3206
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3086
3207
  return of(new UrlSegmentGroup(consumedSegments, {}));
3087
3208
  }
3088
3209
  const matchedOnOutlet = getOutlet(route) === outlet;
3089
- const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3210
+ const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3090
3211
  return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3091
3212
  }));
3092
3213
  }
3093
- getChildConfig(ngModule, route, segments) {
3214
+ getChildConfig(injector, route, segments) {
3094
3215
  if (route.children) {
3095
3216
  // The children belong to the same module
3096
- return of(new LoadedRouterConfig(route.children, ngModule));
3217
+ return of({ routes: route.children, injector });
3097
3218
  }
3098
3219
  if (route.loadChildren) {
3099
3220
  // lazy children belong to the loaded module
3100
- if (route._loadedConfig !== undefined) {
3101
- return of(route._loadedConfig);
3221
+ if (route._loadedRoutes !== undefined) {
3222
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3102
3223
  }
3103
- return this.runCanLoadGuards(ngModule.injector, route, segments)
3224
+ return this.runCanLoadGuards(injector, route, segments)
3104
3225
  .pipe(mergeMap((shouldLoadResult) => {
3105
3226
  if (shouldLoadResult) {
3106
- return this.configLoader.load(ngModule.injector, route)
3107
- .pipe(map((cfg) => {
3108
- route._loadedConfig = cfg;
3109
- return cfg;
3227
+ return this.configLoader.loadChildren(injector, route)
3228
+ .pipe(tap((cfg) => {
3229
+ route._loadedRoutes = cfg.routes;
3230
+ route._loadedInjector = cfg.injector;
3110
3231
  }));
3111
3232
  }
3112
3233
  return canLoadFails(route);
3113
3234
  }));
3114
3235
  }
3115
- return of(new LoadedRouterConfig([], ngModule));
3236
+ return of({ routes: [], injector });
3116
3237
  }
3117
- runCanLoadGuards(moduleInjector, route, segments) {
3238
+ runCanLoadGuards(injector, route, segments) {
3118
3239
  const canLoad = route.canLoad;
3119
3240
  if (!canLoad || canLoad.length === 0)
3120
3241
  return of(true);
3121
3242
  const canLoadObservables = canLoad.map((injectionToken) => {
3122
- const guard = moduleInjector.get(injectionToken);
3243
+ const guard = injector.get(injectionToken);
3123
3244
  let guardVal;
3124
3245
  if (isCanLoad(guard)) {
3125
3246
  guardVal = guard.canLoad(route, segments);
@@ -3247,8 +3368,8 @@ function squashSegmentGroup(segmentGroup) {
3247
3368
  * Use of this source code is governed by an MIT-style license that can be
3248
3369
  * found in the LICENSE file at https://angular.io/license
3249
3370
  */
3250
- function applyRedirects(moduleInjector, configLoader, urlSerializer, config) {
3251
- return switchMap(t => applyRedirects$1(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
3371
+ function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3372
+ return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3252
3373
  .pipe(map(urlAfterRedirects => (Object.assign(Object.assign({}, t), { urlAfterRedirects })))));
3253
3374
  }
3254
3375
 
@@ -3282,21 +3403,11 @@ function getCanActivateChild(p) {
3282
3403
  return null;
3283
3404
  return { node: p, guards: canActivateChild };
3284
3405
  }
3285
- function getToken(token, snapshot, moduleInjector) {
3286
- const config = getClosestLoadedConfig(snapshot);
3287
- const injector = config ? config.module.injector : moduleInjector;
3406
+ function getToken(token, snapshot, fallbackInjector) {
3407
+ const routeInjector = getClosestRouteInjector(snapshot);
3408
+ const injector = routeInjector !== null && routeInjector !== void 0 ? routeInjector : fallbackInjector;
3288
3409
  return injector.get(token);
3289
3410
  }
3290
- function getClosestLoadedConfig(snapshot) {
3291
- if (!snapshot)
3292
- return null;
3293
- for (let s = snapshot.parent; s; s = s.parent) {
3294
- const route = s.routeConfig;
3295
- if (route && route._loadedConfig)
3296
- return route._loadedConfig;
3297
- }
3298
- return null;
3299
- }
3300
3411
  function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
3301
3412
  canDeactivateChecks: [],
3302
3413
  canActivateChecks: []
@@ -3540,7 +3651,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
3540
3651
  * Use of this source code is governed by an MIT-style license that can be
3541
3652
  * found in the LICENSE file at https://angular.io/license
3542
3653
  */
3543
- const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
3654
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3544
3655
  class NoMatch {
3545
3656
  }
3546
3657
  function newObservableError(e) {
@@ -3649,6 +3760,7 @@ class Recognizer {
3649
3760
  return null;
3650
3761
  }
3651
3762
  processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
3763
+ var _a, _b, _c, _d;
3652
3764
  if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet))
3653
3765
  return null;
3654
3766
  let snapshot;
@@ -3657,11 +3769,11 @@ class Recognizer {
3657
3769
  if (route.path === '**') {
3658
3770
  const params = segments.length > 0 ? last(segments).parameters : {};
3659
3771
  const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
3660
- snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
3772
+ 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),
3661
3773
  // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
3662
3774
  // production bundle size. This value is intended only to surface a warning to users
3663
3775
  // depending on `relativeLinkResolution: 'legacy'` in dev mode.
3664
- (NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3776
+ (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3665
3777
  pathIndexShift));
3666
3778
  }
3667
3779
  else {
@@ -3672,7 +3784,7 @@ class Recognizer {
3672
3784
  consumedSegments = result.consumedSegments;
3673
3785
  remainingSegments = result.remainingSegments;
3674
3786
  const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3675
- snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
3787
+ 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 :
3676
3788
  pathIndexShift));
3677
3789
  }
3678
3790
  const childConfig = getChildConfig(route);
@@ -3721,7 +3833,7 @@ function getChildConfig(route) {
3721
3833
  return route.children;
3722
3834
  }
3723
3835
  if (route.loadChildren) {
3724
- return route._loadedConfig.routes;
3836
+ return route._loadedRoutes;
3725
3837
  }
3726
3838
  return [];
3727
3839
  }
@@ -3867,16 +3979,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
3867
3979
  }
3868
3980
  const data = {};
3869
3981
  return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
3870
- .pipe(take(1), tap((value) => {
3982
+ .pipe(first(), tap((value) => {
3871
3983
  data[key] = value;
3872
- }))), takeLast(1), mergeMap(() => {
3873
- // Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
3874
- // the chain which will cancel navigation
3875
- if (getDataKeys(data).length === keys.length) {
3876
- return of(data);
3877
- }
3878
- return EMPTY;
3879
- }));
3984
+ }))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
3880
3985
  }
3881
3986
  function getDataKeys(obj) {
3882
3987
  return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
@@ -3985,6 +4090,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3985
4090
  * Use of this source code is governed by an MIT-style license that can be
3986
4091
  * found in the LICENSE file at https://angular.io/license
3987
4092
  */
4093
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3988
4094
  /**
3989
4095
  * The [DI token](guide/glossary/#di-token) for a router configuration.
3990
4096
  *
@@ -3997,43 +4103,85 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3997
4103
  */
3998
4104
  const ROUTES = new InjectionToken('ROUTES');
3999
4105
  class RouterConfigLoader {
4000
- constructor(injector, compiler, onLoadStartListener, onLoadEndListener) {
4106
+ constructor(injector, compiler) {
4001
4107
  this.injector = injector;
4002
4108
  this.compiler = compiler;
4003
- this.onLoadStartListener = onLoadStartListener;
4004
- this.onLoadEndListener = onLoadEndListener;
4109
+ this.componentLoaders = new WeakMap();
4110
+ this.childrenLoaders = new WeakMap();
4111
+ }
4112
+ loadComponent(route) {
4113
+ if (this.componentLoaders.get(route)) {
4114
+ return this.componentLoaders.get(route);
4115
+ }
4116
+ else if (route._loadedComponent) {
4117
+ return of(route._loadedComponent);
4118
+ }
4119
+ if (this.onLoadStartListener) {
4120
+ this.onLoadStartListener(route);
4121
+ }
4122
+ const loadRunner = wrapIntoObservable(route.loadComponent())
4123
+ .pipe(tap(component => {
4124
+ var _a;
4125
+ if (this.onLoadEndListener) {
4126
+ this.onLoadEndListener(route);
4127
+ }
4128
+ NG_DEV_MODE$1 && assertStandalone((_a = route.path) !== null && _a !== void 0 ? _a : '', component);
4129
+ route._loadedComponent = component;
4130
+ }), finalize(() => {
4131
+ this.componentLoaders.delete(route);
4132
+ }));
4133
+ // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
4134
+ const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
4135
+ this.componentLoaders.set(route, loader);
4136
+ return loader;
4005
4137
  }
4006
- load(parentInjector, route) {
4007
- if (route._loader$) {
4008
- return route._loader$;
4138
+ loadChildren(parentInjector, route) {
4139
+ if (this.childrenLoaders.get(route)) {
4140
+ return this.childrenLoaders.get(route);
4141
+ }
4142
+ else if (route._loadedRoutes) {
4143
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
4009
4144
  }
4010
4145
  if (this.onLoadStartListener) {
4011
4146
  this.onLoadStartListener(route);
4012
4147
  }
4013
- const moduleFactory$ = this.loadModuleFactory(route.loadChildren);
4014
- const loadRunner = moduleFactory$.pipe(map((factory) => {
4148
+ const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
4149
+ const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
4015
4150
  if (this.onLoadEndListener) {
4016
4151
  this.onLoadEndListener(route);
4017
4152
  }
4018
- const module = factory.create(parentInjector);
4019
- // When loading a module that doesn't provide `RouterModule.forChild()` preloader
4020
- // will get stuck in an infinite loop. The child module's Injector will look to
4021
- // its parent `Injector` when it doesn't find any ROUTES so it will return routes
4022
- // for it's parent module instead.
4023
- return new LoadedRouterConfig(flatten(module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))
4024
- .map(standardizeConfig), module);
4025
- }), catchError((err) => {
4026
- route._loader$ = undefined;
4027
- throw err;
4153
+ // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
4154
+ // injector associated with lazy loading a `Route` array.
4155
+ let injector;
4156
+ let rawRoutes;
4157
+ let requireStandaloneComponents = false;
4158
+ if (Array.isArray(factoryOrRoutes)) {
4159
+ rawRoutes = factoryOrRoutes;
4160
+ requireStandaloneComponents = true;
4161
+ }
4162
+ else {
4163
+ injector = factoryOrRoutes.create(parentInjector).injector;
4164
+ // When loading a module that doesn't provide `RouterModule.forChild()` preloader
4165
+ // will get stuck in an infinite loop. The child module's Injector will look to
4166
+ // its parent `Injector` when it doesn't find any ROUTES so it will return routes
4167
+ // for it's parent module instead.
4168
+ rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
4169
+ }
4170
+ const routes = rawRoutes.map(standardizeConfig);
4171
+ NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
4172
+ return { routes, injector };
4173
+ }), finalize(() => {
4174
+ this.childrenLoaders.delete(route);
4028
4175
  }));
4029
4176
  // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
4030
- route._loader$ = new ConnectableObservable(loadRunner, () => new Subject())
4177
+ const loader = new ConnectableObservable(loadRunner, () => new Subject())
4031
4178
  .pipe(refCount());
4032
- return route._loader$;
4179
+ this.childrenLoaders.set(route, loader);
4180
+ return loader;
4033
4181
  }
4034
- loadModuleFactory(loadChildren) {
4182
+ loadModuleFactoryOrRoutes(loadChildren) {
4035
4183
  return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
4036
- if (t instanceof NgModuleFactory) {
4184
+ if (t instanceof NgModuleFactory || Array.isArray(t)) {
4037
4185
  return of(t);
4038
4186
  }
4039
4187
  else {
@@ -4042,6 +4190,11 @@ class RouterConfigLoader {
4042
4190
  }));
4043
4191
  }
4044
4192
  }
4193
+ RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4194
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterConfigLoader });
4195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterConfigLoader, decorators: [{
4196
+ type: Injectable
4197
+ }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
4045
4198
 
4046
4199
  /**
4047
4200
  * @license
@@ -4074,6 +4227,7 @@ class DefaultUrlHandlingStrategy {
4074
4227
  }
4075
4228
  }
4076
4229
 
4230
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
4077
4231
  function defaultErrorHandler(error) {
4078
4232
  throw error;
4079
4233
  }
@@ -4245,6 +4399,9 @@ class Router {
4245
4399
  this.canceledNavigationResolution = 'replace';
4246
4400
  const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
4247
4401
  const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
4402
+ this.configLoader = injector.get(RouterConfigLoader);
4403
+ this.configLoader.onLoadEndListener = onLoadEnd;
4404
+ this.configLoader.onLoadStartListener = onLoadStart;
4248
4405
  this.ngModule = injector.get(NgModuleRef);
4249
4406
  this.console = injector.get(ɵConsole);
4250
4407
  const ngZone = injector.get(NgZone);
@@ -4253,7 +4410,6 @@ class Router {
4253
4410
  this.currentUrlTree = createEmptyUrlTree();
4254
4411
  this.rawUrlTree = this.currentUrlTree;
4255
4412
  this.browserUrlTree = this.currentUrlTree;
4256
- this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
4257
4413
  this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4258
4414
  this.transitions = new BehaviorSubject({
4259
4415
  id: 0,
@@ -4451,6 +4607,26 @@ class Router {
4451
4607
  skipLocationChange: !!skipLocationChange,
4452
4608
  replaceUrl: !!replaceUrl,
4453
4609
  });
4610
+ }),
4611
+ // --- LOAD COMPONENTS ---
4612
+ switchTap((t) => {
4613
+ const loadComponents = (route) => {
4614
+ var _a;
4615
+ const loaders = [];
4616
+ if (((_a = route.routeConfig) === null || _a === void 0 ? void 0 : _a.loadComponent) &&
4617
+ !route.routeConfig._loadedComponent) {
4618
+ loaders.push(this.configLoader.loadComponent(route.routeConfig)
4619
+ .pipe(tap(loadedComponent => {
4620
+ route.component = loadedComponent;
4621
+ }), map(() => void 0)));
4622
+ }
4623
+ for (const child of route.children) {
4624
+ loaders.push(...loadComponents(child));
4625
+ }
4626
+ return loaders;
4627
+ };
4628
+ return combineLatest(loadComponents(t.targetSnapshot.root))
4629
+ .pipe(defaultIfEmpty(), take(1));
4454
4630
  }), map((t) => {
4455
4631
  const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4456
4632
  return (Object.assign(Object.assign({}, t), { targetRouterState }));
@@ -4530,23 +4706,17 @@ class Router {
4530
4706
  t.resolve(false);
4531
4707
  }
4532
4708
  else {
4533
- // setTimeout is required so this navigation finishes with
4534
- // the return EMPTY below. If it isn't allowed to finish
4535
- // processing, there can be multiple navigations to the same
4536
- // URL.
4537
- setTimeout(() => {
4538
- const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4539
- const extras = {
4540
- skipLocationChange: t.extras.skipLocationChange,
4541
- // The URL is already updated at this point if we have 'eager' URL
4542
- // updates or if the navigation was triggered by the browser (back
4543
- // button, URL bar, etc). We want to replace that item in history if
4544
- // the navigation is rejected.
4545
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
4546
- isBrowserTriggeredNavigation(t.source)
4547
- };
4548
- this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4549
- }, 0);
4709
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4710
+ const extras = {
4711
+ skipLocationChange: t.extras.skipLocationChange,
4712
+ // The URL is already updated at this point if we have 'eager' URL
4713
+ // updates or if the navigation was triggered by the browser (back
4714
+ // button, URL bar, etc). We want to replace that item in history if
4715
+ // the navigation is rejected.
4716
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
4717
+ isBrowserTriggeredNavigation(t.source)
4718
+ };
4719
+ this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4550
4720
  }
4551
4721
  /* All other errors should reset to the router's internal URL reference to
4552
4722
  * the pre-error state. */
@@ -4657,7 +4827,7 @@ class Router {
4657
4827
  * ```
4658
4828
  */
4659
4829
  resetConfig(config) {
4660
- validateConfig(config);
4830
+ NG_DEV_MODE && validateConfig(config);
4661
4831
  this.config = config.map(standardizeConfig);
4662
4832
  this.navigated = false;
4663
4833
  this.lastSuccessfulId = -1;
@@ -5015,9 +5185,9 @@ class Router {
5015
5185
  return { navigationId };
5016
5186
  }
5017
5187
  }
5018
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5019
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router });
5020
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router, decorators: [{
5188
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5189
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router });
5190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router, decorators: [{
5021
5191
  type: Injectable
5022
5192
  }], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
5023
5193
  function validateCommands(commands) {
@@ -5209,9 +5379,9 @@ class RouterLink {
5209
5379
  });
5210
5380
  }
5211
5381
  }
5212
- RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5213
- RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.13", 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 });
5214
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLink, decorators: [{
5382
+ RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5383
+ RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-next.16", 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 });
5384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLink, decorators: [{
5215
5385
  type: Directive,
5216
5386
  args: [{ selector: ':not(a):not(area)[routerLink]' }]
5217
5387
  }], ctorParameters: function () {
@@ -5330,9 +5500,9 @@ class RouterLinkWithHref {
5330
5500
  });
5331
5501
  }
5332
5502
  }
5333
- RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5334
- RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.13", 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 });
5335
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5503
+ RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5504
+ RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-next.16", 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 });
5505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5336
5506
  type: Directive,
5337
5507
  args: [{ selector: 'a[routerLink],area[routerLink]' }]
5338
5508
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
@@ -5429,6 +5599,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
5429
5599
  * </div>
5430
5600
  * ```
5431
5601
  *
5602
+ * The `RouterLinkActive` directive can also be used to set the aria-current attribute
5603
+ * to provide an alternative distinction for active elements to visually impaired users.
5604
+ *
5605
+ * For example, the following code adds the 'active' class to the Home Page link when it is
5606
+ * indeed active and in such case also sets its aria-current attribute to 'page':
5607
+ *
5608
+ * ```
5609
+ * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
5610
+ * ```
5611
+ *
5432
5612
  * @ngModule RouterModule
5433
5613
  *
5434
5614
  * @publicApi
@@ -5524,6 +5704,12 @@ class RouterLinkActive {
5524
5704
  this.renderer.removeClass(this.element.nativeElement, c);
5525
5705
  }
5526
5706
  });
5707
+ if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
5708
+ this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
5709
+ }
5710
+ else {
5711
+ this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
5712
+ }
5527
5713
  // Emit on isActiveChange after classes are updated
5528
5714
  this.isActiveChange.emit(hasActiveLinks);
5529
5715
  }
@@ -5543,9 +5729,9 @@ class RouterLinkActive {
5543
5729
  this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
5544
5730
  }
5545
5731
  }
5546
- RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", 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 });
5547
- RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.13", 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 });
5548
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLinkActive, decorators: [{
5732
+ RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", 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 });
5733
+ RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.0-next.16", 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 });
5734
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLinkActive, decorators: [{
5549
5735
  type: Directive,
5550
5736
  args: [{
5551
5737
  selector: '[routerLinkActive]',
@@ -5565,6 +5751,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
5565
5751
  args: [RouterLinkWithHref, { descendants: true }]
5566
5752
  }], routerLinkActiveOptions: [{
5567
5753
  type: Input
5754
+ }], ariaCurrentWhenActive: [{
5755
+ type: Input
5568
5756
  }], isActiveChange: [{
5569
5757
  type: Output
5570
5758
  }], routerLinkActive: [{
@@ -5649,9 +5837,9 @@ class DefaultTitleStrategy extends TitleStrategy {
5649
5837
  }
5650
5838
  }
5651
5839
  }
5652
- DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5653
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5840
+ DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5841
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5842
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5655
5843
  type: Injectable,
5656
5844
  args: [{ providedIn: 'root' }]
5657
5845
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -5715,13 +5903,11 @@ class NoPreloading {
5715
5903
  * @publicApi
5716
5904
  */
5717
5905
  class RouterPreloader {
5718
- constructor(router, compiler, injector, preloadingStrategy) {
5906
+ constructor(router, compiler, injector, preloadingStrategy, loader) {
5719
5907
  this.router = router;
5720
5908
  this.injector = injector;
5721
5909
  this.preloadingStrategy = preloadingStrategy;
5722
- const onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r));
5723
- const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
5724
- this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
5910
+ this.loader = loader;
5725
5911
  }
5726
5912
  setUpPreloading() {
5727
5913
  this.subscription =
@@ -5730,8 +5916,7 @@ class RouterPreloader {
5730
5916
  .subscribe(() => { });
5731
5917
  }
5732
5918
  preload() {
5733
- const ngModule = this.injector.get(NgModuleRef);
5734
- return this.processRoutes(ngModule, this.router.config);
5919
+ return this.processRoutes(this.injector, this.router.config);
5735
5920
  }
5736
5921
  /** @nodoc */
5737
5922
  ngOnDestroy() {
@@ -5739,41 +5924,61 @@ class RouterPreloader {
5739
5924
  this.subscription.unsubscribe();
5740
5925
  }
5741
5926
  }
5742
- processRoutes(ngModule, routes) {
5927
+ processRoutes(injector, routes) {
5928
+ var _a, _b, _c;
5743
5929
  const res = [];
5744
5930
  for (const route of routes) {
5745
- // we already have the config loaded, just recurse
5746
- if (route.loadChildren && !route.canLoad && route._loadedConfig) {
5747
- const childConfig = route._loadedConfig;
5748
- res.push(this.processRoutes(childConfig.module, childConfig.routes));
5749
- // no config loaded, fetch the config
5931
+ if (route.providers && !route._injector) {
5932
+ route._injector =
5933
+ createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
5750
5934
  }
5751
- else if (route.loadChildren && !route.canLoad) {
5752
- res.push(this.preloadConfig(ngModule, route));
5753
- // recurse into children
5935
+ const injectorForCurrentRoute = (_a = route._injector) !== null && _a !== void 0 ? _a : injector;
5936
+ const injectorForChildren = (_b = route._loadedInjector) !== null && _b !== void 0 ? _b : injectorForCurrentRoute;
5937
+ if ((route.loadChildren && !route._loadedRoutes) ||
5938
+ (route.loadComponent && !route._loadedComponent)) {
5939
+ res.push(this.preloadConfig(injectorForCurrentRoute, route));
5754
5940
  }
5755
- else if (route.children) {
5756
- res.push(this.processRoutes(ngModule, route.children));
5941
+ else if (route.children || route._loadedRoutes) {
5942
+ res.push(this.processRoutes(injectorForChildren, ((_c = route.children) !== null && _c !== void 0 ? _c : route._loadedRoutes)));
5757
5943
  }
5758
5944
  }
5759
- return from(res).pipe(mergeAll(), map((_) => void 0));
5945
+ return from(res).pipe(mergeAll());
5760
5946
  }
5761
- preloadConfig(ngModule, route) {
5947
+ preloadConfig(injector, route) {
5762
5948
  return this.preloadingStrategy.preload(route, () => {
5763
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
5764
- this.loader.load(ngModule.injector, route);
5765
- return loaded$.pipe(mergeMap((config) => {
5766
- route._loadedConfig = config;
5767
- return this.processRoutes(config.module, config.routes);
5949
+ let loadedChildren$;
5950
+ if (route.loadChildren && route.canLoad === undefined) {
5951
+ loadedChildren$ = this.loader.loadChildren(injector, route);
5952
+ }
5953
+ else {
5954
+ loadedChildren$ = of(null);
5955
+ }
5956
+ const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
5957
+ var _a;
5958
+ if (config === null) {
5959
+ return of(void 0);
5960
+ }
5961
+ route._loadedRoutes = config.routes;
5962
+ route._loadedInjector = config.injector;
5963
+ // If the loaded config was a module, use that as the module/module injector going
5964
+ // forward. Otherwise, continue using the current module/module injector.
5965
+ return this.processRoutes((_a = config.injector) !== null && _a !== void 0 ? _a : injector, config.routes);
5768
5966
  }));
5967
+ if (route.loadComponent && !route._loadedComponent) {
5968
+ const loadComponent$ = this.loader.loadComponent(route);
5969
+ return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
5970
+ }
5971
+ else {
5972
+ return recursiveLoadChildren$;
5973
+ }
5769
5974
  });
5770
5975
  }
5771
5976
  }
5772
- RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.Injector }, { token: PreloadingStrategy }], target: i0.ɵɵFactoryTarget.Injectable });
5773
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterPreloader });
5774
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterPreloader, decorators: [{
5977
+ RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
5978
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterPreloader });
5979
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterPreloader, decorators: [{
5775
5980
  type: Injectable
5776
- }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.Injector }, { type: PreloadingStrategy }]; } });
5981
+ }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
5777
5982
 
5778
5983
  class RouterScroller {
5779
5984
  constructor(router,
@@ -5850,9 +6055,9 @@ class RouterScroller {
5850
6055
  }
5851
6056
  }
5852
6057
  }
5853
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5854
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller });
5855
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller, decorators: [{
6058
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6059
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller });
6060
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller, decorators: [{
5856
6061
  type: Injectable
5857
6062
  }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
5858
6063
 
@@ -5895,6 +6100,7 @@ const ROUTER_PROVIDERS = [
5895
6100
  NoPreloading,
5896
6101
  PreloadAllModules,
5897
6102
  { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
6103
+ RouterConfigLoader,
5898
6104
  ];
5899
6105
  function routerNgProbeToken() {
5900
6106
  return new NgProbeToken('Router', Router);
@@ -5993,10 +6199,10 @@ class RouterModule {
5993
6199
  return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
5994
6200
  }
5995
6201
  }
5996
- RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
5997
- RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
5998
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule });
5999
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule, decorators: [{
6202
+ RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6203
+ RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
6204
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule });
6205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule, decorators: [{
6000
6206
  type: NgModule,
6001
6207
  args: [{
6002
6208
  declarations: ROUTER_DIRECTIVES,
@@ -6060,12 +6266,12 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
6060
6266
  }
6061
6267
  router.titleStrategy = titleStrategy !== null && titleStrategy !== void 0 ? titleStrategy : defaultTitleStrategy;
6062
6268
  assignExtraOptionsToRouter(opts, router);
6063
- if (opts.enableTracing) {
6269
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
6064
6270
  router.events.subscribe((e) => {
6065
6271
  var _a, _b;
6066
6272
  // tslint:disable:no-console
6067
6273
  (_a = console.group) === null || _a === void 0 ? void 0 : _a.call(console, `Router Event: ${e.constructor.name}`);
6068
- console.log(e.toString());
6274
+ console.log(stringifyEvent(e));
6069
6275
  console.log(e);
6070
6276
  (_b = console.groupEnd) === null || _b === void 0 ? void 0 : _b.call(console);
6071
6277
  // tslint:enable:no-console
@@ -6132,9 +6338,7 @@ class RouterInitializer {
6132
6338
  router.setUpLocationChangeListener();
6133
6339
  resolve(true);
6134
6340
  }
6135
- else if (
6136
- // TODO: enabled is deprecated as of v11, can be removed in v13
6137
- opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
6341
+ else if (opts.initialNavigation === 'enabledBlocking') {
6138
6342
  router.hooks.afterPreactivation = () => {
6139
6343
  // only the initial navigation should be delayed
6140
6344
  if (!this.initNavigation) {
@@ -6178,9 +6382,9 @@ class RouterInitializer {
6178
6382
  this.destroyed = true;
6179
6383
  }
6180
6384
  }
6181
- RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6182
- RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterInitializer });
6183
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterInitializer, decorators: [{
6385
+ RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6386
+ RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterInitializer });
6387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterInitializer, decorators: [{
6184
6388
  type: Injectable
6185
6389
  }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
6186
6390
  function getAppInitializer(r) {
@@ -6220,7 +6424,7 @@ function provideRouterInitializer() {
6220
6424
  /**
6221
6425
  * @publicApi
6222
6426
  */
6223
- const VERSION = new Version('14.0.0-next.13');
6427
+ const VERSION = new Version('14.0.0-next.16');
6224
6428
 
6225
6429
  /**
6226
6430
  * @license