@angular/router 14.1.0-next.0 → 14.1.0-next.3

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 (35) hide show
  1. package/esm2020/src/apply_redirects.mjs +30 -56
  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 +3 -3
  5. package/esm2020/src/directives/router_outlet.mjs +8 -5
  6. package/esm2020/src/index.mjs +1 -1
  7. package/esm2020/src/models.mjs +1 -1
  8. package/esm2020/src/operators/check_guards.mjs +48 -4
  9. package/esm2020/src/operators/recognize.mjs +3 -3
  10. package/esm2020/src/page_title_strategy.mjs +3 -3
  11. package/esm2020/src/private_export.mjs +2 -2
  12. package/esm2020/src/recognize.mjs +133 -110
  13. package/esm2020/src/router.mjs +8 -37
  14. package/esm2020/src/router_config_loader.mjs +3 -3
  15. package/esm2020/src/router_module.mjs +151 -136
  16. package/esm2020/src/router_preloader.mjs +16 -4
  17. package/esm2020/src/router_scroller.mjs +6 -5
  18. package/esm2020/src/utils/config_matching.mjs +16 -2
  19. package/esm2020/src/utils/type_guards.mjs +4 -1
  20. package/esm2020/src/version.mjs +1 -1
  21. package/esm2020/testing/src/router_testing_module.mjs +8 -8
  22. package/fesm2015/router.mjs +840 -778
  23. package/fesm2015/router.mjs.map +1 -1
  24. package/fesm2015/testing.mjs +8 -8
  25. package/fesm2015/testing.mjs.map +1 -1
  26. package/fesm2015/upgrade.mjs +1 -1
  27. package/fesm2020/router.mjs +835 -779
  28. package/fesm2020/router.mjs.map +1 -1
  29. package/fesm2020/testing.mjs +8 -8
  30. package/fesm2020/testing.mjs.map +1 -1
  31. package/fesm2020/upgrade.mjs +1 -1
  32. package/index.d.ts +117 -1
  33. package/package.json +4 -4
  34. package/testing/index.d.ts +2 -2
  35. package/upgrade/index.d.ts +1 -1
@@ -1,15 +1,15 @@
1
1
  /**
2
- * @license Angular v14.1.0-next.0
2
+ * @license Angular v14.1.0-next.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, ApplicationRef, Version } from '@angular/core';
9
- import { from, of, BehaviorSubject, combineLatest, throwError, EmptyError, concat, defer, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
8
+ import { ɵisObservable, ɵisPromise, EventEmitter, Directive, Attribute, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, InjectionToken, InjectFlags, NgModuleFactory, Injectable, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, Input, HostListener, HostBinding, Optional, ContentChildren, Injector, Compiler, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, Inject, ApplicationRef, ENVIRONMENT_INITIALIZER, Version } from '@angular/core';
9
+ import { from, of, BehaviorSubject, combineLatest, concat, defer, pipe, throwError, EmptyError, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
10
10
  import * as i3 from '@angular/common';
11
- import { Location, LocationStrategy, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
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';
11
+ import { Location, LocationStrategy, HashLocationStrategy, PathLocationStrategy, ViewportScroller, LOCATION_INITIALIZED } from '@angular/common';
12
+ import { map, switchMap, take, startWith, scan, filter, mergeMap, first, concatMap, tap, catchError, last as last$1, takeWhile, defaultIfEmpty, takeLast, mapTo, finalize, refCount, mergeAll } from 'rxjs/operators';
13
13
  import * as i1 from '@angular/platform-browser';
14
14
 
15
15
  /**
@@ -2391,7 +2391,10 @@ class RouterOutlet {
2391
2391
  }
2392
2392
  /** @nodoc */
2393
2393
  ngOnDestroy() {
2394
- this.parentContexts.onChildOutletDestroyed(this.name);
2394
+ // Ensure that the registered outlet is this one before removing it on the context.
2395
+ if (this.parentContexts.getContext(this.name)?.outlet === this) {
2396
+ this.parentContexts.onChildOutletDestroyed(this.name);
2397
+ }
2395
2398
  }
2396
2399
  /** @nodoc */
2397
2400
  ngOnInit() {
@@ -2489,9 +2492,9 @@ class RouterOutlet {
2489
2492
  this.activateEvents.emit(this.activated.instance);
2490
2493
  }
2491
2494
  }
2492
- RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
2493
- RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.0", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2494
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterOutlet, decorators: [{
2495
+ RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterOutlet, deps: [{ token: ChildrenOutletContexts }, { token: i0.ViewContainerRef }, { token: 'name', attribute: true }, { token: i0.ChangeDetectorRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive });
2496
+ RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.3", type: RouterOutlet, selector: "router-outlet", outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], ngImport: i0 });
2497
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterOutlet, decorators: [{
2495
2498
  type: Directive,
2496
2499
  args: [{ selector: 'router-outlet', exportAs: 'outlet' }]
2497
2500
  }], ctorParameters: function () { return [{ type: ChildrenOutletContexts }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
@@ -2548,9 +2551,9 @@ function isComponentFactoryResolver(item) {
2548
2551
  */
2549
2552
  class ɵEmptyOutletComponent {
2550
2553
  }
2551
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2552
- ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.0-next.0", 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"] }] });
2553
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2554
+ ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2555
+ ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.0-next.3", 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"] }] });
2556
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2554
2557
  type: Component,
2555
2558
  args: [{ template: `<router-outlet></router-outlet>` }]
2556
2559
  }] });
@@ -2920,6 +2923,146 @@ class ActivateRoutes {
2920
2923
  }
2921
2924
  }
2922
2925
 
2926
+ /**
2927
+ * @license
2928
+ * Copyright Google LLC All Rights Reserved.
2929
+ *
2930
+ * Use of this source code is governed by an MIT-style license that can be
2931
+ * found in the LICENSE file at https://angular.io/license
2932
+ */
2933
+ class CanActivate {
2934
+ constructor(path) {
2935
+ this.path = path;
2936
+ this.route = this.path[this.path.length - 1];
2937
+ }
2938
+ }
2939
+ class CanDeactivate {
2940
+ constructor(component, route) {
2941
+ this.component = component;
2942
+ this.route = route;
2943
+ }
2944
+ }
2945
+ function getAllRouteGuards(future, curr, parentContexts) {
2946
+ const futureRoot = future._root;
2947
+ const currRoot = curr ? curr._root : null;
2948
+ return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
2949
+ }
2950
+ function getCanActivateChild(p) {
2951
+ const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
2952
+ if (!canActivateChild || canActivateChild.length === 0)
2953
+ return null;
2954
+ return { node: p, guards: canActivateChild };
2955
+ }
2956
+ function getToken(token, snapshot, fallbackInjector) {
2957
+ const routeInjector = getClosestRouteInjector(snapshot);
2958
+ const injector = routeInjector ?? fallbackInjector;
2959
+ return injector.get(token);
2960
+ }
2961
+ function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
2962
+ canDeactivateChecks: [],
2963
+ canActivateChecks: []
2964
+ }) {
2965
+ const prevChildren = nodeChildrenAsMap(currNode);
2966
+ // Process the children of the future route
2967
+ futureNode.children.forEach(c => {
2968
+ getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
2969
+ delete prevChildren[c.value.outlet];
2970
+ });
2971
+ // Process any children left from the current route (not active for the future route)
2972
+ forEach(prevChildren, (v, k) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks));
2973
+ return checks;
2974
+ }
2975
+ function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
2976
+ canDeactivateChecks: [],
2977
+ canActivateChecks: []
2978
+ }) {
2979
+ const future = futureNode.value;
2980
+ const curr = currNode ? currNode.value : null;
2981
+ const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
2982
+ // reusing the node
2983
+ if (curr && future.routeConfig === curr.routeConfig) {
2984
+ const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers);
2985
+ if (shouldRun) {
2986
+ checks.canActivateChecks.push(new CanActivate(futurePath));
2987
+ }
2988
+ else {
2989
+ // we need to set the data
2990
+ future.data = curr.data;
2991
+ future._resolvedData = curr._resolvedData;
2992
+ }
2993
+ // If we have a component, we need to go through an outlet.
2994
+ if (future.component) {
2995
+ getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
2996
+ // if we have a componentless route, we recurse but keep the same outlet map.
2997
+ }
2998
+ else {
2999
+ getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
3000
+ }
3001
+ if (shouldRun && context && context.outlet && context.outlet.isActivated) {
3002
+ checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
3003
+ }
3004
+ }
3005
+ else {
3006
+ if (curr) {
3007
+ deactivateRouteAndItsChildren(currNode, context, checks);
3008
+ }
3009
+ checks.canActivateChecks.push(new CanActivate(futurePath));
3010
+ // If we have a component, we need to go through an outlet.
3011
+ if (future.component) {
3012
+ getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
3013
+ // if we have a componentless route, we recurse but keep the same outlet map.
3014
+ }
3015
+ else {
3016
+ getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
3017
+ }
3018
+ }
3019
+ return checks;
3020
+ }
3021
+ function shouldRunGuardsAndResolvers(curr, future, mode) {
3022
+ if (typeof mode === 'function') {
3023
+ return mode(curr, future);
3024
+ }
3025
+ switch (mode) {
3026
+ case 'pathParamsChange':
3027
+ return !equalPath(curr.url, future.url);
3028
+ case 'pathParamsOrQueryParamsChange':
3029
+ return !equalPath(curr.url, future.url) ||
3030
+ !shallowEqual(curr.queryParams, future.queryParams);
3031
+ case 'always':
3032
+ return true;
3033
+ case 'paramsOrQueryParamsChange':
3034
+ return !equalParamsAndUrlSegments(curr, future) ||
3035
+ !shallowEqual(curr.queryParams, future.queryParams);
3036
+ case 'paramsChange':
3037
+ default:
3038
+ return !equalParamsAndUrlSegments(curr, future);
3039
+ }
3040
+ }
3041
+ function deactivateRouteAndItsChildren(route, context, checks) {
3042
+ const children = nodeChildrenAsMap(route);
3043
+ const r = route.value;
3044
+ forEach(children, (node, childName) => {
3045
+ if (!r.component) {
3046
+ deactivateRouteAndItsChildren(node, context, checks);
3047
+ }
3048
+ else if (context) {
3049
+ deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
3050
+ }
3051
+ else {
3052
+ deactivateRouteAndItsChildren(node, null, checks);
3053
+ }
3054
+ });
3055
+ if (!r.component) {
3056
+ checks.canDeactivateChecks.push(new CanDeactivate(null, r));
3057
+ }
3058
+ else if (context && context.outlet && context.outlet.isActivated) {
3059
+ checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
3060
+ }
3061
+ else {
3062
+ checks.canDeactivateChecks.push(new CanDeactivate(null, r));
3063
+ }
3064
+ }
3065
+
2923
3066
  /**
2924
3067
  * @license
2925
3068
  * Copyright Google LLC All Rights Reserved.
@@ -2961,6 +3104,9 @@ function isCanActivateChild(guard) {
2961
3104
  function isCanDeactivate(guard) {
2962
3105
  return guard && isFunction(guard.canDeactivate);
2963
3106
  }
3107
+ function isCanMatch(guard) {
3108
+ return guard && isFunction(guard.canMatch);
3109
+ }
2964
3110
 
2965
3111
  /**
2966
3112
  * @license
@@ -3008,92 +3154,277 @@ function prioritizedGuardValue() {
3008
3154
  * Use of this source code is governed by an MIT-style license that can be
3009
3155
  * found in the LICENSE file at https://angular.io/license
3010
3156
  */
3011
- const noMatch$1 = {
3012
- matched: false,
3013
- consumedSegments: [],
3014
- remainingSegments: [],
3015
- parameters: {},
3016
- positionalParamSegments: {}
3017
- };
3018
- function match(segmentGroup, route, segments) {
3019
- if (route.path === '') {
3020
- if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
3021
- return { ...noMatch$1 };
3157
+ function checkGuards(moduleInjector, forwardEvent) {
3158
+ return mergeMap(t => {
3159
+ const { targetSnapshot, currentSnapshot, guards: { canActivateChecks, canDeactivateChecks } } = t;
3160
+ if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
3161
+ return of({ ...t, guardsResult: true });
3022
3162
  }
3023
- return {
3024
- matched: true,
3025
- consumedSegments: [],
3026
- remainingSegments: segments,
3027
- parameters: {},
3028
- positionalParamSegments: {}
3029
- };
3030
- }
3031
- const matcher = route.matcher || defaultUrlMatcher;
3032
- const res = matcher(segments, segmentGroup, route);
3033
- if (!res)
3034
- return { ...noMatch$1 };
3035
- const posParams = {};
3036
- forEach(res.posParams, (v, k) => {
3037
- posParams[k] = v.path;
3163
+ return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot, moduleInjector)
3164
+ .pipe(mergeMap(canDeactivate => {
3165
+ return canDeactivate && isBoolean(canDeactivate) ?
3166
+ runCanActivateChecks(targetSnapshot, canActivateChecks, moduleInjector, forwardEvent) :
3167
+ of(canDeactivate);
3168
+ }), map(guardsResult => ({ ...t, guardsResult })));
3038
3169
  });
3039
- const parameters = res.consumed.length > 0 ?
3040
- { ...posParams, ...res.consumed[res.consumed.length - 1].parameters } :
3041
- posParams;
3042
- return {
3043
- matched: true,
3044
- consumedSegments: res.consumed,
3045
- remainingSegments: segments.slice(res.consumed.length),
3046
- // TODO(atscott): investigate combining parameters and positionalParamSegments
3047
- parameters,
3048
- positionalParamSegments: res.posParams ?? {}
3049
- };
3050
3170
  }
3051
- function split(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution = 'corrected') {
3052
- if (slicedSegments.length > 0 &&
3053
- containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
3054
- const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
3055
- s._sourceSegment = segmentGroup;
3056
- s._segmentIndexShift = consumedSegments.length;
3057
- return { segmentGroup: s, slicedSegments: [] };
3058
- }
3059
- if (slicedSegments.length === 0 &&
3060
- containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
3061
- const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution));
3062
- s._sourceSegment = segmentGroup;
3063
- s._segmentIndexShift = consumedSegments.length;
3064
- return { segmentGroup: s, slicedSegments };
3065
- }
3066
- const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
3067
- s._sourceSegment = segmentGroup;
3068
- s._segmentIndexShift = consumedSegments.length;
3069
- return { segmentGroup: s, slicedSegments };
3171
+ function runCanDeactivateChecks(checks, futureRSS, currRSS, moduleInjector) {
3172
+ return from(checks).pipe(mergeMap(check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, moduleInjector)), first(result => {
3173
+ return result !== true;
3174
+ }, true));
3070
3175
  }
3071
- function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) {
3072
- const res = {};
3073
- for (const r of routes) {
3074
- if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
3075
- const s = new UrlSegmentGroup([], {});
3076
- s._sourceSegment = segmentGroup;
3077
- if (relativeLinkResolution === 'legacy') {
3078
- s._segmentIndexShift = segmentGroup.segments.length;
3079
- if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
3080
- s._segmentIndexShiftCorrected = consumedSegments.length;
3081
- }
3082
- }
3083
- else {
3084
- s._segmentIndexShift = consumedSegments.length;
3085
- }
3086
- res[getOutlet(r)] = s;
3087
- }
3176
+ function runCanActivateChecks(futureSnapshot, checks, moduleInjector, forwardEvent) {
3177
+ return from(checks).pipe(concatMap((check) => {
3178
+ return concat(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path, moduleInjector), runCanActivate(futureSnapshot, check.route, moduleInjector));
3179
+ }), first(result => {
3180
+ return result !== true;
3181
+ }, true));
3182
+ }
3183
+ /**
3184
+ * This should fire off `ActivationStart` events for each route being activated at this
3185
+ * level.
3186
+ * In other words, if you're activating `a` and `b` below, `path` will contain the
3187
+ * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always
3188
+ * return
3189
+ * `true` so checks continue to run.
3190
+ */
3191
+ function fireActivationStart(snapshot, forwardEvent) {
3192
+ if (snapshot !== null && forwardEvent) {
3193
+ forwardEvent(new ActivationStart(snapshot));
3088
3194
  }
3089
- return { ...children, ...res };
3195
+ return of(true);
3090
3196
  }
3091
- function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
3092
- const res = {};
3093
- res[PRIMARY_OUTLET] = primarySegment;
3094
- primarySegment._sourceSegment = segmentGroup;
3095
- primarySegment._segmentIndexShift = consumedSegments.length;
3096
- for (const r of routes) {
3197
+ /**
3198
+ * This should fire off `ChildActivationStart` events for each route being activated at this
3199
+ * level.
3200
+ * In other words, if you're activating `a` and `b` below, `path` will contain the
3201
+ * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always
3202
+ * return
3203
+ * `true` so checks continue to run.
3204
+ */
3205
+ function fireChildActivationStart(snapshot, forwardEvent) {
3206
+ if (snapshot !== null && forwardEvent) {
3207
+ forwardEvent(new ChildActivationStart(snapshot));
3208
+ }
3209
+ return of(true);
3210
+ }
3211
+ function runCanActivate(futureRSS, futureARS, moduleInjector) {
3212
+ const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
3213
+ if (!canActivate || canActivate.length === 0)
3214
+ return of(true);
3215
+ const canActivateObservables = canActivate.map((c) => {
3216
+ return defer(() => {
3217
+ const guard = getToken(c, futureARS, moduleInjector);
3218
+ let observable;
3219
+ if (isCanActivate(guard)) {
3220
+ observable = wrapIntoObservable(guard.canActivate(futureARS, futureRSS));
3221
+ }
3222
+ else if (isFunction(guard)) {
3223
+ observable = wrapIntoObservable(guard(futureARS, futureRSS));
3224
+ }
3225
+ else {
3226
+ throw new Error('Invalid CanActivate guard');
3227
+ }
3228
+ return observable.pipe(first());
3229
+ });
3230
+ });
3231
+ return of(canActivateObservables).pipe(prioritizedGuardValue());
3232
+ }
3233
+ function runCanActivateChild(futureRSS, path, moduleInjector) {
3234
+ const futureARS = path[path.length - 1];
3235
+ const canActivateChildGuards = path.slice(0, path.length - 1)
3236
+ .reverse()
3237
+ .map(p => getCanActivateChild(p))
3238
+ .filter(_ => _ !== null);
3239
+ const canActivateChildGuardsMapped = canActivateChildGuards.map((d) => {
3240
+ return defer(() => {
3241
+ const guardsMapped = d.guards.map((c) => {
3242
+ const guard = getToken(c, d.node, moduleInjector);
3243
+ let observable;
3244
+ if (isCanActivateChild(guard)) {
3245
+ observable = wrapIntoObservable(guard.canActivateChild(futureARS, futureRSS));
3246
+ }
3247
+ else if (isFunction(guard)) {
3248
+ observable = wrapIntoObservable(guard(futureARS, futureRSS));
3249
+ }
3250
+ else {
3251
+ throw new Error('Invalid CanActivateChild guard');
3252
+ }
3253
+ return observable.pipe(first());
3254
+ });
3255
+ return of(guardsMapped).pipe(prioritizedGuardValue());
3256
+ });
3257
+ });
3258
+ return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
3259
+ }
3260
+ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector) {
3261
+ const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
3262
+ if (!canDeactivate || canDeactivate.length === 0)
3263
+ return of(true);
3264
+ const canDeactivateObservables = canDeactivate.map((c) => {
3265
+ const guard = getToken(c, currARS, moduleInjector);
3266
+ let observable;
3267
+ if (isCanDeactivate(guard)) {
3268
+ observable = wrapIntoObservable(guard.canDeactivate(component, currARS, currRSS, futureRSS));
3269
+ }
3270
+ else if (isFunction(guard)) {
3271
+ observable = wrapIntoObservable(guard(component, currARS, currRSS, futureRSS));
3272
+ }
3273
+ else {
3274
+ throw new Error('Invalid CanDeactivate guard');
3275
+ }
3276
+ return observable.pipe(first());
3277
+ });
3278
+ return of(canDeactivateObservables).pipe(prioritizedGuardValue());
3279
+ }
3280
+ function runCanLoadGuards(injector, route, segments, urlSerializer) {
3281
+ const canLoad = route.canLoad;
3282
+ if (canLoad === undefined || canLoad.length === 0) {
3283
+ return of(true);
3284
+ }
3285
+ const canLoadObservables = canLoad.map((injectionToken) => {
3286
+ const guard = injector.get(injectionToken);
3287
+ let guardVal;
3288
+ if (isCanLoad(guard)) {
3289
+ guardVal = guard.canLoad(route, segments);
3290
+ }
3291
+ else if (isFunction(guard)) {
3292
+ guardVal = guard(route, segments);
3293
+ }
3294
+ else {
3295
+ throw new Error('Invalid CanLoad guard');
3296
+ }
3297
+ return wrapIntoObservable(guardVal);
3298
+ });
3299
+ return of(canLoadObservables)
3300
+ .pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
3301
+ }
3302
+ function redirectIfUrlTree(urlSerializer) {
3303
+ return pipe(tap((result) => {
3304
+ if (!isUrlTree(result))
3305
+ return;
3306
+ const error = navigationCancelingError(`Redirecting to "${urlSerializer.serialize(result)}"`);
3307
+ error.url = result;
3308
+ throw error;
3309
+ }), map(result => result === true));
3310
+ }
3311
+ function runCanMatchGuards(injector, route, segments, urlSerializer) {
3312
+ const canMatch = route.canMatch;
3313
+ if (!canMatch || canMatch.length === 0)
3314
+ return of(true);
3315
+ const canMatchObservables = canMatch.map(injectionToken => {
3316
+ const guard = injector.get(injectionToken);
3317
+ const guardVal = isCanMatch(guard) ? guard.canMatch(route, segments) : guard(route, segments);
3318
+ return wrapIntoObservable(guardVal);
3319
+ });
3320
+ return of(canMatchObservables)
3321
+ .pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
3322
+ }
3323
+
3324
+ /**
3325
+ * @license
3326
+ * Copyright Google LLC All Rights Reserved.
3327
+ *
3328
+ * Use of this source code is governed by an MIT-style license that can be
3329
+ * found in the LICENSE file at https://angular.io/license
3330
+ */
3331
+ const noMatch$1 = {
3332
+ matched: false,
3333
+ consumedSegments: [],
3334
+ remainingSegments: [],
3335
+ parameters: {},
3336
+ positionalParamSegments: {}
3337
+ };
3338
+ function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
3339
+ const result = match(segmentGroup, route, segments);
3340
+ if (!result.matched) {
3341
+ return of(result);
3342
+ }
3343
+ // Only create the Route's `EnvironmentInjector` if it matches the attempted
3344
+ // navigation
3345
+ injector = getOrCreateRouteInjectorIfNeeded(route, injector);
3346
+ return runCanMatchGuards(injector, route, segments, urlSerializer)
3347
+ .pipe(map((v) => v === true ? result : { ...noMatch$1 }));
3348
+ }
3349
+ function match(segmentGroup, route, segments) {
3350
+ if (route.path === '') {
3351
+ if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
3352
+ return { ...noMatch$1 };
3353
+ }
3354
+ return {
3355
+ matched: true,
3356
+ consumedSegments: [],
3357
+ remainingSegments: segments,
3358
+ parameters: {},
3359
+ positionalParamSegments: {}
3360
+ };
3361
+ }
3362
+ const matcher = route.matcher || defaultUrlMatcher;
3363
+ const res = matcher(segments, segmentGroup, route);
3364
+ if (!res)
3365
+ return { ...noMatch$1 };
3366
+ const posParams = {};
3367
+ forEach(res.posParams, (v, k) => {
3368
+ posParams[k] = v.path;
3369
+ });
3370
+ const parameters = res.consumed.length > 0 ?
3371
+ { ...posParams, ...res.consumed[res.consumed.length - 1].parameters } :
3372
+ posParams;
3373
+ return {
3374
+ matched: true,
3375
+ consumedSegments: res.consumed,
3376
+ remainingSegments: segments.slice(res.consumed.length),
3377
+ // TODO(atscott): investigate combining parameters and positionalParamSegments
3378
+ parameters,
3379
+ positionalParamSegments: res.posParams ?? {}
3380
+ };
3381
+ }
3382
+ function split(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution = 'corrected') {
3383
+ if (slicedSegments.length > 0 &&
3384
+ containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
3385
+ const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
3386
+ s._sourceSegment = segmentGroup;
3387
+ s._segmentIndexShift = consumedSegments.length;
3388
+ return { segmentGroup: s, slicedSegments: [] };
3389
+ }
3390
+ if (slicedSegments.length === 0 &&
3391
+ containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
3392
+ const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution));
3393
+ s._sourceSegment = segmentGroup;
3394
+ s._segmentIndexShift = consumedSegments.length;
3395
+ return { segmentGroup: s, slicedSegments };
3396
+ }
3397
+ const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
3398
+ s._sourceSegment = segmentGroup;
3399
+ s._segmentIndexShift = consumedSegments.length;
3400
+ return { segmentGroup: s, slicedSegments };
3401
+ }
3402
+ function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) {
3403
+ const res = {};
3404
+ for (const r of routes) {
3405
+ if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
3406
+ const s = new UrlSegmentGroup([], {});
3407
+ s._sourceSegment = segmentGroup;
3408
+ if (relativeLinkResolution === 'legacy') {
3409
+ s._segmentIndexShift = segmentGroup.segments.length;
3410
+ if (typeof ngDevMode === 'undefined' || !!ngDevMode) {
3411
+ s._segmentIndexShiftCorrected = consumedSegments.length;
3412
+ }
3413
+ }
3414
+ else {
3415
+ s._segmentIndexShift = consumedSegments.length;
3416
+ }
3417
+ res[getOutlet(r)] = s;
3418
+ }
3419
+ }
3420
+ return { ...children, ...res };
3421
+ }
3422
+ function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
3423
+ const res = {};
3424
+ res[PRIMARY_OUTLET] = primarySegment;
3425
+ primarySegment._sourceSegment = segmentGroup;
3426
+ primarySegment._segmentIndexShift = consumedSegments.length;
3427
+ for (const r of routes) {
3097
3428
  if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
3098
3429
  const s = new UrlSegmentGroup([], {});
3099
3430
  s._sourceSegment = segmentGroup;
@@ -3346,28 +3677,30 @@ class ApplyRedirects {
3346
3677
  }
3347
3678
  return of(new UrlSegmentGroup(segments, {}));
3348
3679
  }
3349
- const { matched, consumedSegments, remainingSegments } = match(rawSegmentGroup, route, segments);
3350
- if (!matched)
3351
- return noMatch(rawSegmentGroup);
3352
- // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation
3353
- injector = getOrCreateRouteInjectorIfNeeded(route, injector);
3354
- const childConfig$ = this.getChildConfig(injector, route, segments);
3355
- return childConfig$.pipe(mergeMap((routerConfig) => {
3356
- const childInjector = routerConfig.injector ?? injector;
3357
- const childConfig = routerConfig.routes;
3358
- const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3359
- // See comment on the other call to `split` about why this is necessary.
3360
- const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3361
- if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3362
- const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3363
- return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3364
- }
3365
- if (childConfig.length === 0 && slicedSegments.length === 0) {
3366
- return of(new UrlSegmentGroup(consumedSegments, {}));
3367
- }
3368
- const matchedOnOutlet = getOutlet(route) === outlet;
3369
- const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3370
- return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3680
+ return matchWithChecks(rawSegmentGroup, route, segments, injector, this.urlSerializer)
3681
+ .pipe(switchMap(({ matched, consumedSegments, remainingSegments }) => {
3682
+ if (!matched)
3683
+ return noMatch(rawSegmentGroup);
3684
+ // If the route has an injector created from providers, we should start using that.
3685
+ injector = route._injector ?? injector;
3686
+ const childConfig$ = this.getChildConfig(injector, route, segments);
3687
+ return childConfig$.pipe(mergeMap((routerConfig) => {
3688
+ const childInjector = routerConfig.injector ?? injector;
3689
+ const childConfig = routerConfig.routes;
3690
+ const { segmentGroup: splitSegmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);
3691
+ // See comment on the other call to `split` about why this is necessary.
3692
+ const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);
3693
+ if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3694
+ const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);
3695
+ return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children)));
3696
+ }
3697
+ if (childConfig.length === 0 && slicedSegments.length === 0) {
3698
+ return of(new UrlSegmentGroup(consumedSegments, {}));
3699
+ }
3700
+ const matchedOnOutlet = getOutlet(route) === outlet;
3701
+ const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);
3702
+ return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children)));
3703
+ }));
3371
3704
  }));
3372
3705
  }
3373
3706
  getChildConfig(injector, route, segments) {
@@ -3380,7 +3713,7 @@ class ApplyRedirects {
3380
3713
  if (route._loadedRoutes !== undefined) {
3381
3714
  return of({ routes: route._loadedRoutes, injector: route._loadedInjector });
3382
3715
  }
3383
- return this.runCanLoadGuards(injector, route, segments)
3716
+ return runCanLoadGuards(injector, route, segments, this.urlSerializer)
3384
3717
  .pipe(mergeMap((shouldLoadResult) => {
3385
3718
  if (shouldLoadResult) {
3386
3719
  return this.configLoader.loadChildren(injector, route)
@@ -3394,33 +3727,6 @@ class ApplyRedirects {
3394
3727
  }
3395
3728
  return of({ routes: [], injector });
3396
3729
  }
3397
- runCanLoadGuards(injector, route, segments) {
3398
- const canLoad = route.canLoad;
3399
- if (!canLoad || canLoad.length === 0)
3400
- return of(true);
3401
- const canLoadObservables = canLoad.map((injectionToken) => {
3402
- const guard = injector.get(injectionToken);
3403
- let guardVal;
3404
- if (isCanLoad(guard)) {
3405
- guardVal = guard.canLoad(route, segments);
3406
- }
3407
- else if (isFunction(guard)) {
3408
- guardVal = guard(route, segments);
3409
- }
3410
- else {
3411
- throw new Error('Invalid CanLoad guard');
3412
- }
3413
- return wrapIntoObservable(guardVal);
3414
- });
3415
- return of(canLoadObservables)
3416
- .pipe(prioritizedGuardValue(), tap((result) => {
3417
- if (!isUrlTree(result))
3418
- return;
3419
- const error = navigationCancelingError(`Redirecting to "${this.urlSerializer.serialize(result)}"`);
3420
- error.url = result;
3421
- throw error;
3422
- }), map(result => result === true));
3423
- }
3424
3730
  lineralizeSegments(route, urlTree) {
3425
3731
  let res = [];
3426
3732
  let c = urlTree.root;
@@ -3430,344 +3736,61 @@ class ApplyRedirects {
3430
3736
  return of(res);
3431
3737
  }
3432
3738
  if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
3433
- return namedOutletsRedirect(route.redirectTo);
3434
- }
3435
- c = c.children[PRIMARY_OUTLET];
3436
- }
3437
- }
3438
- applyRedirectCommands(segments, redirectTo, posParams) {
3439
- return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3440
- }
3441
- applyRedirectCreatreUrlTree(redirectTo, urlTree, segments, posParams) {
3442
- const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
3443
- return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
3444
- }
3445
- createQueryParams(redirectToParams, actualParams) {
3446
- const res = {};
3447
- forEach(redirectToParams, (v, k) => {
3448
- const copySourceValue = typeof v === 'string' && v.startsWith(':');
3449
- if (copySourceValue) {
3450
- const sourceName = v.substring(1);
3451
- res[k] = actualParams[sourceName];
3452
- }
3453
- else {
3454
- res[k] = v;
3455
- }
3456
- });
3457
- return res;
3458
- }
3459
- createSegmentGroup(redirectTo, group, segments, posParams) {
3460
- const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
3461
- let children = {};
3462
- forEach(group.children, (child, name) => {
3463
- children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
3464
- });
3465
- return new UrlSegmentGroup(updatedSegments, children);
3466
- }
3467
- createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
3468
- return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) :
3469
- this.findOrReturn(s, actualSegments));
3470
- }
3471
- findPosParam(redirectTo, redirectToUrlSegment, posParams) {
3472
- const pos = posParams[redirectToUrlSegment.path.substring(1)];
3473
- if (!pos)
3474
- throw new Error(`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
3475
- return pos;
3476
- }
3477
- findOrReturn(redirectToUrlSegment, actualSegments) {
3478
- let idx = 0;
3479
- for (const s of actualSegments) {
3480
- if (s.path === redirectToUrlSegment.path) {
3481
- actualSegments.splice(idx);
3482
- return s;
3483
- }
3484
- idx++;
3485
- }
3486
- return redirectToUrlSegment;
3487
- }
3488
- }
3489
-
3490
- /**
3491
- * @license
3492
- * Copyright Google LLC All Rights Reserved.
3493
- *
3494
- * Use of this source code is governed by an MIT-style license that can be
3495
- * found in the LICENSE file at https://angular.io/license
3496
- */
3497
- function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3498
- return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3499
- .pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
3500
- }
3501
-
3502
- /**
3503
- * @license
3504
- * Copyright Google LLC All Rights Reserved.
3505
- *
3506
- * Use of this source code is governed by an MIT-style license that can be
3507
- * found in the LICENSE file at https://angular.io/license
3508
- */
3509
- class CanActivate {
3510
- constructor(path) {
3511
- this.path = path;
3512
- this.route = this.path[this.path.length - 1];
3513
- }
3514
- }
3515
- class CanDeactivate {
3516
- constructor(component, route) {
3517
- this.component = component;
3518
- this.route = route;
3519
- }
3520
- }
3521
- function getAllRouteGuards(future, curr, parentContexts) {
3522
- const futureRoot = future._root;
3523
- const currRoot = curr ? curr._root : null;
3524
- return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
3525
- }
3526
- function getCanActivateChild(p) {
3527
- const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
3528
- if (!canActivateChild || canActivateChild.length === 0)
3529
- return null;
3530
- return { node: p, guards: canActivateChild };
3531
- }
3532
- function getToken(token, snapshot, fallbackInjector) {
3533
- const routeInjector = getClosestRouteInjector(snapshot);
3534
- const injector = routeInjector ?? fallbackInjector;
3535
- return injector.get(token);
3536
- }
3537
- function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
3538
- canDeactivateChecks: [],
3539
- canActivateChecks: []
3540
- }) {
3541
- const prevChildren = nodeChildrenAsMap(currNode);
3542
- // Process the children of the future route
3543
- futureNode.children.forEach(c => {
3544
- getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
3545
- delete prevChildren[c.value.outlet];
3546
- });
3547
- // Process any children left from the current route (not active for the future route)
3548
- forEach(prevChildren, (v, k) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks));
3549
- return checks;
3550
- }
3551
- function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
3552
- canDeactivateChecks: [],
3553
- canActivateChecks: []
3554
- }) {
3555
- const future = futureNode.value;
3556
- const curr = currNode ? currNode.value : null;
3557
- const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
3558
- // reusing the node
3559
- if (curr && future.routeConfig === curr.routeConfig) {
3560
- const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers);
3561
- if (shouldRun) {
3562
- checks.canActivateChecks.push(new CanActivate(futurePath));
3563
- }
3564
- else {
3565
- // we need to set the data
3566
- future.data = curr.data;
3567
- future._resolvedData = curr._resolvedData;
3568
- }
3569
- // If we have a component, we need to go through an outlet.
3570
- if (future.component) {
3571
- getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
3572
- // if we have a componentless route, we recurse but keep the same outlet map.
3573
- }
3574
- else {
3575
- getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
3576
- }
3577
- if (shouldRun && context && context.outlet && context.outlet.isActivated) {
3578
- checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
3579
- }
3580
- }
3581
- else {
3582
- if (curr) {
3583
- deactivateRouteAndItsChildren(currNode, context, checks);
3584
- }
3585
- checks.canActivateChecks.push(new CanActivate(futurePath));
3586
- // If we have a component, we need to go through an outlet.
3587
- if (future.component) {
3588
- getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
3589
- // if we have a componentless route, we recurse but keep the same outlet map.
3590
- }
3591
- else {
3592
- getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
3593
- }
3594
- }
3595
- return checks;
3596
- }
3597
- function shouldRunGuardsAndResolvers(curr, future, mode) {
3598
- if (typeof mode === 'function') {
3599
- return mode(curr, future);
3600
- }
3601
- switch (mode) {
3602
- case 'pathParamsChange':
3603
- return !equalPath(curr.url, future.url);
3604
- case 'pathParamsOrQueryParamsChange':
3605
- return !equalPath(curr.url, future.url) ||
3606
- !shallowEqual(curr.queryParams, future.queryParams);
3607
- case 'always':
3608
- return true;
3609
- case 'paramsOrQueryParamsChange':
3610
- return !equalParamsAndUrlSegments(curr, future) ||
3611
- !shallowEqual(curr.queryParams, future.queryParams);
3612
- case 'paramsChange':
3613
- default:
3614
- return !equalParamsAndUrlSegments(curr, future);
3615
- }
3616
- }
3617
- function deactivateRouteAndItsChildren(route, context, checks) {
3618
- const children = nodeChildrenAsMap(route);
3619
- const r = route.value;
3620
- forEach(children, (node, childName) => {
3621
- if (!r.component) {
3622
- deactivateRouteAndItsChildren(node, context, checks);
3623
- }
3624
- else if (context) {
3625
- deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
3626
- }
3627
- else {
3628
- deactivateRouteAndItsChildren(node, null, checks);
3629
- }
3630
- });
3631
- if (!r.component) {
3632
- checks.canDeactivateChecks.push(new CanDeactivate(null, r));
3633
- }
3634
- else if (context && context.outlet && context.outlet.isActivated) {
3635
- checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
3636
- }
3637
- else {
3638
- checks.canDeactivateChecks.push(new CanDeactivate(null, r));
3639
- }
3640
- }
3641
-
3642
- /**
3643
- * @license
3644
- * Copyright Google LLC All Rights Reserved.
3645
- *
3646
- * Use of this source code is governed by an MIT-style license that can be
3647
- * found in the LICENSE file at https://angular.io/license
3648
- */
3649
- function checkGuards(moduleInjector, forwardEvent) {
3650
- return mergeMap(t => {
3651
- const { targetSnapshot, currentSnapshot, guards: { canActivateChecks, canDeactivateChecks } } = t;
3652
- if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
3653
- return of({ ...t, guardsResult: true });
3654
- }
3655
- return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot, moduleInjector)
3656
- .pipe(mergeMap(canDeactivate => {
3657
- return canDeactivate && isBoolean(canDeactivate) ?
3658
- runCanActivateChecks(targetSnapshot, canActivateChecks, moduleInjector, forwardEvent) :
3659
- of(canDeactivate);
3660
- }), map(guardsResult => ({ ...t, guardsResult })));
3661
- });
3662
- }
3663
- function runCanDeactivateChecks(checks, futureRSS, currRSS, moduleInjector) {
3664
- return from(checks).pipe(mergeMap(check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, moduleInjector)), first(result => {
3665
- return result !== true;
3666
- }, true));
3667
- }
3668
- function runCanActivateChecks(futureSnapshot, checks, moduleInjector, forwardEvent) {
3669
- return from(checks).pipe(concatMap((check) => {
3670
- return concat(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path, moduleInjector), runCanActivate(futureSnapshot, check.route, moduleInjector));
3671
- }), first(result => {
3672
- return result !== true;
3673
- }, true));
3674
- }
3675
- /**
3676
- * This should fire off `ActivationStart` events for each route being activated at this
3677
- * level.
3678
- * In other words, if you're activating `a` and `b` below, `path` will contain the
3679
- * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always
3680
- * return
3681
- * `true` so checks continue to run.
3682
- */
3683
- function fireActivationStart(snapshot, forwardEvent) {
3684
- if (snapshot !== null && forwardEvent) {
3685
- forwardEvent(new ActivationStart(snapshot));
3686
- }
3687
- return of(true);
3688
- }
3689
- /**
3690
- * This should fire off `ChildActivationStart` events for each route being activated at this
3691
- * level.
3692
- * In other words, if you're activating `a` and `b` below, `path` will contain the
3693
- * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always
3694
- * return
3695
- * `true` so checks continue to run.
3696
- */
3697
- function fireChildActivationStart(snapshot, forwardEvent) {
3698
- if (snapshot !== null && forwardEvent) {
3699
- forwardEvent(new ChildActivationStart(snapshot));
3700
- }
3701
- return of(true);
3702
- }
3703
- function runCanActivate(futureRSS, futureARS, moduleInjector) {
3704
- const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
3705
- if (!canActivate || canActivate.length === 0)
3706
- return of(true);
3707
- const canActivateObservables = canActivate.map((c) => {
3708
- return defer(() => {
3709
- const guard = getToken(c, futureARS, moduleInjector);
3710
- let observable;
3711
- if (isCanActivate(guard)) {
3712
- observable = wrapIntoObservable(guard.canActivate(futureARS, futureRSS));
3739
+ return namedOutletsRedirect(route.redirectTo);
3713
3740
  }
3714
- else if (isFunction(guard)) {
3715
- observable = wrapIntoObservable(guard(futureARS, futureRSS));
3741
+ c = c.children[PRIMARY_OUTLET];
3742
+ }
3743
+ }
3744
+ applyRedirectCommands(segments, redirectTo, posParams) {
3745
+ return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3746
+ }
3747
+ applyRedirectCreatreUrlTree(redirectTo, urlTree, segments, posParams) {
3748
+ const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
3749
+ return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
3750
+ }
3751
+ createQueryParams(redirectToParams, actualParams) {
3752
+ const res = {};
3753
+ forEach(redirectToParams, (v, k) => {
3754
+ const copySourceValue = typeof v === 'string' && v.startsWith(':');
3755
+ if (copySourceValue) {
3756
+ const sourceName = v.substring(1);
3757
+ res[k] = actualParams[sourceName];
3716
3758
  }
3717
3759
  else {
3718
- throw new Error('Invalid CanActivate guard');
3760
+ res[k] = v;
3719
3761
  }
3720
- return observable.pipe(first());
3721
3762
  });
3722
- });
3723
- return of(canActivateObservables).pipe(prioritizedGuardValue());
3724
- }
3725
- function runCanActivateChild(futureRSS, path, moduleInjector) {
3726
- const futureARS = path[path.length - 1];
3727
- const canActivateChildGuards = path.slice(0, path.length - 1)
3728
- .reverse()
3729
- .map(p => getCanActivateChild(p))
3730
- .filter(_ => _ !== null);
3731
- const canActivateChildGuardsMapped = canActivateChildGuards.map((d) => {
3732
- return defer(() => {
3733
- const guardsMapped = d.guards.map((c) => {
3734
- const guard = getToken(c, d.node, moduleInjector);
3735
- let observable;
3736
- if (isCanActivateChild(guard)) {
3737
- observable = wrapIntoObservable(guard.canActivateChild(futureARS, futureRSS));
3738
- }
3739
- else if (isFunction(guard)) {
3740
- observable = wrapIntoObservable(guard(futureARS, futureRSS));
3741
- }
3742
- else {
3743
- throw new Error('Invalid CanActivateChild guard');
3744
- }
3745
- return observable.pipe(first());
3746
- });
3747
- return of(guardsMapped).pipe(prioritizedGuardValue());
3763
+ return res;
3764
+ }
3765
+ createSegmentGroup(redirectTo, group, segments, posParams) {
3766
+ const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
3767
+ let children = {};
3768
+ forEach(group.children, (child, name) => {
3769
+ children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
3748
3770
  });
3749
- });
3750
- return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
3751
- }
3752
- function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector) {
3753
- const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
3754
- if (!canDeactivate || canDeactivate.length === 0)
3755
- return of(true);
3756
- const canDeactivateObservables = canDeactivate.map((c) => {
3757
- const guard = getToken(c, currARS, moduleInjector);
3758
- let observable;
3759
- if (isCanDeactivate(guard)) {
3760
- observable = wrapIntoObservable(guard.canDeactivate(component, currARS, currRSS, futureRSS));
3761
- }
3762
- else if (isFunction(guard)) {
3763
- observable = wrapIntoObservable(guard(component, currARS, currRSS, futureRSS));
3764
- }
3765
- else {
3766
- throw new Error('Invalid CanDeactivate guard');
3771
+ return new UrlSegmentGroup(updatedSegments, children);
3772
+ }
3773
+ createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
3774
+ return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) :
3775
+ this.findOrReturn(s, actualSegments));
3776
+ }
3777
+ findPosParam(redirectTo, redirectToUrlSegment, posParams) {
3778
+ const pos = posParams[redirectToUrlSegment.path.substring(1)];
3779
+ if (!pos)
3780
+ throw new Error(`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
3781
+ return pos;
3782
+ }
3783
+ findOrReturn(redirectToUrlSegment, actualSegments) {
3784
+ let idx = 0;
3785
+ for (const s of actualSegments) {
3786
+ if (s.path === redirectToUrlSegment.path) {
3787
+ actualSegments.splice(idx);
3788
+ return s;
3789
+ }
3790
+ idx++;
3767
3791
  }
3768
- return observable.pipe(first());
3769
- });
3770
- return of(canDeactivateObservables).pipe(prioritizedGuardValue());
3792
+ return redirectToUrlSegment;
3793
+ }
3771
3794
  }
3772
3795
 
3773
3796
  /**
@@ -3777,53 +3800,64 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector
3777
3800
  * Use of this source code is governed by an MIT-style license that can be
3778
3801
  * found in the LICENSE file at https://angular.io/license
3779
3802
  */
3780
- const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3803
+ function applyRedirects(environmentInjector, configLoader, urlSerializer, config) {
3804
+ return switchMap(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)
3805
+ .pipe(map(urlAfterRedirects => ({ ...t, urlAfterRedirects }))));
3806
+ }
3807
+
3808
+ /**
3809
+ * @license
3810
+ * Copyright Google LLC All Rights Reserved.
3811
+ *
3812
+ * Use of this source code is governed by an MIT-style license that can be
3813
+ * found in the LICENSE file at https://angular.io/license
3814
+ */
3815
+ const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3781
3816
  class NoMatch {
3782
3817
  }
3783
3818
  function newObservableError(e) {
3784
3819
  // TODO(atscott): This pattern is used throughout the router code and can be `throwError` instead.
3785
3820
  return new Observable((obs) => obs.error(e));
3786
3821
  }
3787
- function recognize$1(rootComponentType, config, urlTree, url, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') {
3788
- try {
3789
- const result = new Recognizer(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution)
3790
- .recognize();
3822
+ function recognize$1(injector, rootComponentType, config, urlTree, url, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') {
3823
+ return new Recognizer(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer)
3824
+ .recognize()
3825
+ .pipe(switchMap(result => {
3791
3826
  if (result === null) {
3792
3827
  return newObservableError(new NoMatch());
3793
3828
  }
3794
3829
  else {
3795
3830
  return of(result);
3796
3831
  }
3797
- }
3798
- catch (e) {
3799
- // Catch the potential error from recognize due to duplicate outlet matches and return as an
3800
- // `Observable` error instead.
3801
- return newObservableError(e);
3802
- }
3832
+ }));
3803
3833
  }
3804
3834
  class Recognizer {
3805
- constructor(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution) {
3835
+ constructor(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer) {
3836
+ this.injector = injector;
3806
3837
  this.rootComponentType = rootComponentType;
3807
3838
  this.config = config;
3808
3839
  this.urlTree = urlTree;
3809
3840
  this.url = url;
3810
3841
  this.paramsInheritanceStrategy = paramsInheritanceStrategy;
3811
3842
  this.relativeLinkResolution = relativeLinkResolution;
3843
+ this.urlSerializer = urlSerializer;
3812
3844
  }
3813
3845
  recognize() {
3814
3846
  const rootSegmentGroup = split(this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined), this.relativeLinkResolution)
3815
3847
  .segmentGroup;
3816
- const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
3817
- if (children === null) {
3818
- return null;
3819
- }
3820
- // Use Object.freeze to prevent readers of the Router state from modifying it outside of a
3821
- // navigation, resulting in the router being out of sync with the browser.
3822
- const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
3823
- const rootNode = new TreeNode(root, children);
3824
- const routeState = new RouterStateSnapshot(this.url, rootNode);
3825
- this.inheritParamsAndData(routeState._root);
3826
- return routeState;
3848
+ return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET)
3849
+ .pipe(map(children => {
3850
+ if (children === null) {
3851
+ return null;
3852
+ }
3853
+ // Use Object.freeze to prevent readers of the Router state from modifying it outside of a
3854
+ // navigation, resulting in the router being out of sync with the browser.
3855
+ const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
3856
+ const rootNode = new TreeNode(root, children);
3857
+ const routeState = new RouterStateSnapshot(this.url, rootNode);
3858
+ this.inheritParamsAndData(routeState._root);
3859
+ return routeState;
3860
+ }));
3827
3861
  }
3828
3862
  inheritParamsAndData(routeNode) {
3829
3863
  const route = routeNode.value;
@@ -3832,11 +3866,11 @@ class Recognizer {
3832
3866
  route.data = Object.freeze(i.data);
3833
3867
  routeNode.children.forEach(n => this.inheritParamsAndData(n));
3834
3868
  }
3835
- processSegmentGroup(config, segmentGroup, outlet) {
3869
+ processSegmentGroup(injector, config, segmentGroup, outlet) {
3836
3870
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
3837
- return this.processChildren(config, segmentGroup);
3871
+ return this.processChildren(injector, config, segmentGroup);
3838
3872
  }
3839
- return this.processSegment(config, segmentGroup, segmentGroup.segments, outlet);
3873
+ return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet);
3840
3874
  }
3841
3875
  /**
3842
3876
  * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
@@ -3846,102 +3880,125 @@ class Recognizer {
3846
3880
  * @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the
3847
3881
  * config.
3848
3882
  */
3849
- processChildren(config, segmentGroup) {
3850
- const children = [];
3851
- for (const childOutlet of Object.keys(segmentGroup.children)) {
3883
+ processChildren(injector, config, segmentGroup) {
3884
+ return from(Object.keys(segmentGroup.children))
3885
+ .pipe(concatMap(childOutlet => {
3852
3886
  const child = segmentGroup.children[childOutlet];
3853
- // Sort the config so that routes with outlets that match the one being activated appear
3854
- // first, followed by routes for other outlets, which might match if they have an empty path.
3887
+ // Sort the config so that routes with outlets that match the one being activated
3888
+ // appear first, followed by routes for other outlets, which might match if they have
3889
+ // an empty path.
3855
3890
  const sortedConfig = sortByMatchingOutlets(config, childOutlet);
3856
- const outletChildren = this.processSegmentGroup(sortedConfig, child, childOutlet);
3857
- if (outletChildren === null) {
3858
- // Configs must match all segment children so because we did not find a match for this
3859
- // outlet, return `null`.
3891
+ return this.processSegmentGroup(injector, sortedConfig, child, childOutlet);
3892
+ }), scan((children, outletChildren) => {
3893
+ if (!children || !outletChildren)
3860
3894
  return null;
3861
- }
3862
3895
  children.push(...outletChildren);
3863
- }
3864
- // Because we may have matched two outlets to the same empty path segment, we can have multiple
3865
- // activated results for the same outlet. We should merge the children of these results so the
3866
- // final return value is only one `TreeNode` per outlet.
3867
- const mergedChildren = mergeEmptyPathMatches(children);
3868
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
3869
- // This should really never happen - we are only taking the first match for each outlet and
3870
- // merge the empty path matches.
3871
- checkOutletNameUniqueness(mergedChildren);
3872
- }
3873
- sortActivatedRouteSnapshots(mergedChildren);
3874
- return mergedChildren;
3875
- }
3876
- processSegment(config, segmentGroup, segments, outlet) {
3877
- for (const r of config) {
3878
- const children = this.processSegmentAgainstRoute(r, segmentGroup, segments, outlet);
3879
- if (children !== null) {
3880
- return children;
3896
+ return children;
3897
+ }), takeWhile(children => children !== null), defaultIfEmpty(null), last$1(), map(children => {
3898
+ if (children === null)
3899
+ return null;
3900
+ // Because we may have matched two outlets to the same empty path segment, we can have
3901
+ // multiple activated results for the same outlet. We should merge the children of
3902
+ // these results so the final return value is only one `TreeNode` per outlet.
3903
+ const mergedChildren = mergeEmptyPathMatches(children);
3904
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
3905
+ // This should really never happen - we are only taking the first match for each
3906
+ // outlet and merge the empty path matches.
3907
+ checkOutletNameUniqueness(mergedChildren);
3881
3908
  }
3882
- }
3883
- if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
3884
- return [];
3885
- }
3886
- return null;
3909
+ sortActivatedRouteSnapshots(mergedChildren);
3910
+ return mergedChildren;
3911
+ }));
3912
+ }
3913
+ processSegment(injector, routes, segmentGroup, segments, outlet) {
3914
+ return from(routes).pipe(concatMap(r => {
3915
+ return this.processSegmentAgainstRoute(r._injector ?? injector, r, segmentGroup, segments, outlet);
3916
+ }), first((x) => !!x), catchError(e => {
3917
+ if (e instanceof EmptyError) {
3918
+ if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
3919
+ return of([]);
3920
+ }
3921
+ return of(null);
3922
+ }
3923
+ throw e;
3924
+ }));
3887
3925
  }
3888
- processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
3926
+ processSegmentAgainstRoute(injector, route, rawSegment, segments, outlet) {
3889
3927
  if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet))
3890
- return null;
3891
- let snapshot;
3892
- let consumedSegments = [];
3893
- let remainingSegments = [];
3928
+ return of(null);
3929
+ let matchResult;
3894
3930
  if (route.path === '**') {
3895
3931
  const params = segments.length > 0 ? last(segments).parameters : {};
3896
3932
  const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;
3897
- 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),
3933
+ const 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),
3898
3934
  // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting
3899
3935
  // production bundle size. This value is intended only to surface a warning to users
3900
3936
  // depending on `relativeLinkResolution: 'legacy'` in dev mode.
3901
- (NG_DEV_MODE$2 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3937
+ (NG_DEV_MODE$3 ? getCorrectedPathIndexShift(rawSegment) + segments.length :
3902
3938
  pathIndexShift));
3939
+ matchResult = of({
3940
+ snapshot,
3941
+ consumedSegments: [],
3942
+ remainingSegments: [],
3943
+ });
3903
3944
  }
3904
3945
  else {
3905
- const result = match(rawSegment, route, segments);
3906
- if (!result.matched) {
3907
- return null;
3908
- }
3909
- consumedSegments = result.consumedSegments;
3910
- remainingSegments = result.remainingSegments;
3911
- const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3912
- 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 :
3913
- pathIndexShift));
3946
+ matchResult =
3947
+ matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer)
3948
+ .pipe(map(({ matched, consumedSegments, remainingSegments, parameters }) => {
3949
+ if (!matched) {
3950
+ return null;
3951
+ }
3952
+ const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;
3953
+ const snapshot = new ActivatedRouteSnapshot(consumedSegments, 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$3 ?
3954
+ getCorrectedPathIndexShift(rawSegment) + consumedSegments.length :
3955
+ pathIndexShift));
3956
+ return { snapshot, consumedSegments, remainingSegments };
3957
+ }));
3914
3958
  }
3915
- const childConfig = getChildConfig(route);
3916
- const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
3917
- // Filter out routes with redirectTo because we are trying to create activated route
3918
- // snapshots and don't handle redirects here. That should have been done in
3919
- // `applyRedirects`.
3920
- childConfig.filter(c => c.redirectTo === undefined), this.relativeLinkResolution);
3921
- if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3922
- const children = this.processChildren(childConfig, segmentGroup);
3923
- if (children === null) {
3924
- return null;
3959
+ return matchResult.pipe(switchMap((result) => {
3960
+ if (result === null) {
3961
+ return of(null);
3925
3962
  }
3926
- return [new TreeNode(snapshot, children)];
3927
- }
3928
- if (childConfig.length === 0 && slicedSegments.length === 0) {
3929
- return [new TreeNode(snapshot, [])];
3930
- }
3931
- const matchedOnOutlet = getOutlet(route) === outlet;
3932
- // If we matched a config due to empty path match on a different outlet, we need to continue
3933
- // passing the current outlet for the segment rather than switch to PRIMARY.
3934
- // Note that we switch to primary when we have a match because outlet configs look like this:
3935
- // {path: 'a', outlet: 'a', children: [
3936
- // {path: 'b', component: B},
3937
- // {path: 'c', component: C},
3938
- // ]}
3939
- // Notice that the children of the named outlet are configured with the primary outlet
3940
- const children = this.processSegment(childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet);
3941
- if (children === null) {
3942
- return null;
3943
- }
3944
- return [new TreeNode(snapshot, children)];
3963
+ const { snapshot, consumedSegments, remainingSegments } = result;
3964
+ // If the route has an injector created from providers, we should start using that.
3965
+ injector = route._injector ?? injector;
3966
+ const childInjector = route._loadedInjector ?? injector;
3967
+ const childConfig = getChildConfig(route);
3968
+ const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments,
3969
+ // Filter out routes with redirectTo because we are trying to create activated route
3970
+ // snapshots and don't handle redirects here. That should have been done in
3971
+ // `applyRedirects`.
3972
+ childConfig.filter(c => c.redirectTo === undefined), this.relativeLinkResolution);
3973
+ if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3974
+ return this.processChildren(childInjector, childConfig, segmentGroup).pipe(map(children => {
3975
+ if (children === null) {
3976
+ return null;
3977
+ }
3978
+ return [new TreeNode(snapshot, children)];
3979
+ }));
3980
+ }
3981
+ if (childConfig.length === 0 && slicedSegments.length === 0) {
3982
+ return of([new TreeNode(snapshot, [])]);
3983
+ }
3984
+ const matchedOnOutlet = getOutlet(route) === outlet;
3985
+ // If we matched a config due to empty path match on a different outlet, we need to
3986
+ // continue passing the current outlet for the segment rather than switch to PRIMARY.
3987
+ // Note that we switch to primary when we have a match because outlet configs look like
3988
+ // this: {path: 'a', outlet: 'a', children: [
3989
+ // {path: 'b', component: B},
3990
+ // {path: 'c', component: C},
3991
+ // ]}
3992
+ // Notice that the children of the named outlet are configured with the primary outlet
3993
+ return this
3994
+ .processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet)
3995
+ .pipe(map(children => {
3996
+ if (children === null) {
3997
+ return null;
3998
+ }
3999
+ return [new TreeNode(snapshot, children)];
4000
+ }));
4001
+ }));
3945
4002
  }
3946
4003
  }
3947
4004
  function sortActivatedRouteSnapshots(nodes) {
@@ -3967,9 +4024,9 @@ function hasEmptyPathConfig(node) {
3967
4024
  return config && config.path === '' && config.redirectTo === undefined;
3968
4025
  }
3969
4026
  /**
3970
- * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with the
3971
- * children from each duplicate. This is necessary because different outlets can match a single
3972
- * empty path route config and the results need to then be merged.
4027
+ * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with
4028
+ * the children from each duplicate. This is necessary because different outlets can match a
4029
+ * single empty path route config and the results need to then be merged.
3973
4030
  */
3974
4031
  function mergeEmptyPathMatches(nodes) {
3975
4032
  const result = [];
@@ -3990,9 +4047,9 @@ function mergeEmptyPathMatches(nodes) {
3990
4047
  }
3991
4048
  }
3992
4049
  // For each node which has children from multiple sources, we need to recompute a new `TreeNode`
3993
- // by also merging those children. This is necessary when there are multiple empty path configs in
3994
- // a row. Put another way: whenever we combine children of two nodes, we need to also check if any
3995
- // of those children can be combined into a single node as well.
4050
+ // by also merging those children. This is necessary when there are multiple empty path configs
4051
+ // in a row. Put another way: whenever we combine children of two nodes, we need to also check
4052
+ // if any of those children can be combined into a single node as well.
3996
4053
  for (const mergedNode of mergedNodes) {
3997
4054
  const mergedChildren = mergeEmptyPathMatches(mergedNode.children);
3998
4055
  result.push(new TreeNode(mergedNode.value, mergedChildren));
@@ -4050,8 +4107,8 @@ function getResolve(route) {
4050
4107
  * Use of this source code is governed by an MIT-style license that can be
4051
4108
  * found in the LICENSE file at https://angular.io/license
4052
4109
  */
4053
- function recognize(rootComponentType, config, serializer, paramsInheritanceStrategy, relativeLinkResolution) {
4054
- return mergeMap(t => recognize$1(rootComponentType, config, t.urlAfterRedirects, serializer(t.urlAfterRedirects), paramsInheritanceStrategy, relativeLinkResolution)
4110
+ function recognize(injector, rootComponentType, config, serializer, paramsInheritanceStrategy, relativeLinkResolution) {
4111
+ return mergeMap(t => recognize$1(injector, rootComponentType, config, t.urlAfterRedirects, serializer.serialize(t.urlAfterRedirects), serializer, paramsInheritanceStrategy, relativeLinkResolution)
4055
4112
  .pipe(map(targetSnapshot => ({ ...t, targetSnapshot }))));
4056
4113
  }
4057
4114
 
@@ -4213,7 +4270,7 @@ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4213
4270
  * Use of this source code is governed by an MIT-style license that can be
4214
4271
  * found in the LICENSE file at https://angular.io/license
4215
4272
  */
4216
- const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4273
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4217
4274
  /**
4218
4275
  * The [DI token](guide/glossary/#di-token) for a router configuration.
4219
4276
  *
@@ -4247,7 +4304,7 @@ class RouterConfigLoader {
4247
4304
  if (this.onLoadEndListener) {
4248
4305
  this.onLoadEndListener(route);
4249
4306
  }
4250
- NG_DEV_MODE$1 && assertStandalone(route.path ?? '', component);
4307
+ NG_DEV_MODE$2 && assertStandalone(route.path ?? '', component);
4251
4308
  route._loadedComponent = component;
4252
4309
  }), finalize(() => {
4253
4310
  this.componentLoaders.delete(route);
@@ -4290,7 +4347,7 @@ class RouterConfigLoader {
4290
4347
  rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
4291
4348
  }
4292
4349
  const routes = rawRoutes.map(standardizeConfig);
4293
- NG_DEV_MODE$1 && validateConfig(routes, route.path, requireStandaloneComponents);
4350
+ NG_DEV_MODE$2 && validateConfig(routes, route.path, requireStandaloneComponents);
4294
4351
  return { routes, injector };
4295
4352
  }), finalize(() => {
4296
4353
  this.childrenLoaders.delete(route);
@@ -4312,9 +4369,9 @@ class RouterConfigLoader {
4312
4369
  }));
4313
4370
  }
4314
4371
  }
4315
- RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4316
- RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterConfigLoader });
4317
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterConfigLoader, decorators: [{
4372
+ RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4373
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterConfigLoader });
4374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterConfigLoader, decorators: [{
4318
4375
  type: Injectable
4319
4376
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
4320
4377
 
@@ -4356,19 +4413,13 @@ class DefaultUrlHandlingStrategy {
4356
4413
  * Use of this source code is governed by an MIT-style license that can be
4357
4414
  * found in the LICENSE file at https://angular.io/license
4358
4415
  */
4359
- const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
4416
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4360
4417
  function defaultErrorHandler(error) {
4361
4418
  throw error;
4362
4419
  }
4363
4420
  function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
4364
4421
  return urlSerializer.parse('/');
4365
4422
  }
4366
- /**
4367
- * @internal
4368
- */
4369
- function defaultRouterHook(snapshot, runExtras) {
4370
- return of(null);
4371
- }
4372
4423
  /**
4373
4424
  * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
4374
4425
  * (exact = true).
@@ -4448,13 +4499,12 @@ class Router {
4448
4499
  this.navigated = false;
4449
4500
  this.lastSuccessfulId = -1;
4450
4501
  /**
4451
- * Hooks that enable you to pause navigation,
4452
- * either before or after the preactivation phase.
4502
+ * Hook that enables you to pause navigation after the preactivation phase.
4453
4503
  * Used by `RouterModule`.
4454
4504
  *
4455
4505
  * @internal
4456
4506
  */
4457
- this.hooks = { beforePreactivation: defaultRouterHook, afterPreactivation: defaultRouterHook };
4507
+ this.afterPreactivation = () => of(void 0);
4458
4508
  /**
4459
4509
  * A strategy for extracting and merging URLs.
4460
4510
  * Used for AngularJS to Angular migrations.
@@ -4634,7 +4684,7 @@ class Router {
4634
4684
  };
4635
4685
  }),
4636
4686
  // Recognize
4637
- recognize(this.rootComponentType, this.config, (url) => this.serializeUrl(url), this.paramsInheritanceStrategy, this.relativeLinkResolution),
4687
+ recognize(this.ngModule.injector, this.rootComponentType, this.config, this.urlSerializer, this.paramsInheritanceStrategy, this.relativeLinkResolution),
4638
4688
  // Update URL if in `eager` update mode
4639
4689
  tap(t => {
4640
4690
  if (this.urlUpdateStrategy === 'eager') {
@@ -4679,17 +4729,6 @@ class Router {
4679
4729
  }
4680
4730
  }
4681
4731
  }),
4682
- // Before Preactivation
4683
- switchTap(t => {
4684
- const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
4685
- return this.hooks.beforePreactivation(targetSnapshot, {
4686
- navigationId,
4687
- appliedUrlTree,
4688
- rawUrlTree,
4689
- skipLocationChange: !!skipLocationChange,
4690
- replaceUrl: !!replaceUrl,
4691
- });
4692
- }),
4693
4732
  // --- GUARDS ---
4694
4733
  tap(t => {
4695
4734
  const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
@@ -4736,18 +4775,7 @@ class Router {
4736
4775
  }));
4737
4776
  }
4738
4777
  return undefined;
4739
- }),
4740
- // --- AFTER PREACTIVATION ---
4741
- switchTap((t) => {
4742
- const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
4743
- return this.hooks.afterPreactivation(targetSnapshot, {
4744
- navigationId,
4745
- appliedUrlTree,
4746
- rawUrlTree,
4747
- skipLocationChange: !!skipLocationChange,
4748
- replaceUrl: !!replaceUrl,
4749
- });
4750
- }),
4778
+ }), switchTap(() => this.afterPreactivation()),
4751
4779
  // --- LOAD COMPONENTS ---
4752
4780
  switchTap((t) => {
4753
4781
  const loadComponents = (route) => {
@@ -4964,7 +4992,7 @@ class Router {
4964
4992
  * ```
4965
4993
  */
4966
4994
  resetConfig(config) {
4967
- NG_DEV_MODE && validateConfig(config);
4995
+ NG_DEV_MODE$1 && validateConfig(config);
4968
4996
  this.config = config.map(standardizeConfig);
4969
4997
  this.navigated = false;
4970
4998
  this.lastSuccessfulId = -1;
@@ -5319,9 +5347,9 @@ class Router {
5319
5347
  return { navigationId };
5320
5348
  }
5321
5349
  }
5322
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5323
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: Router });
5324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: Router, decorators: [{
5350
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5351
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: Router });
5352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: Router, decorators: [{
5325
5353
  type: Injectable
5326
5354
  }], ctorParameters: function () { return [{ type: i0.Type }, { type: UrlSerializer }, { type: ChildrenOutletContexts }, { type: i3.Location }, { type: i0.Injector }, { type: i0.Compiler }, { type: undefined }]; } });
5327
5355
  function validateCommands(commands) {
@@ -5520,9 +5548,9 @@ class RouterLink {
5520
5548
  });
5521
5549
  }
5522
5550
  }
5523
- RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5524
- RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.0", 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 });
5525
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterLink, decorators: [{
5551
+ RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
5552
+ RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.3", 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 });
5553
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterLink, decorators: [{
5526
5554
  type: Directive,
5527
5555
  args: [{ selector: ':not(a):not(area)[routerLink]' }]
5528
5556
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
@@ -5639,9 +5667,9 @@ class RouterLinkWithHref {
5639
5667
  });
5640
5668
  }
5641
5669
  }
5642
- RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5643
- RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.0", 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 });
5644
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5670
+ RouterLinkWithHref.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterLinkWithHref, deps: [{ token: Router }, { token: ActivatedRoute }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
5671
+ RouterLinkWithHref.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.3", 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 });
5672
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterLinkWithHref, decorators: [{
5645
5673
  type: Directive,
5646
5674
  args: [{ selector: 'a[routerLink],area[routerLink]' }]
5647
5675
  }], ctorParameters: function () { return [{ type: Router }, { type: ActivatedRoute }, { type: i3.LocationStrategy }]; }, propDecorators: { target: [{
@@ -5866,9 +5894,9 @@ class RouterLinkActive {
5866
5894
  this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
5867
5895
  }
5868
5896
  }
5869
- RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", 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 });
5870
- RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.0", 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 });
5871
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterLinkActive, decorators: [{
5897
+ RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", 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 });
5898
+ RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.0-next.3", 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 });
5899
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterLinkActive, decorators: [{
5872
5900
  type: Directive,
5873
5901
  args: [{
5874
5902
  selector: '[routerLinkActive]',
@@ -5971,9 +5999,9 @@ class DefaultTitleStrategy extends TitleStrategy {
5971
5999
  }
5972
6000
  }
5973
6001
  }
5974
- DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
5975
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
5976
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
6002
+ DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
6003
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
6004
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
5977
6005
  type: Injectable,
5978
6006
  args: [{ providedIn: 'root' }]
5979
6007
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -6010,6 +6038,12 @@ class PreloadAllModules {
6010
6038
  return fn().pipe(catchError(() => of(null)));
6011
6039
  }
6012
6040
  }
6041
+ PreloadAllModules.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6042
+ PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
6043
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: PreloadAllModules, decorators: [{
6044
+ type: Injectable,
6045
+ args: [{ providedIn: 'root' }]
6046
+ }] });
6013
6047
  /**
6014
6048
  * @description
6015
6049
  *
@@ -6024,6 +6058,12 @@ class NoPreloading {
6024
6058
  return of(null);
6025
6059
  }
6026
6060
  }
6061
+ NoPreloading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6062
+ NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: NoPreloading, providedIn: 'root' });
6063
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: NoPreloading, decorators: [{
6064
+ type: Injectable,
6065
+ args: [{ providedIn: 'root' }]
6066
+ }] });
6027
6067
  /**
6028
6068
  * The preloader optimistically loads all router configurations to
6029
6069
  * make navigations into lazily-loaded sections of the application faster.
@@ -6106,9 +6146,9 @@ class RouterPreloader {
6106
6146
  });
6107
6147
  }
6108
6148
  }
6109
- RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
6110
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterPreloader });
6111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterPreloader, decorators: [{
6149
+ RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
6150
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterPreloader });
6151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterPreloader, decorators: [{
6112
6152
  type: Injectable
6113
6153
  }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
6114
6154
 
@@ -6119,6 +6159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0",
6119
6159
  * Use of this source code is governed by an MIT-style license that can be
6120
6160
  * found in the LICENSE file at https://angular.io/license
6121
6161
  */
6162
+ const ROUTER_SCROLLER = new InjectionToken('');
6122
6163
  class RouterScroller {
6123
6164
  constructor(router,
6124
6165
  /** @docsNotRequired */ viewportScroller, options = {}) {
@@ -6194,9 +6235,9 @@ class RouterScroller {
6194
6235
  }
6195
6236
  }
6196
6237
  }
6197
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6198
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterScroller });
6199
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterScroller, decorators: [{
6238
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6239
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterScroller });
6240
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterScroller, decorators: [{
6200
6241
  type: Injectable
6201
6242
  }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: undefined }]; } });
6202
6243
 
@@ -6207,6 +6248,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0",
6207
6248
  * Use of this source code is governed by an MIT-style license that can be
6208
6249
  * found in the LICENSE file at https://angular.io/license
6209
6250
  */
6251
+ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
6210
6252
  /**
6211
6253
  * The directives defined in the `RouterModule`.
6212
6254
  */
@@ -6216,11 +6258,15 @@ const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterL
6216
6258
  *
6217
6259
  * @publicApi
6218
6260
  */
6219
- const ROUTER_CONFIGURATION = new InjectionToken('ROUTER_CONFIGURATION');
6261
+ const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE ? 'router config' : 'ROUTER_CONFIGURATION', {
6262
+ providedIn: 'root',
6263
+ factory: () => ({}),
6264
+ });
6220
6265
  /**
6221
6266
  * @docsNotRequired
6222
6267
  */
6223
- const ROUTER_FORROOT_GUARD = new InjectionToken('ROUTER_FORROOT_GUARD');
6268
+ const ROUTER_FORROOT_GUARD = new InjectionToken(NG_DEV_MODE ? 'router duplicate forRoot guard' : 'ROUTER_FORROOT_GUARD');
6269
+ const ROUTER_PRELOADER = new InjectionToken(NG_DEV_MODE ? 'router preloader' : '');
6224
6270
  const ROUTER_PROVIDERS = [
6225
6271
  Location,
6226
6272
  { provide: UrlSerializer, useClass: DefaultUrlSerializer },
@@ -6235,10 +6281,6 @@ const ROUTER_PROVIDERS = [
6235
6281
  },
6236
6282
  ChildrenOutletContexts,
6237
6283
  { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
6238
- RouterPreloader,
6239
- NoPreloading,
6240
- PreloadAllModules,
6241
- { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } },
6242
6284
  RouterConfigLoader,
6243
6285
  ];
6244
6286
  function routerNgProbeToken() {
@@ -6291,6 +6333,7 @@ class RouterModule {
6291
6333
  ngModule: RouterModule,
6292
6334
  providers: [
6293
6335
  ROUTER_PROVIDERS,
6336
+ NG_DEV_MODE ? (config?.enableTracing ? provideTracing() : []) : [],
6294
6337
  provideRoutes(routes),
6295
6338
  {
6296
6339
  provide: ROUTER_FORROOT_GUARD,
@@ -6298,22 +6341,11 @@ class RouterModule {
6298
6341
  deps: [[Router, new Optional(), new SkipSelf()]]
6299
6342
  },
6300
6343
  { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
6301
- {
6302
- provide: LocationStrategy,
6303
- useFactory: provideLocationStrategy,
6304
- deps: [PlatformLocation, [new Inject(APP_BASE_HREF), new Optional()], ROUTER_CONFIGURATION]
6305
- },
6306
- {
6307
- provide: RouterScroller,
6308
- useFactory: createRouterScroller,
6309
- deps: [Router, ViewportScroller, ROUTER_CONFIGURATION]
6310
- },
6311
- {
6312
- provide: PreloadingStrategy,
6313
- useExisting: config && config.preloadingStrategy ? config.preloadingStrategy :
6314
- NoPreloading
6315
- },
6344
+ config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(),
6345
+ provideRouterScroller(),
6346
+ config?.preloadingStrategy ? providePreloading(config.preloadingStrategy) : [],
6316
6347
  { provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken },
6348
+ config?.initialNavigation ? provideInitialNavigation(config) : [],
6317
6349
  provideRouterInitializer(),
6318
6350
  ],
6319
6351
  };
@@ -6338,10 +6370,10 @@ class RouterModule {
6338
6370
  return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
6339
6371
  }
6340
6372
  }
6341
- RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6342
- RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
6343
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterModule });
6344
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterModule, decorators: [{
6373
+ RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }, { token: Router, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6374
+ RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterModule, declarations: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] });
6375
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterModule });
6376
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.3", ngImport: i0, type: RouterModule, decorators: [{
6345
6377
  type: NgModule,
6346
6378
  args: [{
6347
6379
  declarations: ROUTER_DIRECTIVES,
@@ -6355,18 +6387,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0",
6355
6387
  }] }, { type: Router, decorators: [{
6356
6388
  type: Optional
6357
6389
  }] }]; } });
6358
- function createRouterScroller(router, viewportScroller, config) {
6359
- if (config.scrollOffset) {
6360
- viewportScroller.setOffset(config.scrollOffset);
6361
- }
6362
- return new RouterScroller(router, viewportScroller, config);
6390
+ function provideRouterScroller() {
6391
+ return {
6392
+ provide: ROUTER_SCROLLER,
6393
+ useFactory: () => {
6394
+ const router = inject(Router);
6395
+ const viewportScroller = inject(ViewportScroller);
6396
+ const config = inject(ROUTER_CONFIGURATION);
6397
+ if (config.scrollOffset) {
6398
+ viewportScroller.setOffset(config.scrollOffset);
6399
+ }
6400
+ return new RouterScroller(router, viewportScroller, config);
6401
+ },
6402
+ };
6363
6403
  }
6364
- function provideLocationStrategy(platformLocationStrategy, baseHref, options = {}) {
6365
- return options.useHash ? new HashLocationStrategy(platformLocationStrategy, baseHref) :
6366
- new PathLocationStrategy(platformLocationStrategy, baseHref);
6404
+ function provideHashLocationStrategy() {
6405
+ return { provide: LocationStrategy, useClass: HashLocationStrategy };
6406
+ }
6407
+ function providePathLocationStrategy() {
6408
+ return { provide: LocationStrategy, useClass: PathLocationStrategy };
6367
6409
  }
6368
6410
  function provideForRootGuard(router) {
6369
- if ((typeof ngDevMode === 'undefined' || ngDevMode) && router) {
6411
+ if (NG_DEV_MODE && router) {
6370
6412
  throw new Error(`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
6371
6413
  }
6372
6414
  return 'guarded';
@@ -6403,16 +6445,6 @@ function setupRouter(urlSerializer, contexts, location, injector, compiler, conf
6403
6445
  }
6404
6446
  router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
6405
6447
  assignExtraOptionsToRouter(opts, router);
6406
- if ((typeof ngDevMode === 'undefined' || ngDevMode) && opts.enableTracing) {
6407
- router.events.subscribe((e) => {
6408
- // tslint:disable:no-console
6409
- console.group?.(`Router Event: ${e.constructor.name}`);
6410
- console.log(stringifyEvent(e));
6411
- console.log(e);
6412
- console.groupEnd?.();
6413
- // tslint:enable:no-console
6414
- });
6415
- }
6416
6448
  return router;
6417
6449
  }
6418
6450
  function assignExtraOptionsToRouter(opts, router) {
@@ -6441,112 +6473,136 @@ function assignExtraOptionsToRouter(opts, router) {
6441
6473
  function rootRoute(router) {
6442
6474
  return router.routerState.root;
6443
6475
  }
6444
- /**
6445
- * Router initialization requires two steps:
6446
- *
6447
- * First, we start the navigation in a `APP_INITIALIZER` to block the bootstrap if
6448
- * a resolver or a guard executes asynchronously.
6449
- *
6450
- * Next, we actually run activation in a `BOOTSTRAP_LISTENER`, using the
6451
- * `afterPreactivation` hook provided by the router.
6452
- * The router navigation starts, reaches the point when preactivation is done, and then
6453
- * pauses. It waits for the hook to be resolved. We then resolve it only in a bootstrap listener.
6454
- */
6455
- class RouterInitializer {
6456
- constructor(injector) {
6457
- this.injector = injector;
6458
- this.initNavigation = false;
6459
- this.destroyed = false;
6460
- this.resultOfPreactivationDone = new Subject();
6461
- }
6462
- appInitializer() {
6463
- const p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
6464
- return p.then(() => {
6465
- // If the injector was destroyed, the DI lookups below will fail.
6466
- if (this.destroyed) {
6467
- return Promise.resolve(true);
6468
- }
6469
- let resolve = null;
6470
- const res = new Promise(r => resolve = r);
6471
- const router = this.injector.get(Router);
6472
- const opts = this.injector.get(ROUTER_CONFIGURATION);
6473
- if (opts.initialNavigation === 'disabled') {
6474
- router.setUpLocationChangeListener();
6475
- resolve(true);
6476
- }
6477
- else if (opts.initialNavigation === 'enabledBlocking') {
6478
- router.hooks.afterPreactivation = () => {
6479
- // only the initial navigation should be delayed
6480
- if (!this.initNavigation) {
6481
- this.initNavigation = true;
6482
- resolve(true);
6483
- return this.resultOfPreactivationDone;
6484
- // subsequent navigations should not be delayed
6485
- }
6486
- else {
6487
- return of(null);
6488
- }
6489
- };
6490
- router.initialNavigation();
6491
- }
6492
- else {
6493
- resolve(true);
6494
- }
6495
- return res;
6496
- });
6497
- }
6498
- bootstrapListener(bootstrappedComponentRef) {
6499
- const opts = this.injector.get(ROUTER_CONFIGURATION);
6500
- const preloader = this.injector.get(RouterPreloader);
6501
- const routerScroller = this.injector.get(RouterScroller);
6502
- const router = this.injector.get(Router);
6503
- const ref = this.injector.get(ApplicationRef);
6476
+ function getBootstrapListener() {
6477
+ const injector = inject(Injector);
6478
+ return (bootstrappedComponentRef) => {
6479
+ const ref = injector.get(ApplicationRef);
6504
6480
  if (bootstrappedComponentRef !== ref.components[0]) {
6505
6481
  return;
6506
6482
  }
6483
+ const router = injector.get(Router);
6484
+ const bootstrapDone = injector.get(BOOTSTRAP_DONE);
6507
6485
  // Default case
6508
- if (opts.initialNavigation === 'enabledNonBlocking' || opts.initialNavigation === undefined) {
6486
+ if (injector.get(INITIAL_NAVIGATION, null, InjectFlags.Optional) === null) {
6509
6487
  router.initialNavigation();
6510
6488
  }
6511
- preloader.setUpPreloading();
6512
- routerScroller.init();
6489
+ injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
6490
+ injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
6513
6491
  router.resetRootComponentType(ref.componentTypes[0]);
6514
- this.resultOfPreactivationDone.next(null);
6515
- this.resultOfPreactivationDone.complete();
6516
- }
6517
- ngOnDestroy() {
6518
- this.destroyed = true;
6519
- }
6520
- }
6521
- RouterInitializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterInitializer, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
6522
- RouterInitializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterInitializer });
6523
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0-next.0", ngImport: i0, type: RouterInitializer, decorators: [{
6524
- type: Injectable
6525
- }], ctorParameters: function () { return [{ type: i0.Injector }]; } });
6526
- function getAppInitializer(r) {
6527
- return r.appInitializer.bind(r);
6528
- }
6529
- function getBootstrapListener(r) {
6530
- return r.bootstrapListener.bind(r);
6492
+ bootstrapDone.next();
6493
+ bootstrapDone.complete();
6494
+ };
6531
6495
  }
6496
+ // TODO(atscott): This should not be in the public API
6532
6497
  /**
6533
6498
  * A [DI token](guide/glossary/#di-token) for the router initializer that
6534
6499
  * is called after the app is bootstrapped.
6535
6500
  *
6536
6501
  * @publicApi
6537
6502
  */
6538
- const ROUTER_INITIALIZER = new InjectionToken('Router Initializer');
6503
+ const ROUTER_INITIALIZER = new InjectionToken(NG_DEV_MODE ? 'Router Initializer' : '');
6504
+ function provideInitialNavigation(config) {
6505
+ return [
6506
+ config.initialNavigation === 'disabled' ? provideDisabledInitialNavigation() : [],
6507
+ config.initialNavigation === 'enabledBlocking' ? provideEnabledBlockingInitialNavigation() : [],
6508
+ ];
6509
+ }
6539
6510
  function provideRouterInitializer() {
6540
6511
  return [
6541
- RouterInitializer,
6512
+ // ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
6513
+ // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.
6514
+ { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener },
6515
+ { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
6516
+ ];
6517
+ }
6518
+ /**
6519
+ * A subject used to indicate that the bootstrapping phase is done. When initial navigation is
6520
+ * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing
6521
+ * to the activation phase.
6522
+ */
6523
+ const BOOTSTRAP_DONE = new InjectionToken(NG_DEV_MODE ? 'bootstrap done indicator' : '', {
6524
+ factory: () => {
6525
+ return new Subject();
6526
+ }
6527
+ });
6528
+ function provideEnabledBlockingInitialNavigation() {
6529
+ return [
6530
+ { provide: INITIAL_NAVIGATION, useValue: 'enabledBlocking' },
6542
6531
  {
6543
6532
  provide: APP_INITIALIZER,
6544
6533
  multi: true,
6545
- useFactory: getAppInitializer,
6546
- deps: [RouterInitializer]
6534
+ deps: [Injector],
6535
+ useFactory: (injector) => {
6536
+ const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
6537
+ let initNavigation = false;
6538
+ return () => {
6539
+ return locationInitialized.then(() => {
6540
+ return new Promise(resolve => {
6541
+ const router = injector.get(Router);
6542
+ const bootstrapDone = injector.get(BOOTSTRAP_DONE);
6543
+ router.afterPreactivation = () => {
6544
+ // only the initial navigation should be delayed
6545
+ if (!initNavigation) {
6546
+ initNavigation = true;
6547
+ resolve(true);
6548
+ return bootstrapDone;
6549
+ // subsequent navigations should not be delayed
6550
+ }
6551
+ else {
6552
+ return of(void 0);
6553
+ }
6554
+ };
6555
+ router.initialNavigation();
6556
+ });
6557
+ });
6558
+ };
6559
+ }
6547
6560
  },
6548
- { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener, deps: [RouterInitializer] },
6549
- { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
6561
+ ];
6562
+ }
6563
+ const INITIAL_NAVIGATION = new InjectionToken(NG_DEV_MODE ? 'initial navigation' : '');
6564
+ function provideDisabledInitialNavigation() {
6565
+ return [
6566
+ {
6567
+ provide: APP_INITIALIZER,
6568
+ multi: true,
6569
+ useFactory: () => {
6570
+ const router = inject(Router);
6571
+ return () => {
6572
+ router.setUpLocationChangeListener();
6573
+ };
6574
+ }
6575
+ },
6576
+ { provide: INITIAL_NAVIGATION, useValue: 'disabled' }
6577
+ ];
6578
+ }
6579
+ function provideTracing() {
6580
+ if (NG_DEV_MODE) {
6581
+ return [{
6582
+ provide: ENVIRONMENT_INITIALIZER,
6583
+ multi: true,
6584
+ useFactory: () => {
6585
+ const router = inject(Router);
6586
+ return () => router.events.subscribe((e) => {
6587
+ // tslint:disable:no-console
6588
+ console.group?.(`Router Event: ${e.constructor.name}`);
6589
+ console.log(stringifyEvent(e));
6590
+ console.log(e);
6591
+ console.groupEnd?.();
6592
+ // tslint:enable:no-console
6593
+ });
6594
+ }
6595
+ }];
6596
+ }
6597
+ else {
6598
+ return [];
6599
+ }
6600
+ }
6601
+ function providePreloading(preloadingStrategy) {
6602
+ return [
6603
+ RouterPreloader,
6604
+ { provide: ROUTER_PRELOADER, useExisting: RouterPreloader },
6605
+ { provide: PreloadingStrategy, useExisting: preloadingStrategy },
6550
6606
  ];
6551
6607
  }
6552
6608
 
@@ -6560,7 +6616,7 @@ function provideRouterInitializer() {
6560
6616
  /**
6561
6617
  * @publicApi
6562
6618
  */
6563
- const VERSION = new Version('14.1.0-next.0');
6619
+ const VERSION = new Version('14.1.0-next.3');
6564
6620
 
6565
6621
  /**
6566
6622
  * @license
@@ -6599,5 +6655,5 @@ const VERSION = new Version('14.1.0-next.0');
6599
6655
  * Generated bundle index. Do not edit.
6600
6656
  */
6601
6657
 
6602
- export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, provideRoutes, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, assignExtraOptionsToRouter as ɵassignExtraOptionsToRouter, flatten as ɵflatten };
6658
+ export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, provideRoutes, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, assignExtraOptionsToRouter as ɵassignExtraOptionsToRouter, flatten as ɵflatten, providePreloading as ɵprovidePreloading };
6603
6659
  //# sourceMappingURL=router.mjs.map