@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,5 +1,5 @@
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
  */
@@ -7,9 +7,9 @@
7
7
  import * as i3 from '@angular/common';
8
8
  import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
9
9
  import * as i0 from '@angular/core';
10
- 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';
10
+ 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';
11
11
  import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
12
- import { map, switchMap, take, startWith, scan, filter, catchError, concatMap, last as last$1, first, mergeMap, tap, takeLast, refCount, finalize, mergeAll } from 'rxjs/operators';
12
+ 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';
13
13
  import * as i1 from '@angular/platform-browser';
14
14
 
15
15
  /**
@@ -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,53 @@ 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
+ if (!('type' in routerEvent)) {
435
+ return `Unknown Router Event: ${routerEvent.constructor.name}`;
436
+ }
437
+ switch (routerEvent.type) {
438
+ case 14 /* EventType.ActivationEnd */:
439
+ return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
440
+ case 13 /* EventType.ActivationStart */:
441
+ return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
442
+ case 12 /* EventType.ChildActivationEnd */:
443
+ return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
444
+ case 11 /* EventType.ChildActivationStart */:
445
+ return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
446
+ case 8 /* EventType.GuardsCheckEnd */:
447
+ return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
448
+ case 7 /* EventType.GuardsCheckStart */:
449
+ return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
450
+ case 2 /* EventType.NavigationCancel */:
451
+ return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
452
+ case 1 /* EventType.NavigationEnd */:
453
+ return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
454
+ case 3 /* EventType.NavigationError */:
455
+ return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
456
+ case 0 /* EventType.NavigationStart */:
457
+ return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
458
+ case 6 /* EventType.ResolveEnd */:
459
+ return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
460
+ case 5 /* EventType.ResolveStart */:
461
+ return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
462
+ case 10 /* EventType.RouteConfigLoadEnd */:
463
+ return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
464
+ case 9 /* EventType.RouteConfigLoadStart */:
465
+ return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
466
+ case 4 /* EventType.RoutesRecognized */:
467
+ return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
468
+ case 15 /* EventType.Scroll */:
469
+ const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
470
+ return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
471
+ }
472
+ }
417
473
 
418
474
  /**
419
475
  * @license
@@ -1362,7 +1418,6 @@ class ActivatedRoute {
1362
1418
  /** The outlet name of the route, a constant. */
1363
1419
  outlet,
1364
1420
  /** The component of the route, a constant. */
1365
- // TODO(vsavkin): remove |string
1366
1421
  component, futureSnapshot) {
1367
1422
  this.url = url;
1368
1423
  this.params = params;
@@ -2020,181 +2075,76 @@ function compare(path, params, segment) {
2020
2075
  * Use of this source code is governed by an MIT-style license that can be
2021
2076
  * found in the LICENSE file at https://angular.io/license
2022
2077
  */
2023
- const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2024
- new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2025
- .activate(rootContexts);
2026
- return t;
2027
- });
2028
- class ActivateRoutes {
2029
- constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2030
- this.routeReuseStrategy = routeReuseStrategy;
2031
- this.futureState = futureState;
2032
- this.currState = currState;
2033
- this.forwardEvent = forwardEvent;
2034
- }
2035
- activate(parentContexts) {
2036
- const futureRoot = this.futureState._root;
2037
- const currRoot = this.currState ? this.currState._root : null;
2038
- this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2039
- advanceActivatedRoute(this.futureState.root);
2040
- this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2041
- }
2042
- // De-activate the child route that are not re-used for the future state
2043
- deactivateChildRoutes(futureNode, currNode, contexts) {
2044
- const children = nodeChildrenAsMap(currNode);
2045
- // Recurse on the routes active in the future state to de-activate deeper children
2046
- futureNode.children.forEach(futureChild => {
2047
- const childOutletName = futureChild.value.outlet;
2048
- this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2049
- delete children[childOutletName];
2050
- });
2051
- // De-activate the routes that will not be re-used
2052
- forEach(children, (v, childName) => {
2053
- this.deactivateRouteAndItsChildren(v, contexts);
2054
- });
2055
- }
2056
- deactivateRoutes(futureNode, currNode, parentContext) {
2057
- const future = futureNode.value;
2058
- const curr = currNode ? currNode.value : null;
2059
- if (future === curr) {
2060
- // Reusing the node, check to see if the children need to be de-activated
2061
- if (future.component) {
2062
- // If we have a normal route, we need to go through an outlet.
2063
- const context = parentContext.getContext(future.outlet);
2064
- if (context) {
2065
- this.deactivateChildRoutes(futureNode, currNode, context.children);
2066
- }
2067
- }
2068
- else {
2069
- // if we have a componentless route, we recurse but keep the same outlet map.
2070
- this.deactivateChildRoutes(futureNode, currNode, parentContext);
2071
- }
2072
- }
2073
- else {
2074
- if (curr) {
2075
- // Deactivate the current route which will not be re-used
2076
- this.deactivateRouteAndItsChildren(currNode, parentContext);
2077
- }
2078
- }
2078
+ /**
2079
+ * Store contextual information about a `RouterOutlet`
2080
+ *
2081
+ * @publicApi
2082
+ */
2083
+ class OutletContext {
2084
+ constructor() {
2085
+ this.outlet = null;
2086
+ this.route = null;
2087
+ /**
2088
+ * @deprecated Passing a resolver to retrieve a component factory is not required and is
2089
+ * deprecated since v14.
2090
+ */
2091
+ this.resolver = null;
2092
+ this.injector = null;
2093
+ this.children = new ChildrenOutletContexts();
2094
+ this.attachRef = null;
2079
2095
  }
2080
- deactivateRouteAndItsChildren(route, parentContexts) {
2081
- // If there is no component, the Route is never attached to an outlet (because there is no
2082
- // component to attach).
2083
- if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2084
- this.detachAndStoreRouteSubtree(route, parentContexts);
2085
- }
2086
- else {
2087
- this.deactivateRouteAndOutlet(route, parentContexts);
2088
- }
2096
+ }
2097
+ /**
2098
+ * Store contextual information about the children (= nested) `RouterOutlet`
2099
+ *
2100
+ * @publicApi
2101
+ */
2102
+ class ChildrenOutletContexts {
2103
+ constructor() {
2104
+ // contexts for child outlets, by name.
2105
+ this.contexts = new Map();
2089
2106
  }
2090
- detachAndStoreRouteSubtree(route, parentContexts) {
2091
- const context = parentContexts.getContext(route.value.outlet);
2092
- const contexts = context && route.value.component ? context.children : parentContexts;
2093
- const children = nodeChildrenAsMap(route);
2094
- for (const childOutlet of Object.keys(children)) {
2095
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2096
- }
2097
- if (context && context.outlet) {
2098
- const componentRef = context.outlet.detach();
2099
- const contexts = context.children.onOutletDeactivated();
2100
- this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2101
- }
2107
+ /** Called when a `RouterOutlet` directive is instantiated */
2108
+ onChildOutletCreated(childName, outlet) {
2109
+ const context = this.getOrCreateContext(childName);
2110
+ context.outlet = outlet;
2111
+ this.contexts.set(childName, context);
2102
2112
  }
2103
- deactivateRouteAndOutlet(route, parentContexts) {
2104
- const context = parentContexts.getContext(route.value.outlet);
2105
- // The context could be `null` if we are on a componentless route but there may still be
2106
- // children that need deactivating.
2107
- const contexts = context && route.value.component ? context.children : parentContexts;
2108
- const children = nodeChildrenAsMap(route);
2109
- for (const childOutlet of Object.keys(children)) {
2110
- this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2111
- }
2112
- if (context && context.outlet) {
2113
- // Destroy the component
2114
- context.outlet.deactivate();
2115
- // Destroy the contexts for all the outlets that were in the component
2116
- context.children.onOutletDeactivated();
2117
- // Clear the information about the attached component on the context but keep the reference to
2118
- // the outlet.
2113
+ /**
2114
+ * Called when a `RouterOutlet` directive is destroyed.
2115
+ * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2116
+ * re-created later.
2117
+ */
2118
+ onChildOutletDestroyed(childName) {
2119
+ const context = this.getContext(childName);
2120
+ if (context) {
2121
+ context.outlet = null;
2119
2122
  context.attachRef = null;
2120
- context.resolver = null;
2121
- context.route = null;
2122
2123
  }
2123
2124
  }
2124
- activateChildRoutes(futureNode, currNode, contexts) {
2125
- const children = nodeChildrenAsMap(currNode);
2126
- futureNode.children.forEach(c => {
2127
- this.activateRoutes(c, children[c.value.outlet], contexts);
2128
- this.forwardEvent(new ActivationEnd(c.value.snapshot));
2129
- });
2130
- if (futureNode.children.length) {
2131
- this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2132
- }
2125
+ /**
2126
+ * Called when the corresponding route is deactivated during navigation.
2127
+ * Because the component get destroyed, all children outlet are destroyed.
2128
+ */
2129
+ onOutletDeactivated() {
2130
+ const contexts = this.contexts;
2131
+ this.contexts = new Map();
2132
+ return contexts;
2133
2133
  }
2134
- activateRoutes(futureNode, currNode, parentContexts) {
2135
- const future = futureNode.value;
2136
- const curr = currNode ? currNode.value : null;
2137
- advanceActivatedRoute(future);
2138
- // reusing the node
2139
- if (future === curr) {
2140
- if (future.component) {
2141
- // If we have a normal route, we need to go through an outlet.
2142
- const context = parentContexts.getOrCreateContext(future.outlet);
2143
- this.activateChildRoutes(futureNode, currNode, context.children);
2144
- }
2145
- else {
2146
- // if we have a componentless route, we recurse but keep the same outlet map.
2147
- this.activateChildRoutes(futureNode, currNode, parentContexts);
2148
- }
2149
- }
2150
- else {
2151
- if (future.component) {
2152
- // if we have a normal route, we need to place the component into the outlet and recurse.
2153
- const context = parentContexts.getOrCreateContext(future.outlet);
2154
- if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2155
- const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2156
- this.routeReuseStrategy.store(future.snapshot, null);
2157
- context.children.onOutletReAttached(stored.contexts);
2158
- context.attachRef = stored.componentRef;
2159
- context.route = stored.route.value;
2160
- if (context.outlet) {
2161
- // Attach right away when the outlet has already been instantiated
2162
- // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2163
- context.outlet.attach(stored.componentRef, stored.route.value);
2164
- }
2165
- advanceActivatedRoute(stored.route.value);
2166
- this.activateChildRoutes(futureNode, null, context.children);
2167
- }
2168
- else {
2169
- const config = parentLoadedConfig(future.snapshot);
2170
- const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
2171
- context.attachRef = null;
2172
- context.route = future;
2173
- context.resolver = cmpFactoryResolver;
2174
- if (context.outlet) {
2175
- // Activate the outlet when it has already been instantiated
2176
- // Otherwise it will get activated from its `ngOnInit` when instantiated
2177
- context.outlet.activateWith(future, cmpFactoryResolver);
2178
- }
2179
- this.activateChildRoutes(futureNode, null, context.children);
2180
- }
2181
- }
2182
- else {
2183
- // if we have a componentless route, we recurse but keep the same outlet map.
2184
- this.activateChildRoutes(futureNode, null, parentContexts);
2185
- }
2134
+ onOutletReAttached(contexts) {
2135
+ this.contexts = contexts;
2136
+ }
2137
+ getOrCreateContext(childName) {
2138
+ let context = this.getContext(childName);
2139
+ if (!context) {
2140
+ context = new OutletContext();
2141
+ this.contexts.set(childName, context);
2186
2142
  }
2143
+ return context;
2187
2144
  }
2188
- }
2189
- function parentLoadedConfig(snapshot) {
2190
- for (let s = snapshot.parent; s; s = s.parent) {
2191
- const route = s.routeConfig;
2192
- if (route && route._loadedConfig)
2193
- return route._loadedConfig;
2194
- if (route && route.component)
2195
- return null;
2145
+ getContext(childName) {
2146
+ return this.contexts.get(childName) || null;
2196
2147
  }
2197
- return null;
2198
2148
  }
2199
2149
 
2200
2150
  /**
@@ -2204,182 +2154,13 @@ function parentLoadedConfig(snapshot) {
2204
2154
  * Use of this source code is governed by an MIT-style license that can be
2205
2155
  * found in the LICENSE file at https://angular.io/license
2206
2156
  */
2207
- class LoadedRouterConfig {
2208
- constructor(routes, module) {
2209
- this.routes = routes;
2210
- this.module = module;
2211
- }
2212
- }
2213
-
2214
2157
  /**
2215
- * @license
2216
- * Copyright Google LLC All Rights Reserved.
2158
+ * @description
2217
2159
  *
2218
- * Use of this source code is governed by an MIT-style license that can be
2219
- * found in the LICENSE file at https://angular.io/license
2220
- */
2221
- /**
2222
- * Simple function check, but generic so type inference will flow. Example:
2160
+ * Acts as a placeholder that Angular dynamically fills based on the current router state.
2223
2161
  *
2224
- * function product(a: number, b: number) {
2225
- * return a * b;
2226
- * }
2227
- *
2228
- * if (isFunction<product>(fn)) {
2229
- * return fn(1, 2);
2230
- * } else {
2231
- * throw "Must provide the `product` function";
2232
- * }
2233
- */
2234
- function isFunction(v) {
2235
- return typeof v === 'function';
2236
- }
2237
- function isBoolean(v) {
2238
- return typeof v === 'boolean';
2239
- }
2240
- function isUrlTree(v) {
2241
- return v instanceof UrlTree;
2242
- }
2243
- function isCanLoad(guard) {
2244
- return guard && isFunction(guard.canLoad);
2245
- }
2246
- function isCanActivate(guard) {
2247
- return guard && isFunction(guard.canActivate);
2248
- }
2249
- function isCanActivateChild(guard) {
2250
- return guard && isFunction(guard.canActivateChild);
2251
- }
2252
- function isCanDeactivate(guard) {
2253
- return guard && isFunction(guard.canDeactivate);
2254
- }
2255
-
2256
- /**
2257
- * @license
2258
- * Copyright Google LLC All Rights Reserved.
2259
- *
2260
- * Use of this source code is governed by an MIT-style license that can be
2261
- * found in the LICENSE file at https://angular.io/license
2262
- */
2263
- const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2264
- function prioritizedGuardValue() {
2265
- return switchMap(obs => {
2266
- return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2267
- .pipe(scan((acc, list) => {
2268
- let isPending = false;
2269
- return list.reduce((innerAcc, val, i) => {
2270
- if (innerAcc !== INITIAL_VALUE)
2271
- return innerAcc;
2272
- // Toggle pending flag if any values haven't been set yet
2273
- if (val === INITIAL_VALUE)
2274
- isPending = true;
2275
- // Any other return values are only valid if we haven't yet hit a pending
2276
- // call. This guarantees that in the case of a guard at the bottom of the
2277
- // tree that returns a redirect, we will wait for the higher priority
2278
- // guard at the top to finish before performing the redirect.
2279
- if (!isPending) {
2280
- // Early return when we hit a `false` value as that should always
2281
- // cancel navigation
2282
- if (val === false)
2283
- return val;
2284
- if (i === list.length - 1 || isUrlTree(val)) {
2285
- return val;
2286
- }
2287
- }
2288
- return innerAcc;
2289
- }, acc);
2290
- }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2291
- take(1));
2292
- });
2293
- }
2294
-
2295
- /**
2296
- * @license
2297
- * Copyright Google LLC All Rights Reserved.
2298
- *
2299
- * Use of this source code is governed by an MIT-style license that can be
2300
- * found in the LICENSE file at https://angular.io/license
2301
- */
2302
- /**
2303
- * Store contextual information about a `RouterOutlet`
2304
- *
2305
- * @publicApi
2306
- */
2307
- class OutletContext {
2308
- constructor() {
2309
- this.outlet = null;
2310
- this.route = null;
2311
- this.resolver = null;
2312
- this.children = new ChildrenOutletContexts();
2313
- this.attachRef = null;
2314
- }
2315
- }
2316
- /**
2317
- * Store contextual information about the children (= nested) `RouterOutlet`
2318
- *
2319
- * @publicApi
2320
- */
2321
- class ChildrenOutletContexts {
2322
- constructor() {
2323
- // contexts for child outlets, by name.
2324
- this.contexts = new Map();
2325
- }
2326
- /** Called when a `RouterOutlet` directive is instantiated */
2327
- onChildOutletCreated(childName, outlet) {
2328
- const context = this.getOrCreateContext(childName);
2329
- context.outlet = outlet;
2330
- this.contexts.set(childName, context);
2331
- }
2332
- /**
2333
- * Called when a `RouterOutlet` directive is destroyed.
2334
- * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
2335
- * re-created later.
2336
- */
2337
- onChildOutletDestroyed(childName) {
2338
- const context = this.getContext(childName);
2339
- if (context) {
2340
- context.outlet = null;
2341
- context.attachRef = null;
2342
- }
2343
- }
2344
- /**
2345
- * Called when the corresponding route is deactivated during navigation.
2346
- * Because the component get destroyed, all children outlet are destroyed.
2347
- */
2348
- onOutletDeactivated() {
2349
- const contexts = this.contexts;
2350
- this.contexts = new Map();
2351
- return contexts;
2352
- }
2353
- onOutletReAttached(contexts) {
2354
- this.contexts = contexts;
2355
- }
2356
- getOrCreateContext(childName) {
2357
- let context = this.getContext(childName);
2358
- if (!context) {
2359
- context = new OutletContext();
2360
- this.contexts.set(childName, context);
2361
- }
2362
- return context;
2363
- }
2364
- getContext(childName) {
2365
- return this.contexts.get(childName) || null;
2366
- }
2367
- }
2368
-
2369
- /**
2370
- * @license
2371
- * Copyright Google LLC All Rights Reserved.
2372
- *
2373
- * Use of this source code is governed by an MIT-style license that can be
2374
- * found in the LICENSE file at https://angular.io/license
2375
- */
2376
- /**
2377
- * @description
2378
- *
2379
- * Acts as a placeholder that Angular dynamically fills based on the current router state.
2380
- *
2381
- * Each outlet can have a unique name, determined by the optional `name` attribute.
2382
- * The name cannot be set or changed dynamically. If not set, default value is "primary".
2162
+ * Each outlet can have a unique name, determined by the optional `name` attribute.
2163
+ * The name cannot be set or changed dynamically. If not set, default value is "primary".
2383
2164
  *
2384
2165
  * ```
2385
2166
  * <router-outlet></router-outlet>
@@ -2425,11 +2206,11 @@ class ChildrenOutletContexts {
2425
2206
  * @publicApi
2426
2207
  */
2427
2208
  class RouterOutlet {
2428
- constructor(parentContexts, location, resolver, name, changeDetector) {
2209
+ constructor(parentContexts, location, name, changeDetector, environmentInjector) {
2429
2210
  this.parentContexts = parentContexts;
2430
2211
  this.location = location;
2431
- this.resolver = resolver;
2432
2212
  this.changeDetector = changeDetector;
2213
+ this.environmentInjector = environmentInjector;
2433
2214
  this.activated = null;
2434
2215
  this._activatedRoute = null;
2435
2216
  this.activateEvents = new EventEmitter();
@@ -2464,7 +2245,7 @@ class RouterOutlet {
2464
2245
  }
2465
2246
  else {
2466
2247
  // otherwise the component defined in the configuration is created
2467
- this.activateWith(context.route, context.resolver || null);
2248
+ this.activateWith(context.route, context.injector);
2468
2249
  }
2469
2250
  }
2470
2251
  }
@@ -2523,33 +2304,39 @@ class RouterOutlet {
2523
2304
  this.deactivateEvents.emit(c);
2524
2305
  }
2525
2306
  }
2526
- activateWith(activatedRoute, resolver) {
2307
+ activateWith(activatedRoute, resolverOrInjector) {
2527
2308
  if (this.isActivated) {
2528
2309
  throw new Error('Cannot activate an already activated outlet');
2529
2310
  }
2530
2311
  this._activatedRoute = activatedRoute;
2312
+ const location = this.location;
2531
2313
  const snapshot = activatedRoute._futureSnapshot;
2532
- const component = snapshot.routeConfig.component;
2533
- resolver = resolver || this.resolver;
2534
- const factory = resolver.resolveComponentFactory(component);
2314
+ const component = snapshot.component;
2535
2315
  const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
2536
- const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
2537
- this.activated = this.location.createComponent(factory, this.location.length, injector);
2316
+ const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
2317
+ if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
2318
+ const factory = resolverOrInjector.resolveComponentFactory(component);
2319
+ this.activated = location.createComponent(factory, location.length, injector);
2320
+ }
2321
+ else {
2322
+ const environmentInjector = resolverOrInjector ?? this.environmentInjector;
2323
+ this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector });
2324
+ }
2538
2325
  // Calling `markForCheck` to make sure we will run the change detection when the
2539
2326
  // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
2540
2327
  this.changeDetector.markForCheck();
2541
2328
  this.activateEvents.emit(this.activated.instance);
2542
2329
  }
2543
2330
  }
2544
- 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 });
2545
- 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 });
2546
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterOutlet, decorators: [{
2331
+ 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 });
2332
+ 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 });
2333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterOutlet, decorators: [{
2547
2334
  type: Directive,
2548
2335
  args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
2549
- }], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: undefined, decorators: [{
2336
+ }], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
2550
2337
  type: Attribute,
2551
2338
  args: ['name']
2552
- }] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { activateEvents: [{
2339
+ }] }, { type: i0.ChangeDetectorRef }, { type: i0.EnvironmentInjector }]; }, propDecorators: { activateEvents: [{
2553
2340
  type: Output,
2554
2341
  args: ['activate']
2555
2342
  }], deactivateEvents: [{
@@ -2572,10 +2359,388 @@ class OutletInjector {
2572
2359
  if (token === ActivatedRoute) {
2573
2360
  return this.route;
2574
2361
  }
2575
- if (token === ChildrenOutletContexts) {
2576
- return this.childContexts;
2362
+ if (token === ChildrenOutletContexts) {
2363
+ return this.childContexts;
2364
+ }
2365
+ return this.parent.get(token, notFoundValue);
2366
+ }
2367
+ }
2368
+ function isComponentFactoryResolver(item) {
2369
+ return !!item.resolveComponentFactory;
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
+ * This component is used internally within the router to be a placeholder when an empty
2381
+ * router-outlet is needed. For example, with a config such as:
2382
+ *
2383
+ * `{path: 'parent', outlet: 'nav', children: [...]}`
2384
+ *
2385
+ * In order to render, there needs to be a component on this config, which will default
2386
+ * to this `EmptyOutletComponent`.
2387
+ */
2388
+ class ɵEmptyOutletComponent {
2389
+ }
2390
+ ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2391
+ ɵ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"] }] });
2392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2393
+ type: Component,
2394
+ args: [{ template: `<router-outlet></router-outlet>` }]
2395
+ }] });
2396
+
2397
+ /**
2398
+ * @license
2399
+ * Copyright Google LLC All Rights Reserved.
2400
+ *
2401
+ * Use of this source code is governed by an MIT-style license that can be
2402
+ * found in the LICENSE file at https://angular.io/license
2403
+ */
2404
+ function getLoadedRoutes(route) {
2405
+ return route._loadedRoutes;
2406
+ }
2407
+ function getLoadedInjector(route) {
2408
+ return route._loadedInjector;
2409
+ }
2410
+ function getLoadedComponent(route) {
2411
+ return route._loadedComponent;
2412
+ }
2413
+ function getProvidersInjector(route) {
2414
+ return route._injector;
2415
+ }
2416
+ function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
2417
+ // forEach doesn't iterate undefined values
2418
+ for (let i = 0; i < config.length; i++) {
2419
+ const route = config[i];
2420
+ const fullPath = getFullPath(parentPath, route);
2421
+ validateNode(route, fullPath, requireStandaloneComponents);
2422
+ }
2423
+ }
2424
+ function assertStandalone(fullPath, component) {
2425
+ if (component && !ɵisStandalone(component)) {
2426
+ throw new Error(`Invalid configuration of route '${fullPath}'. The component must be standalone.`);
2427
+ }
2428
+ }
2429
+ function validateNode(route, fullPath, requireStandaloneComponents) {
2430
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
2431
+ if (!route) {
2432
+ throw new Error(`
2433
+ Invalid configuration of route '${fullPath}': Encountered undefined route.
2434
+ The reason might be an extra comma.
2435
+
2436
+ Example:
2437
+ const routes: Routes = [
2438
+ { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2439
+ { path: 'dashboard', component: DashboardComponent },, << two commas
2440
+ { path: 'detail/:id', component: HeroDetailComponent }
2441
+ ];
2442
+ `);
2443
+ }
2444
+ if (Array.isArray(route)) {
2445
+ throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2446
+ }
2447
+ if (!route.component && !route.loadComponent && !route.children && !route.loadChildren &&
2448
+ (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2449
+ throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2450
+ }
2451
+ if (route.redirectTo && route.children) {
2452
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2453
+ }
2454
+ if (route.redirectTo && route.loadChildren) {
2455
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2456
+ }
2457
+ if (route.children && route.loadChildren) {
2458
+ throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2459
+ }
2460
+ if (route.redirectTo && (route.component || route.loadComponent)) {
2461
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
2462
+ }
2463
+ if (route.component && route.loadComponent) {
2464
+ throw new Error(`Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
2465
+ }
2466
+ if (route.redirectTo && route.canActivate) {
2467
+ throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2468
+ `so canActivate will never be executed.`);
2469
+ }
2470
+ if (route.path && route.matcher) {
2471
+ throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2472
+ }
2473
+ if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&
2474
+ !route.children && !route.loadChildren) {
2475
+ throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
2476
+ }
2477
+ if (route.path === void 0 && route.matcher === void 0) {
2478
+ throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2479
+ }
2480
+ if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2481
+ throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2482
+ }
2483
+ if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2484
+ const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2485
+ throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2486
+ }
2487
+ if (requireStandaloneComponents) {
2488
+ assertStandalone(fullPath, route.component);
2489
+ }
2490
+ }
2491
+ if (route.children) {
2492
+ validateConfig(route.children, fullPath, requireStandaloneComponents);
2493
+ }
2494
+ }
2495
+ function getFullPath(parentPath, currentRoute) {
2496
+ if (!currentRoute) {
2497
+ return parentPath;
2498
+ }
2499
+ if (!parentPath && !currentRoute.path) {
2500
+ return '';
2501
+ }
2502
+ else if (parentPath && !currentRoute.path) {
2503
+ return `${parentPath}/`;
2504
+ }
2505
+ else if (!parentPath && currentRoute.path) {
2506
+ return currentRoute.path;
2507
+ }
2508
+ else {
2509
+ return `${parentPath}/${currentRoute.path}`;
2510
+ }
2511
+ }
2512
+ /**
2513
+ * Makes a copy of the config and adds any default required properties.
2514
+ */
2515
+ function standardizeConfig(r) {
2516
+ const children = r.children && r.children.map(standardizeConfig);
2517
+ const c = children ? { ...r, children } : { ...r };
2518
+ if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&
2519
+ (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2520
+ c.component = ɵEmptyOutletComponent;
2521
+ }
2522
+ return c;
2523
+ }
2524
+ /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2525
+ function getOutlet(route) {
2526
+ return route.outlet || PRIMARY_OUTLET;
2527
+ }
2528
+ /**
2529
+ * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2530
+ * The order of the configs is otherwise preserved.
2531
+ */
2532
+ function sortByMatchingOutlets(routes, outletName) {
2533
+ const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2534
+ sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2535
+ return sortedConfig;
2536
+ }
2537
+ /**
2538
+ * Gets the first injector in the snapshot's parent tree.
2539
+ *
2540
+ * If the `Route` has a static list of providers, the returned injector will be the one created from
2541
+ * those. If it does not exist, the returned injector may come from the parents, which may be from a
2542
+ * loaded config or their static providers.
2543
+ *
2544
+ * Returns `null` if there is neither this nor any parents have a stored injector.
2545
+ *
2546
+ * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and
2547
+ * also used for getting the correct injector to use for creating components.
2548
+ */
2549
+ function getClosestRouteInjector(snapshot) {
2550
+ if (!snapshot)
2551
+ return null;
2552
+ // If the current route has its own injector, which is created from the static providers on the
2553
+ // route itself, we should use that. Otherwise, we start at the parent since we do not want to
2554
+ // include the lazy loaded injector from this route.
2555
+ if (snapshot.routeConfig?._injector) {
2556
+ return snapshot.routeConfig._injector;
2557
+ }
2558
+ for (let s = snapshot.parent; s; s = s.parent) {
2559
+ const route = s.routeConfig;
2560
+ // Note that the order here is important. `_loadedInjector` stored on the route with
2561
+ // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`
2562
+ // is created from the static providers on that parent route, so it applies to the children as
2563
+ // well, but only if there is no lazy loaded NgModuleRef injector.
2564
+ if (route?._loadedInjector)
2565
+ return route._loadedInjector;
2566
+ if (route?._injector)
2567
+ return route._injector;
2568
+ }
2569
+ return null;
2570
+ }
2571
+
2572
+ /**
2573
+ * @license
2574
+ * Copyright Google LLC All Rights Reserved.
2575
+ *
2576
+ * Use of this source code is governed by an MIT-style license that can be
2577
+ * found in the LICENSE file at https://angular.io/license
2578
+ */
2579
+ const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => map(t => {
2580
+ new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent)
2581
+ .activate(rootContexts);
2582
+ return t;
2583
+ });
2584
+ class ActivateRoutes {
2585
+ constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2586
+ this.routeReuseStrategy = routeReuseStrategy;
2587
+ this.futureState = futureState;
2588
+ this.currState = currState;
2589
+ this.forwardEvent = forwardEvent;
2590
+ }
2591
+ activate(parentContexts) {
2592
+ const futureRoot = this.futureState._root;
2593
+ const currRoot = this.currState ? this.currState._root : null;
2594
+ this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2595
+ advanceActivatedRoute(this.futureState.root);
2596
+ this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2597
+ }
2598
+ // De-activate the child route that are not re-used for the future state
2599
+ deactivateChildRoutes(futureNode, currNode, contexts) {
2600
+ const children = nodeChildrenAsMap(currNode);
2601
+ // Recurse on the routes active in the future state to de-activate deeper children
2602
+ futureNode.children.forEach(futureChild => {
2603
+ const childOutletName = futureChild.value.outlet;
2604
+ this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2605
+ delete children[childOutletName];
2606
+ });
2607
+ // De-activate the routes that will not be re-used
2608
+ forEach(children, (v, childName) => {
2609
+ this.deactivateRouteAndItsChildren(v, contexts);
2610
+ });
2611
+ }
2612
+ deactivateRoutes(futureNode, currNode, parentContext) {
2613
+ const future = futureNode.value;
2614
+ const curr = currNode ? currNode.value : null;
2615
+ if (future === curr) {
2616
+ // Reusing the node, check to see if the children need to be de-activated
2617
+ if (future.component) {
2618
+ // If we have a normal route, we need to go through an outlet.
2619
+ const context = parentContext.getContext(future.outlet);
2620
+ if (context) {
2621
+ this.deactivateChildRoutes(futureNode, currNode, context.children);
2622
+ }
2623
+ }
2624
+ else {
2625
+ // if we have a componentless route, we recurse but keep the same outlet map.
2626
+ this.deactivateChildRoutes(futureNode, currNode, parentContext);
2627
+ }
2628
+ }
2629
+ else {
2630
+ if (curr) {
2631
+ // Deactivate the current route which will not be re-used
2632
+ this.deactivateRouteAndItsChildren(currNode, parentContext);
2633
+ }
2634
+ }
2635
+ }
2636
+ deactivateRouteAndItsChildren(route, parentContexts) {
2637
+ // If there is no component, the Route is never attached to an outlet (because there is no
2638
+ // component to attach).
2639
+ if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
2640
+ this.detachAndStoreRouteSubtree(route, parentContexts);
2641
+ }
2642
+ else {
2643
+ this.deactivateRouteAndOutlet(route, parentContexts);
2644
+ }
2645
+ }
2646
+ detachAndStoreRouteSubtree(route, parentContexts) {
2647
+ const context = parentContexts.getContext(route.value.outlet);
2648
+ const contexts = context && route.value.component ? context.children : parentContexts;
2649
+ const children = nodeChildrenAsMap(route);
2650
+ for (const childOutlet of Object.keys(children)) {
2651
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2652
+ }
2653
+ if (context && context.outlet) {
2654
+ const componentRef = context.outlet.detach();
2655
+ const contexts = context.children.onOutletDeactivated();
2656
+ this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
2657
+ }
2658
+ }
2659
+ deactivateRouteAndOutlet(route, parentContexts) {
2660
+ const context = parentContexts.getContext(route.value.outlet);
2661
+ // The context could be `null` if we are on a componentless route but there may still be
2662
+ // children that need deactivating.
2663
+ const contexts = context && route.value.component ? context.children : parentContexts;
2664
+ const children = nodeChildrenAsMap(route);
2665
+ for (const childOutlet of Object.keys(children)) {
2666
+ this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
2667
+ }
2668
+ if (context && context.outlet) {
2669
+ // Destroy the component
2670
+ context.outlet.deactivate();
2671
+ // Destroy the contexts for all the outlets that were in the component
2672
+ context.children.onOutletDeactivated();
2673
+ // Clear the information about the attached component on the context but keep the reference to
2674
+ // the outlet.
2675
+ context.attachRef = null;
2676
+ context.resolver = null;
2677
+ context.route = null;
2678
+ }
2679
+ }
2680
+ activateChildRoutes(futureNode, currNode, contexts) {
2681
+ const children = nodeChildrenAsMap(currNode);
2682
+ futureNode.children.forEach(c => {
2683
+ this.activateRoutes(c, children[c.value.outlet], contexts);
2684
+ this.forwardEvent(new ActivationEnd(c.value.snapshot));
2685
+ });
2686
+ if (futureNode.children.length) {
2687
+ this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
2688
+ }
2689
+ }
2690
+ activateRoutes(futureNode, currNode, parentContexts) {
2691
+ const future = futureNode.value;
2692
+ const curr = currNode ? currNode.value : null;
2693
+ advanceActivatedRoute(future);
2694
+ // reusing the node
2695
+ if (future === curr) {
2696
+ if (future.component) {
2697
+ // If we have a normal route, we need to go through an outlet.
2698
+ const context = parentContexts.getOrCreateContext(future.outlet);
2699
+ this.activateChildRoutes(futureNode, currNode, context.children);
2700
+ }
2701
+ else {
2702
+ // if we have a componentless route, we recurse but keep the same outlet map.
2703
+ this.activateChildRoutes(futureNode, currNode, parentContexts);
2704
+ }
2705
+ }
2706
+ else {
2707
+ if (future.component) {
2708
+ // if we have a normal route, we need to place the component into the outlet and recurse.
2709
+ const context = parentContexts.getOrCreateContext(future.outlet);
2710
+ if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
2711
+ const stored = this.routeReuseStrategy.retrieve(future.snapshot);
2712
+ this.routeReuseStrategy.store(future.snapshot, null);
2713
+ context.children.onOutletReAttached(stored.contexts);
2714
+ context.attachRef = stored.componentRef;
2715
+ context.route = stored.route.value;
2716
+ if (context.outlet) {
2717
+ // Attach right away when the outlet has already been instantiated
2718
+ // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
2719
+ context.outlet.attach(stored.componentRef, stored.route.value);
2720
+ }
2721
+ advanceActivatedRoute(stored.route.value);
2722
+ this.activateChildRoutes(futureNode, null, context.children);
2723
+ }
2724
+ else {
2725
+ const injector = getClosestRouteInjector(future.snapshot);
2726
+ const cmpFactoryResolver = injector?.get(ComponentFactoryResolver) ?? null;
2727
+ context.attachRef = null;
2728
+ context.route = future;
2729
+ context.resolver = cmpFactoryResolver;
2730
+ context.injector = injector;
2731
+ if (context.outlet) {
2732
+ // Activate the outlet when it has already been instantiated
2733
+ // Otherwise it will get activated from its `ngOnInit` when instantiated
2734
+ context.outlet.activateWith(future, context.injector);
2735
+ }
2736
+ this.activateChildRoutes(futureNode, null, context.children);
2737
+ }
2738
+ }
2739
+ else {
2740
+ // if we have a componentless route, we recurse but keep the same outlet map.
2741
+ this.activateChildRoutes(futureNode, null, parentContexts);
2742
+ }
2577
2743
  }
2578
- return this.parent.get(token, notFoundValue);
2579
2744
  }
2580
2745
  }
2581
2746
 
@@ -2587,22 +2752,39 @@ class OutletInjector {
2587
2752
  * found in the LICENSE file at https://angular.io/license
2588
2753
  */
2589
2754
  /**
2590
- * This component is used internally within the router to be a placeholder when an empty
2591
- * router-outlet is needed. For example, with a config such as:
2755
+ * Simple function check, but generic so type inference will flow. Example:
2592
2756
  *
2593
- * `{path: 'parent', outlet: 'nav', children: [...]}`
2757
+ * function product(a: number, b: number) {
2758
+ * return a * b;
2759
+ * }
2594
2760
  *
2595
- * In order to render, there needs to be a component on this config, which will default
2596
- * to this `EmptyOutletComponent`.
2761
+ * if (isFunction<product>(fn)) {
2762
+ * return fn(1, 2);
2763
+ * } else {
2764
+ * throw "Must provide the `product` function";
2765
+ * }
2597
2766
  */
2598
- class ɵEmptyOutletComponent {
2767
+ function isFunction(v) {
2768
+ return typeof v === 'function';
2769
+ }
2770
+ function isBoolean(v) {
2771
+ return typeof v === 'boolean';
2772
+ }
2773
+ function isUrlTree(v) {
2774
+ return v instanceof UrlTree;
2775
+ }
2776
+ function isCanLoad(guard) {
2777
+ return guard && isFunction(guard.canLoad);
2778
+ }
2779
+ function isCanActivate(guard) {
2780
+ return guard && isFunction(guard.canActivate);
2781
+ }
2782
+ function isCanActivateChild(guard) {
2783
+ return guard && isFunction(guard.canActivateChild);
2784
+ }
2785
+ function isCanDeactivate(guard) {
2786
+ return guard && isFunction(guard.canDeactivate);
2599
2787
  }
2600
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2601
- ɵ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"] }] });
2602
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2603
- type: Component,
2604
- args: [{ template: `<router-outlet></router-outlet>` }]
2605
- }] });
2606
2788
 
2607
2789
  /**
2608
2790
  * @license
@@ -2611,113 +2793,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
2611
2793
  * Use of this source code is governed by an MIT-style license that can be
2612
2794
  * found in the LICENSE file at https://angular.io/license
2613
2795
  */
2614
- function validateConfig(config, parentPath = '') {
2615
- // forEach doesn't iterate undefined values
2616
- for (let i = 0; i < config.length; i++) {
2617
- const route = config[i];
2618
- const fullPath = getFullPath(parentPath, route);
2619
- validateNode(route, fullPath);
2620
- }
2621
- }
2622
- function validateNode(route, fullPath) {
2623
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
2624
- if (!route) {
2625
- throw new Error(`
2626
- Invalid configuration of route '${fullPath}': Encountered undefined route.
2627
- The reason might be an extra comma.
2628
-
2629
- Example:
2630
- const routes: Routes = [
2631
- { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
2632
- { path: 'dashboard', component: DashboardComponent },, << two commas
2633
- { path: 'detail/:id', component: HeroDetailComponent }
2634
- ];
2635
- `);
2636
- }
2637
- if (Array.isArray(route)) {
2638
- throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
2639
- }
2640
- if (!route.component && !route.children && !route.loadChildren &&
2641
- (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
2642
- throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
2643
- }
2644
- if (route.redirectTo && route.children) {
2645
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
2646
- }
2647
- if (route.redirectTo && route.loadChildren) {
2648
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
2649
- }
2650
- if (route.children && route.loadChildren) {
2651
- throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
2652
- }
2653
- if (route.redirectTo && route.component) {
2654
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
2655
- }
2656
- if (route.redirectTo && route.canActivate) {
2657
- throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +
2658
- `so canActivate will never be executed.`);
2659
- }
2660
- if (route.path && route.matcher) {
2661
- throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
2662
- }
2663
- if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
2664
- throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
2665
- }
2666
- if (route.path === void 0 && route.matcher === void 0) {
2667
- throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
2668
- }
2669
- if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
2670
- throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
2671
- }
2672
- if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
2673
- const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
2674
- throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
2675
- }
2676
- }
2677
- if (route.children) {
2678
- validateConfig(route.children, fullPath);
2679
- }
2680
- }
2681
- function getFullPath(parentPath, currentRoute) {
2682
- if (!currentRoute) {
2683
- return parentPath;
2684
- }
2685
- if (!parentPath && !currentRoute.path) {
2686
- return '';
2687
- }
2688
- else if (parentPath && !currentRoute.path) {
2689
- return `${parentPath}/`;
2690
- }
2691
- else if (!parentPath && currentRoute.path) {
2692
- return currentRoute.path;
2693
- }
2694
- else {
2695
- return `${parentPath}/${currentRoute.path}`;
2696
- }
2697
- }
2698
- /**
2699
- * Makes a copy of the config and adds any default required properties.
2700
- */
2701
- function standardizeConfig(r) {
2702
- const children = r.children && r.children.map(standardizeConfig);
2703
- const c = children ? { ...r, children } : { ...r };
2704
- if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
2705
- c.component = ɵEmptyOutletComponent;
2706
- }
2707
- return c;
2708
- }
2709
- /** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */
2710
- function getOutlet(route) {
2711
- return route.outlet || PRIMARY_OUTLET;
2712
- }
2713
- /**
2714
- * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.
2715
- * The order of the configs is otherwise preserved.
2716
- */
2717
- function sortByMatchingOutlets(routes, outletName) {
2718
- const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
2719
- sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
2720
- return sortedConfig;
2796
+ const INITIAL_VALUE = Symbol('INITIAL_VALUE');
2797
+ function prioritizedGuardValue() {
2798
+ return switchMap(obs => {
2799
+ return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE))))
2800
+ .pipe(scan((acc, list) => {
2801
+ let isPending = false;
2802
+ return list.reduce((innerAcc, val, i) => {
2803
+ if (innerAcc !== INITIAL_VALUE)
2804
+ return innerAcc;
2805
+ // Toggle pending flag if any values haven't been set yet
2806
+ if (val === INITIAL_VALUE)
2807
+ isPending = true;
2808
+ // Any other return values are only valid if we haven't yet hit a pending
2809
+ // call. This guarantees that in the case of a guard at the bottom of the
2810
+ // tree that returns a redirect, we will wait for the higher priority
2811
+ // guard at the top to finish before performing the redirect.
2812
+ if (!isPending) {
2813
+ // Early return when we hit a `false` value as that should always
2814
+ // cancel navigation
2815
+ if (val === false)
2816
+ return val;
2817
+ if (i === list.length - 1 || isUrlTree(val)) {
2818
+ return val;
2819
+ }
2820
+ }
2821
+ return innerAcc;
2822
+ }, acc);
2823
+ }, INITIAL_VALUE), filter(item => item !== INITIAL_VALUE), map(item => isUrlTree(item) ? item : item === true), //
2824
+ take(1));
2825
+ });
2721
2826
  }
2722
2827
 
2723
2828
  /**
@@ -2898,17 +3003,17 @@ function canLoadFails(route) {
2898
3003
  *
2899
3004
  * Lazy modules are loaded along the way.
2900
3005
  */
2901
- function applyRedirects$1(moduleInjector, configLoader, urlSerializer, urlTree, config) {
2902
- return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
3006
+ function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) {
3007
+ return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();
2903
3008
  }
2904
3009
  class ApplyRedirects {
2905
- constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
3010
+ constructor(injector, configLoader, urlSerializer, urlTree, config) {
3011
+ this.injector = injector;
2906
3012
  this.configLoader = configLoader;
2907
3013
  this.urlSerializer = urlSerializer;
2908
3014
  this.urlTree = urlTree;
2909
3015
  this.config = config;
2910
3016
  this.allowRedirects = true;
2911
- this.ngModule = moduleInjector.get(NgModuleRef);
2912
3017
  }
2913
3018
  apply() {
2914
3019
  const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
@@ -2919,7 +3024,7 @@ class ApplyRedirects {
2919
3024
  // them. We should be able to remove this logic as a "breaking change" but should do some more
2920
3025
  // investigation into the failures first.
2921
3026
  const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);
2922
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, rootSegmentGroup, PRIMARY_OUTLET);
3027
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
2923
3028
  const urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => {
2924
3029
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);
2925
3030
  }));
@@ -2938,7 +3043,7 @@ class ApplyRedirects {
2938
3043
  }));
2939
3044
  }
2940
3045
  match(tree) {
2941
- const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
3046
+ const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);
2942
3047
  const mapped$ = expanded$.pipe(map((rootSegmentGroup) => {
2943
3048
  return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);
2944
3049
  }));
@@ -2958,15 +3063,15 @@ class ApplyRedirects {
2958
3063
  rootCandidate;
2959
3064
  return new UrlTree(root, queryParams, fragment);
2960
3065
  }
2961
- expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
3066
+ expandSegmentGroup(injector, routes, segmentGroup, outlet) {
2962
3067
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
2963
- return this.expandChildren(ngModule, routes, segmentGroup)
3068
+ return this.expandChildren(injector, routes, segmentGroup)
2964
3069
  .pipe(map((children) => new UrlSegmentGroup([], children)));
2965
3070
  }
2966
- return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
3071
+ return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);
2967
3072
  }
2968
3073
  // Recursively expand segment groups for all the child outlets
2969
- expandChildren(ngModule, routes, segmentGroup) {
3074
+ expandChildren(injector, routes, segmentGroup) {
2970
3075
  // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
2971
3076
  // because an absolute redirect from the primary outlet takes precedence.
2972
3077
  const childOutlets = [];
@@ -2985,16 +3090,25 @@ class ApplyRedirects {
2985
3090
  // first, followed by routes for other outlets, which might match if they have an
2986
3091
  // empty path.
2987
3092
  const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);
2988
- return this.expandSegmentGroup(ngModule, sortedRoutes, child, childOutlet)
3093
+ return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)
2989
3094
  .pipe(map(s => ({ segment: s, outlet: childOutlet })));
2990
3095
  }), scan((children, expandedChild) => {
2991
3096
  children[expandedChild.outlet] = expandedChild.segment;
2992
3097
  return children;
2993
3098
  }, {}), last$1());
2994
3099
  }
2995
- expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
2996
- return from(routes).pipe(concatMap((r) => {
2997
- const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
3100
+ expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) {
3101
+ return from(routes).pipe(concatMap(r => {
3102
+ if (r.providers && !r._injector) {
3103
+ r._injector = createEnvironmentInjector(r.providers, injector, `Route: ${r.path}`);
3104
+ }
3105
+ // We specifically _do not_ want to include the _loadedInjector here. The loaded injector
3106
+ // only applies to the route's children, not the route itself. Note that this distinction
3107
+ // only applies here to any tokens we try to retrieve during this phase. At the moment,
3108
+ // that only includes `canLoad`, which won't run again once the child module is loaded. As
3109
+ // a result, this makes no difference right now, but could in the future if there are more
3110
+ // actions here that need DI (for example, a canMatch guard).
3111
+ const expanded$ = this.expandSegmentAgainstRoute(r._injector ?? injector, segmentGroup, routes, r, segments, outlet, allowRedirects);
2998
3112
  return expanded$.pipe(catchError((e) => {
2999
3113
  if (e instanceof NoMatch$1) {
3000
3114
  return of(null);
@@ -3011,35 +3125,35 @@ class ApplyRedirects {
3011
3125
  throw e;
3012
3126
  }));
3013
3127
  }
3014
- expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3128
+ expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3015
3129
  if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {
3016
3130
  return noMatch(segmentGroup);
3017
3131
  }
3018
3132
  if (route.redirectTo === undefined) {
3019
- return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths, outlet);
3133
+ return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);
3020
3134
  }
3021
3135
  if (allowRedirects && this.allowRedirects) {
3022
- return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
3136
+ return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet);
3023
3137
  }
3024
3138
  return noMatch(segmentGroup);
3025
3139
  }
3026
- expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3140
+ expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3027
3141
  if (route.path === '**') {
3028
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
3142
+ return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3029
3143
  }
3030
- return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
3144
+ return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3031
3145
  }
3032
- expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
3146
+ expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3033
3147
  const newTree = this.applyRedirectCommands([], route.redirectTo, {});
3034
3148
  if (route.redirectTo.startsWith('/')) {
3035
3149
  return absoluteRedirect(newTree);
3036
3150
  }
3037
3151
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3038
3152
  const group = new UrlSegmentGroup(newSegments, {});
3039
- return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
3153
+ return this.expandSegment(injector, group, routes, newSegments, outlet, false);
3040
3154
  }));
3041
3155
  }
3042
- expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3156
+ expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3043
3157
  const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3044
3158
  if (!matched)
3045
3159
  return noMatch(segmentGroup);
@@ -3048,16 +3162,18 @@ class ApplyRedirects {
3048
3162
  return absoluteRedirect(newTree);
3049
3163
  }
3050
3164
  return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
3051
- return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3165
+ return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);
3052
3166
  }));
3053
3167
  }
3054
- matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments, outlet) {
3168
+ matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) {
3055
3169
  if (route.path === '**') {
3056
3170
  if (route.loadChildren) {
3057
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
3058
- this.configLoader.load(ngModule.injector, route);
3171
+ const loaded$ = route._loadedRoutes ?
3172
+ of({ routes: route._loadedRoutes, injector: route._loadedInjector }) :
3173
+ this.configLoader.loadChildren(injector, route);
3059
3174
  return loaded$.pipe(map((cfg) => {
3060
- route._loadedConfig = cfg;
3175
+ route._loadedRoutes = cfg.routes;
3176
+ route._loadedInjector = cfg.injector;
3061
3177
  return new UrlSegmentGroup(segments, {});
3062
3178
  }));
3063
3179
  }
@@ -3066,55 +3182,55 @@ class ApplyRedirects {
3066
3182
  const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
3067
3183
  if (!matched)
3068
3184
  return noMatch(rawSegmentGroup);
3069
- const childConfig$ = this.getChildConfig(ngModule, route, segments);
3185
+ const childConfig$ = this.getChildConfig(injector, route, segments);
3070
3186
  return childConfig$.pipe(mergeMap((routerConfig) => {
3071
- const childModule = routerConfig.module;
3187
+ const childInjector = routerConfig.injector ?? injector;
3072
3188
  const childConfig = routerConfig.routes;
3073
3189
  const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3074
3190
  // See comment on the other call to `split` about why this is necessary.
3075
3191
  const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3076
3192
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3077
- const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
3193
+ const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3078
3194
  return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3079
3195
  }
3080
3196
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3081
3197
  return of(new UrlSegmentGroup(consumedSegments, {}));
3082
3198
  }
3083
3199
  const matchedOnOutlet = getOutlet(route) === outlet;
3084
- const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3200
+ const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3085
3201
  return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3086
3202
  }));
3087
3203
  }
3088
- getChildConfig(ngModule, route, segments) {
3204
+ getChildConfig(injector, route, segments) {
3089
3205
  if (route.children) {
3090
3206
  // The children belong to the same module
3091
- return of(new LoadedRouterConfig(route.children, ngModule));
3207
+ return of({ routes: route.children, injector });
3092
3208
  }
3093
3209
  if (route.loadChildren) {
3094
3210
  // lazy children belong to the loaded module
3095
- if (route._loadedConfig !== undefined) {
3096
- return of(route._loadedConfig);
3211
+ if (route._loadedRoutes !== undefined) {
3212
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3097
3213
  }
3098
- return this.runCanLoadGuards(ngModule.injector, route, segments)
3214
+ return this.runCanLoadGuards(injector, route, segments)
3099
3215
  .pipe(mergeMap((shouldLoadResult) => {
3100
3216
  if (shouldLoadResult) {
3101
- return this.configLoader.load(ngModule.injector, route)
3102
- .pipe(map((cfg) => {
3103
- route._loadedConfig = cfg;
3104
- return cfg;
3217
+ return this.configLoader.loadChildren(injector, route)
3218
+ .pipe(tap((cfg) => {
3219
+ route._loadedRoutes = cfg.routes;
3220
+ route._loadedInjector = cfg.injector;
3105
3221
  }));
3106
3222
  }
3107
3223
  return canLoadFails(route);
3108
3224
  }));
3109
3225
  }
3110
- return of(new LoadedRouterConfig([], ngModule));
3226
+ return of({ routes: [], injector });
3111
3227
  }
3112
- runCanLoadGuards(moduleInjector, route, segments) {
3228
+ runCanLoadGuards(injector, route, segments) {
3113
3229
  const canLoad = route.canLoad;
3114
3230
  if (!canLoad || canLoad.length === 0)
3115
3231
  return of(true);
3116
3232
  const canLoadObservables = canLoad.map((injectionToken) => {
3117
- const guard = moduleInjector.get(injectionToken);
3233
+ const guard = injector.get(injectionToken);
3118
3234
  let guardVal;
3119
3235
  if (isCanLoad(guard)) {
3120
3236
  guardVal = guard.canLoad(route, segments);
@@ -3242,8 +3358,8 @@ function squashSegmentGroup(segmentGroup) {
3242
3358
  * Use of this source code is governed by an MIT-style license that can be
3243
3359
  * found in the LICENSE file at https://angular.io/license
3244
3360
  */
3245
- function applyRedirects(moduleInjector, configLoader, urlSerializer, config) {
3246
- return switchMap(t => applyRedirects$1(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
3361
+ function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3362
+ return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3247
3363
  .pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
3248
3364
  }
3249
3365
 
@@ -3277,21 +3393,11 @@ function getCanActivateChild(p) {
3277
3393
  return null;
3278
3394
  return { node: p, guards: canActivateChild };
3279
3395
  }
3280
- function getToken(token, snapshot, moduleInjector) {
3281
- const config = getClosestLoadedConfig(snapshot);
3282
- const injector = config ? config.module.injector : moduleInjector;
3396
+ function getToken(token, snapshot, fallbackInjector) {
3397
+ const routeInjector = getClosestRouteInjector(snapshot);
3398
+ const injector = routeInjector ?? fallbackInjector;
3283
3399
  return injector.get(token);
3284
3400
  }
3285
- function getClosestLoadedConfig(snapshot) {
3286
- if (!snapshot)
3287
- return null;
3288
- for (let s = snapshot.parent; s; s = s.parent) {
3289
- const route = s.routeConfig;
3290
- if (route && route._loadedConfig)
3291
- return route._loadedConfig;
3292
- }
3293
- return null;
3294
- }
3295
3401
  function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
3296
3402
  canDeactivateChecks: [],
3297
3403
  canActivateChecks: []
@@ -3535,7 +3641,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
3535
3641
  * Use of this source code is governed by an MIT-style license that can be
3536
3642
  * found in the LICENSE file at https://angular.io/license
3537
3643
  */
3538
- const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
3644
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3539
3645
  class NoMatch {
3540
3646
  }
3541
3647
  function newObservableError(e) {
@@ -3652,11 +3758,11 @@ class Recognizer {
3652
3758
  if (route.path === '**') {
3653
3759
  const params = segments.length > 0 ? last(segments).parameters : {};
3654
3760
  const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
3655
- snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
3761
+ snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route),
3656
3762
  // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
3657
3763
  // production bundle size. This value is intended only to surface a warning to users
3658
3764
  // depending on `relativeLinkResolution: 'legacy'` in dev mode.
3659
- (NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3765
+ (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3660
3766
  pathIndexShift));
3661
3767
  }
3662
3768
  else {
@@ -3667,7 +3773,7 @@ class Recognizer {
3667
3773
  consumedSegments = result.consumedSegments;
3668
3774
  remainingSegments = result.remainingSegments;
3669
3775
  const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3670
- snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze({ ...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 :
3776
+ snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
3671
3777
  pathIndexShift));
3672
3778
  }
3673
3779
  const childConfig = getChildConfig(route);
@@ -3716,7 +3822,7 @@ function getChildConfig(route) {
3716
3822
  return route.children;
3717
3823
  }
3718
3824
  if (route.loadChildren) {
3719
- return route._loadedConfig.routes;
3825
+ return route._loadedRoutes;
3720
3826
  }
3721
3827
  return [];
3722
3828
  }
@@ -3860,16 +3966,9 @@ function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
3860
3966
  }
3861
3967
  const data = {};
3862
3968
  return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
3863
- .pipe(take(1), tap((value) => {
3969
+ .pipe(first(), tap((value) => {
3864
3970
  data[key] = value;
3865
- }))), takeLast(1), mergeMap(() => {
3866
- // Ensure all resolvers returned values, otherwise don't emit any "next" and just complete
3867
- // the chain which will cancel navigation
3868
- if (getDataKeys(data).length === keys.length) {
3869
- return of(data);
3870
- }
3871
- return EMPTY;
3872
- }));
3971
+ }))), takeLast(1), mapTo(data), catchError((e) => e instanceof EmptyError ? EMPTY : throwError(e)));
3873
3972
  }
3874
3973
  function getDataKeys(obj) {
3875
3974
  return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
@@ -3978,6 +4077,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3978
4077
  * Use of this source code is governed by an MIT-style license that can be
3979
4078
  * found in the LICENSE file at https://angular.io/license
3980
4079
  */
4080
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3981
4081
  /**
3982
4082
  * The [DI token](guide/glossary/#di-token) for a router configuration.
3983
4083
  *
@@ -3990,43 +4090,84 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
3990
4090
  */
3991
4091
  const ROUTES = new InjectionToken('ROUTES');
3992
4092
  class RouterConfigLoader {
3993
- constructor(injector, compiler, onLoadStartListener, onLoadEndListener) {
4093
+ constructor(injector, compiler) {
3994
4094
  this.injector = injector;
3995
4095
  this.compiler = compiler;
3996
- this.onLoadStartListener = onLoadStartListener;
3997
- this.onLoadEndListener = onLoadEndListener;
4096
+ this.componentLoaders = new WeakMap();
4097
+ this.childrenLoaders = new WeakMap();
4098
+ }
4099
+ loadComponent(route) {
4100
+ if (this.componentLoaders.get(route)) {
4101
+ return this.componentLoaders.get(route);
4102
+ }
4103
+ else if (route._loadedComponent) {
4104
+ return of(route._loadedComponent);
4105
+ }
4106
+ if (this.onLoadStartListener) {
4107
+ this.onLoadStartListener(route);
4108
+ }
4109
+ const loadRunner = wrapIntoObservable(route.loadComponent())
4110
+ .pipe(tap(component => {
4111
+ if (this.onLoadEndListener) {
4112
+ this.onLoadEndListener(route);
4113
+ }
4114
+ NG_DEV_MODE$1 && assertStandalone(route.path ?? '', component);
4115
+ route._loadedComponent = component;
4116
+ }), finalize(() => {
4117
+ this.componentLoaders.delete(route);
4118
+ }));
4119
+ // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
4120
+ const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
4121
+ this.componentLoaders.set(route, loader);
4122
+ return loader;
3998
4123
  }
3999
- load(parentInjector, route) {
4000
- if (route._loader$) {
4001
- return route._loader$;
4124
+ loadChildren(parentInjector, route) {
4125
+ if (this.childrenLoaders.get(route)) {
4126
+ return this.childrenLoaders.get(route);
4127
+ }
4128
+ else if (route._loadedRoutes) {
4129
+ return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
4002
4130
  }
4003
4131
  if (this.onLoadStartListener) {
4004
4132
  this.onLoadStartListener(route);
4005
4133
  }
4006
- const moduleFactory$ = this.loadModuleFactory(route.loadChildren);
4007
- const loadRunner = moduleFactory$.pipe(map((factory) => {
4134
+ const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren);
4135
+ const loadRunner = moduleFactoryOrRoutes$.pipe(map((factoryOrRoutes) => {
4008
4136
  if (this.onLoadEndListener) {
4009
4137
  this.onLoadEndListener(route);
4010
4138
  }
4011
- const module = factory.create(parentInjector);
4012
- // When loading a module that doesn't provide `RouterModule.forChild()` preloader
4013
- // will get stuck in an infinite loop. The child module's Injector will look to
4014
- // its parent `Injector` when it doesn't find any ROUTES so it will return routes
4015
- // for it's parent module instead.
4016
- return new LoadedRouterConfig(flatten(module.injector.get(ROUTES, undefined, InjectFlags.Self | InjectFlags.Optional))
4017
- .map(standardizeConfig), module);
4018
- }), catchError((err) => {
4019
- route._loader$ = undefined;
4020
- throw err;
4139
+ // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no
4140
+ // injector associated with lazy loading a `Route` array.
4141
+ let injector;
4142
+ let rawRoutes;
4143
+ let requireStandaloneComponents = false;
4144
+ if (Array.isArray(factoryOrRoutes)) {
4145
+ rawRoutes = factoryOrRoutes;
4146
+ requireStandaloneComponents = true;
4147
+ }
4148
+ else {
4149
+ injector = factoryOrRoutes.create(parentInjector).injector;
4150
+ // When loading a module that doesn't provide `RouterModule.forChild()` preloader
4151
+ // will get stuck in an infinite loop. The child module's Injector will look to
4152
+ // its parent `Injector` when it doesn't find any ROUTES so it will return routes
4153
+ // for it's parent module instead.
4154
+ rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
4155
+ }
4156
+ const routes = rawRoutes.map(standardizeConfig);
4157
+ NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
4158
+ return { routes, injector };
4159
+ }), finalize(() => {
4160
+ this.childrenLoaders.delete(route);
4021
4161
  }));
4022
4162
  // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much
4023
- route._loader$ = new ConnectableObservable(loadRunner, () => new Subject())
4163
+ const loader = new ConnectableObservable(loadRunner, () => new Subject())
4024
4164
  .pipe(refCount());
4025
- return route._loader$;
4165
+ this.childrenLoaders.set(route, loader);
4166
+ return loader;
4026
4167
  }
4027
- loadModuleFactory(loadChildren) {
4168
+ loadModuleFactoryOrRoutes(loadChildren) {
4028
4169
  return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => {
4029
- if (t instanceof NgModuleFactory) {
4170
+ if (t instanceof NgModuleFactory || Array.isArray(t)) {
4030
4171
  return of(t);
4031
4172
  }
4032
4173
  else {
@@ -4035,6 +4176,11 @@ class RouterConfigLoader {
4035
4176
  }));
4036
4177
  }
4037
4178
  }
4179
+ 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 });
4180
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterConfigLoader });
4181
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterConfigLoader, decorators: [{
4182
+ type: Injectable
4183
+ }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
4038
4184
 
4039
4185
  /**
4040
4186
  * @license
@@ -4074,6 +4220,7 @@ class DefaultUrlHandlingStrategy {
4074
4220
  * Use of this source code is governed by an MIT-style license that can be
4075
4221
  * found in the LICENSE file at https://angular.io/license
4076
4222
  */
4223
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
4077
4224
  function defaultErrorHandler(error) {
4078
4225
  throw error;
4079
4226
  }
@@ -4245,6 +4392,9 @@ class Router {
4245
4392
  this.canceledNavigationResolution = 'replace';
4246
4393
  const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
4247
4394
  const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
4395
+ this.configLoader = injector.get(RouterConfigLoader);
4396
+ this.configLoader.onLoadEndListener = onLoadEnd;
4397
+ this.configLoader.onLoadStartListener = onLoadStart;
4248
4398
  this.ngModule = injector.get(NgModuleRef);
4249
4399
  this.console = injector.get(ɵConsole);
4250
4400
  const ngZone = injector.get(NgZone);
@@ -4253,7 +4403,6 @@ class Router {
4253
4403
  this.currentUrlTree = createEmptyUrlTree();
4254
4404
  this.rawUrlTree = this.currentUrlTree;
4255
4405
  this.browserUrlTree = this.currentUrlTree;
4256
- this.configLoader = new RouterConfigLoader(injector, compiler, onLoadStart, onLoadEnd);
4257
4406
  this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4258
4407
  this.transitions = new BehaviorSubject({
4259
4408
  id: 0,
@@ -4462,6 +4611,25 @@ class Router {
4462
4611
  skipLocationChange: !!skipLocationChange,
4463
4612
  replaceUrl: !!replaceUrl,
4464
4613
  });
4614
+ }),
4615
+ // --- LOAD COMPONENTS ---
4616
+ switchTap((t) => {
4617
+ const loadComponents = (route) => {
4618
+ const loaders = [];
4619
+ if (route.routeConfig?.loadComponent &&
4620
+ !route.routeConfig._loadedComponent) {
4621
+ loaders.push(this.configLoader.loadComponent(route.routeConfig)
4622
+ .pipe(tap(loadedComponent => {
4623
+ route.component = loadedComponent;
4624
+ }), map(() => void 0)));
4625
+ }
4626
+ for (const child of route.children) {
4627
+ loaders.push(...loadComponents(child));
4628
+ }
4629
+ return loaders;
4630
+ };
4631
+ return combineLatest(loadComponents(t.targetSnapshot.root))
4632
+ .pipe(defaultIfEmpty(), take(1));
4465
4633
  }), map((t) => {
4466
4634
  const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4467
4635
  return ({ ...t, targetRouterState });
@@ -4540,23 +4708,17 @@ class Router {
4540
4708
  t.resolve(false);
4541
4709
  }
4542
4710
  else {
4543
- // setTimeout is required so this navigation finishes with
4544
- // the return EMPTY below. If it isn't allowed to finish
4545
- // processing, there can be multiple navigations to the same
4546
- // URL.
4547
- setTimeout(() => {
4548
- const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4549
- const extras = {
4550
- skipLocationChange: t.extras.skipLocationChange,
4551
- // The URL is already updated at this point if we have 'eager' URL
4552
- // updates or if the navigation was triggered by the browser (back
4553
- // button, URL bar, etc). We want to replace that item in history if
4554
- // the navigation is rejected.
4555
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
4556
- isBrowserTriggeredNavigation(t.source)
4557
- };
4558
- this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4559
- }, 0);
4711
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
4712
+ const extras = {
4713
+ skipLocationChange: t.extras.skipLocationChange,
4714
+ // The URL is already updated at this point if we have 'eager' URL
4715
+ // updates or if the navigation was triggered by the browser (back
4716
+ // button, URL bar, etc). We want to replace that item in history if
4717
+ // the navigation is rejected.
4718
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
4719
+ isBrowserTriggeredNavigation(t.source)
4720
+ };
4721
+ this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
4560
4722
  }
4561
4723
  /* All other errors should reset to the router's internal URL reference to
4562
4724
  * the pre-error state. */
@@ -4666,7 +4828,7 @@ class Router {
4666
4828
  * ```
4667
4829
  */
4668
4830
  resetConfig(config) {
4669
- validateConfig(config);
4831
+ NG_DEV_MODE && validateConfig(config);
4670
4832
  this.config = config.map(standardizeConfig);
4671
4833
  this.navigated = false;
4672
4834
  this.lastSuccessfulId = -1;
@@ -5021,9 +5183,9 @@ class Router {
5021
5183
  return { navigationId };
5022
5184
  }
5023
5185
  }
5024
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5025
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router });
5026
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: Router, decorators: [{
5186
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5187
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router });
5188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: Router, decorators: [{
5027
5189
  type: Injectable
5028
5190
  }], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
5029
5191
  function validateCommands(commands) {
@@ -5222,9 +5384,9 @@ class RouterLink {
5222
5384
  });
5223
5385
  }
5224
5386
  }
5225
- 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 });
5226
- 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 });
5227
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLink, decorators: [{
5387
+ 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 });
5388
+ 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 });
5389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLink, decorators: [{
5228
5390
  type: Directive,
5229
5391
  args: [{ selector: ':not(a):not(area)[routerLink]' }]
5230
5392
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
@@ -5341,9 +5503,9 @@ class RouterLinkWithHref {
5341
5503
  });
5342
5504
  }
5343
5505
  }
5344
- 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 });
5345
- 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 });
5346
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5506
+ 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 });
5507
+ 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 });
5508
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5347
5509
  type: Directive,
5348
5510
  args: [{ selector: 'a[routerLink],area[routerLink]' }]
5349
5511
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
@@ -5440,6 +5602,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
5440
5602
  * </div>
5441
5603
  * ```
5442
5604
  *
5605
+ * The `RouterLinkActive` directive can also be used to set the aria-current attribute
5606
+ * to provide an alternative distinction for active elements to visually impaired users.
5607
+ *
5608
+ * For example, the following code adds the 'active' class to the Home Page link when it is
5609
+ * indeed active and in such case also sets its aria-current attribute to 'page':
5610
+ *
5611
+ * ```
5612
+ * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
5613
+ * ```
5614
+ *
5443
5615
  * @ngModule RouterModule
5444
5616
  *
5445
5617
  * @publicApi
@@ -5533,6 +5705,12 @@ class RouterLinkActive {
5533
5705
  this.renderer.removeClass(this.element.nativeElement, c);
5534
5706
  }
5535
5707
  });
5708
+ if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
5709
+ this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
5710
+ }
5711
+ else {
5712
+ this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
5713
+ }
5536
5714
  // Emit on isActiveChange after classes are updated
5537
5715
  this.isActiveChange.emit(hasActiveLinks);
5538
5716
  }
@@ -5552,9 +5730,9 @@ class RouterLinkActive {
5552
5730
  this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
5553
5731
  }
5554
5732
  }
5555
- 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 });
5556
- 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 });
5557
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterLinkActive, decorators: [{
5733
+ 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 });
5734
+ 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 });
5735
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterLinkActive, decorators: [{
5558
5736
  type: Directive,
5559
5737
  args: [{
5560
5738
  selector: '[routerLinkActive]',
@@ -5572,6 +5750,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13",
5572
5750
  args: [RouterLinkWithHref, { descendants: true }]
5573
5751
  }], routerLinkActiveOptions: [{
5574
5752
  type: Input
5753
+ }], ariaCurrentWhenActive: [{
5754
+ type: Input
5575
5755
  }], isActiveChange: [{
5576
5756
  type: Output
5577
5757
  }], routerLinkActive: [{
@@ -5655,9 +5835,9 @@ class DefaultTitleStrategy extends TitleStrategy {
5655
5835
  }
5656
5836
  }
5657
5837
  }
5658
- 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 });
5659
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5660
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5838
+ 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 });
5839
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5661
5841
  type: Injectable,
5662
5842
  args: [{ providedIn: 'root' }]
5663
5843
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -5721,13 +5901,11 @@ class NoPreloading {
5721
5901
  * @publicApi
5722
5902
  */
5723
5903
  class RouterPreloader {
5724
- constructor(router, compiler, injector, preloadingStrategy) {
5904
+ constructor(router, compiler, injector, preloadingStrategy, loader) {
5725
5905
  this.router = router;
5726
5906
  this.injector = injector;
5727
5907
  this.preloadingStrategy = preloadingStrategy;
5728
- const onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r));
5729
- const onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r));
5730
- this.loader = new RouterConfigLoader(injector, compiler, onStartLoad, onEndLoad);
5908
+ this.loader = loader;
5731
5909
  }
5732
5910
  setUpPreloading() {
5733
5911
  this.subscription =
@@ -5736,8 +5914,7 @@ class RouterPreloader {
5736
5914
  .subscribe(() => { });
5737
5915
  }
5738
5916
  preload() {
5739
- const ngModule = this.injector.get(NgModuleRef);
5740
- return this.processRoutes(ngModule, this.router.config);
5917
+ return this.processRoutes(this.injector, this.router.config);
5741
5918
  }
5742
5919
  /** @nodoc */
5743
5920
  ngOnDestroy() {
@@ -5745,41 +5922,59 @@ class RouterPreloader {
5745
5922
  this.subscription.unsubscribe();
5746
5923
  }
5747
5924
  }
5748
- processRoutes(ngModule, routes) {
5925
+ processRoutes(injector, routes) {
5749
5926
  const res = [];
5750
5927
  for (const route of routes) {
5751
- // we already have the config loaded, just recurse
5752
- if (route.loadChildren && !route.canLoad && route._loadedConfig) {
5753
- const childConfig = route._loadedConfig;
5754
- res.push(this.processRoutes(childConfig.module, childConfig.routes));
5755
- // no config loaded, fetch the config
5928
+ if (route.providers && !route._injector) {
5929
+ route._injector =
5930
+ createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
5756
5931
  }
5757
- else if (route.loadChildren && !route.canLoad) {
5758
- res.push(this.preloadConfig(ngModule, route));
5759
- // recurse into children
5932
+ const injectorForCurrentRoute = route._injector ?? injector;
5933
+ const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
5934
+ if ((route.loadChildren && !route._loadedRoutes) ||
5935
+ (route.loadComponent && !route._loadedComponent)) {
5936
+ res.push(this.preloadConfig(injectorForCurrentRoute, route));
5760
5937
  }
5761
- else if (route.children) {
5762
- res.push(this.processRoutes(ngModule, route.children));
5938
+ else if (route.children || route._loadedRoutes) {
5939
+ res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
5763
5940
  }
5764
5941
  }
5765
- return from(res).pipe(mergeAll(), map((_) => void 0));
5942
+ return from(res).pipe(mergeAll());
5766
5943
  }
5767
- preloadConfig(ngModule, route) {
5944
+ preloadConfig(injector, route) {
5768
5945
  return this.preloadingStrategy.preload(route, () => {
5769
- const loaded$ = route._loadedConfig ? of(route._loadedConfig) :
5770
- this.loader.load(ngModule.injector, route);
5771
- return loaded$.pipe(mergeMap((config) => {
5772
- route._loadedConfig = config;
5773
- return this.processRoutes(config.module, config.routes);
5946
+ let loadedChildren$;
5947
+ if (route.loadChildren && route.canLoad === undefined) {
5948
+ loadedChildren$ = this.loader.loadChildren(injector, route);
5949
+ }
5950
+ else {
5951
+ loadedChildren$ = of(null);
5952
+ }
5953
+ const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
5954
+ if (config === null) {
5955
+ return of(void 0);
5956
+ }
5957
+ route._loadedRoutes = config.routes;
5958
+ route._loadedInjector = config.injector;
5959
+ // If the loaded config was a module, use that as the module/module injector going
5960
+ // forward. Otherwise, continue using the current module/module injector.
5961
+ return this.processRoutes(config.injector ?? injector, config.routes);
5774
5962
  }));
5963
+ if (route.loadComponent && !route._loadedComponent) {
5964
+ const loadComponent$ = this.loader.loadComponent(route);
5965
+ return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
5966
+ }
5967
+ else {
5968
+ return recursiveLoadChildren$;
5969
+ }
5775
5970
  });
5776
5971
  }
5777
5972
  }
5778
- 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 });
5779
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterPreloader });
5780
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterPreloader, decorators: [{
5973
+ 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 });
5974
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterPreloader });
5975
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterPreloader, decorators: [{
5781
5976
  type: Injectable
5782
- }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.Injector }, { type: PreloadingStrategy }]; } });
5977
+ }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
5783
5978
 
5784
5979
  /**
5785
5980
  * @license
@@ -5863,9 +6058,9 @@ class RouterScroller {
5863
6058
  }
5864
6059
  }
5865
6060
  }
5866
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5867
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller });
5868
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterScroller, decorators: [{
6061
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6062
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller });
6063
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterScroller, decorators: [{
5869
6064
  type: Injectable
5870
6065
  }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
5871
6066
 
@@ -5908,6 +6103,7 @@ const ROUTER_PROVIDERS = [
5908
6103
  NoPreloading,
5909
6104
  PreloadAllModules,
5910
6105
  { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
6106
+ RouterConfigLoader,
5911
6107
  ];
5912
6108
  function routerNgProbeToken() {
5913
6109
  return new NgProbeToken('Router', Router);
@@ -6006,10 +6202,10 @@ class RouterModule {
6006
6202
  return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
6007
6203
  }
6008
6204
  }
6009
- 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 });
6010
- 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] });
6011
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule });
6012
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterModule, decorators: [{
6205
+ 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 });
6206
+ 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] });
6207
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule });
6208
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.16", ngImport: i0, type: RouterModule, decorators: [{
6013
6209
  type: NgModule,
6014
6210
  args: [{
6015
6211
  declarations: ROUTER_DIRECTIVES,
@@ -6071,11 +6267,11 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
6071
6267
  }
6072
6268
  router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
6073
6269
  assignExtraOptionsToRouter(opts, router);
6074
- if (opts.enableTracing) {
6270
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
6075
6271
  router.events.subscribe((e) => {
6076
6272
  // tslint:disable:no-console
6077
6273
  console.group?.(`Router Event: ${e.constructor.name}`);
6078
- console.log(e.toString());
6274
+ console.log(stringifyEvent(e));
6079
6275
  console.log(e);
6080
6276
  console.groupEnd?.();
6081
6277
  // tslint:enable:no-console
@@ -6142,9 +6338,7 @@ class RouterInitializer {
6142
6338
  router.setUpLocationChangeListener();
6143
6339
  resolve(true);
6144
6340
  }
6145
- else if (
6146
- // TODO: enabled is deprecated as of v11, can be removed in v13
6147
- opts.initialNavigation === 'enabled' || opts.initialNavigation === 'enabledBlocking') {
6341
+ else if (opts.initialNavigation === 'enabledBlocking') {
6148
6342
  router.hooks.afterPreactivation = () => {
6149
6343
  // only the initial navigation should be delayed
6150
6344
  if (!this.initNavigation) {
@@ -6188,9 +6382,9 @@ class RouterInitializer {
6188
6382
  this.destroyed = true;
6189
6383
  }
6190
6384
  }
6191
- 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 });
6192
- RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.13", ngImport: i0, type: RouterInitializer });
6193
- 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: [{
6194
6388
  type: Injectable
6195
6389
  }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
6196
6390
  function getAppInitializer(r) {
@@ -6230,7 +6424,7 @@ function provideRouterInitializer() {
6230
6424
  /**
6231
6425
  * @publicApi
6232
6426
  */
6233
- const VERSION = new Version('14.0.0-next.13');
6427
+ const VERSION = new Version('14.0.0-next.16');
6234
6428
 
6235
6429
  /**
6236
6430
  * @license