@angular/router 21.0.0-next.0 → 21.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  /**
2
- * @license Angular v21.0.0-next.0
2
+ * @license Angular v21.0.0-next.2
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { DOCUMENT, Location } from '@angular/common';
8
8
  import * as i0 from '@angular/core';
9
- import { ɵisPromise as _isPromise, ɵRuntimeError as _RuntimeError, Injectable, ɵisNgModule as _isNgModule, isStandalone, createEnvironmentInjector, InjectionToken, EventEmitter, input, inject, ViewContainerRef, ChangeDetectorRef, Directive, Input, Output, reflectComponentType, Component, ɵisInjectable as _isInjectable, runInInjectionContext, Compiler, NgModuleFactory, ɵresolveComponentResources as _resolveComponentResources, afterNextRender, signal, EnvironmentInjector, DestroyRef, untracked, ɵConsole as _Console, ɵPendingTasksInternal as _PendingTasksInternal, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER } from '@angular/core';
10
- import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, concat, defer, pipe, throwError, EMPTY, ConnectableObservable, Subject, Observable, Subscription } from 'rxjs';
11
- import { map, switchMap, take, startWith, filter, mergeMap, first, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, finalize, refCount, takeUntil } from 'rxjs/operators';
9
+ import { ɵisPromise as _isPromise, ɵRuntimeError as _RuntimeError, Injectable, ɵisNgModule as _isNgModule, isStandalone, createEnvironmentInjector, InjectionToken, EventEmitter, input, inject, ViewContainerRef, ChangeDetectorRef, Directive, Input, Output, reflectComponentType, Component, ɵisInjectable as _isInjectable, runInInjectionContext, makeEnvironmentProviders, Compiler, NgModuleFactory, ɵresolveComponentResources as _resolveComponentResources, afterNextRender, signal, EnvironmentInjector, DestroyRef, untracked, ɵConsole as _Console, ɵPendingTasksInternal as _PendingTasksInternal, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER } from '@angular/core';
10
+ import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, Observable, concat, defer, pipe, throwError, EMPTY, ConnectableObservable, Subject, Subscription } from 'rxjs';
11
+ import { map, switchMap, take, startWith, filter, takeUntil, mergeMap, first, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, finalize, refCount } from 'rxjs/operators';
12
12
  import * as i1 from '@angular/platform-browser';
13
13
 
14
14
  /**
@@ -3569,6 +3569,28 @@ function isRedirect(val) {
3569
3569
  return isUrlTree(val) || val instanceof RedirectCommand;
3570
3570
  }
3571
3571
 
3572
+ /**
3573
+ * Converts an AbortSignal to an Observable<void>.
3574
+ * Emits and completes when the signal is aborted.
3575
+ * If the signal is already aborted, it emits and completes immediately.
3576
+ */
3577
+ function abortSignalToObservable(signal) {
3578
+ if (signal.aborted) {
3579
+ return of(undefined).pipe(take(1)); // Emit and complete immediately
3580
+ }
3581
+ return new Observable((subscriber) => {
3582
+ const handler = () => {
3583
+ subscriber.next();
3584
+ subscriber.complete();
3585
+ };
3586
+ signal.addEventListener('abort', handler);
3587
+ return () => signal.removeEventListener('abort', handler);
3588
+ });
3589
+ }
3590
+ function takeUntilAbort(signal) {
3591
+ return takeUntil(abortSignalToObservable(signal));
3592
+ }
3593
+
3572
3594
  function checkGuards(injector, forwardEvent) {
3573
3595
  return mergeMap((t) => {
3574
3596
  const { targetSnapshot, currentSnapshot, guards: { canActivateChecks, canDeactivateChecks }, } = t;
@@ -3674,7 +3696,7 @@ function runCanDeactivate(component, currARS, currRSS, futureRSS, injector) {
3674
3696
  });
3675
3697
  return of(canDeactivateObservables).pipe(prioritizedGuardValue());
3676
3698
  }
3677
- function runCanLoadGuards(injector, route, segments, urlSerializer) {
3699
+ function runCanLoadGuards(injector, route, segments, urlSerializer, abortSignal) {
3678
3700
  const canLoad = route.canLoad;
3679
3701
  if (canLoad === undefined || canLoad.length === 0) {
3680
3702
  return of(true);
@@ -3684,7 +3706,8 @@ function runCanLoadGuards(injector, route, segments, urlSerializer) {
3684
3706
  const guardVal = isCanLoad(guard)
3685
3707
  ? guard.canLoad(route, segments)
3686
3708
  : runInInjectionContext(injector, () => guard(route, segments));
3687
- return wrapIntoObservable(guardVal);
3709
+ const obs$ = wrapIntoObservable(guardVal);
3710
+ return abortSignal ? obs$.pipe(takeUntilAbort(abortSignal)) : obs$;
3688
3711
  });
3689
3712
  return of(canLoadObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
3690
3713
  }
@@ -3695,7 +3718,7 @@ function redirectIfUrlTree(urlSerializer) {
3695
3718
  throw redirectingNavigationError(urlSerializer, result);
3696
3719
  }), map((result) => result === true));
3697
3720
  }
3698
- function runCanMatchGuards(injector, route, segments, urlSerializer) {
3721
+ function runCanMatchGuards(injector, route, segments, urlSerializer, abortSignal) {
3699
3722
  const canMatch = route.canMatch;
3700
3723
  if (!canMatch || canMatch.length === 0)
3701
3724
  return of(true);
@@ -3704,67 +3727,79 @@ function runCanMatchGuards(injector, route, segments, urlSerializer) {
3704
3727
  const guardVal = isCanMatch(guard)
3705
3728
  ? guard.canMatch(route, segments)
3706
3729
  : runInInjectionContext(injector, () => guard(route, segments));
3707
- return wrapIntoObservable(guardVal);
3730
+ let obs$ = wrapIntoObservable(guardVal);
3731
+ return abortSignal ? obs$.pipe(takeUntilAbort(abortSignal)) : obs$;
3708
3732
  });
3709
3733
  return of(canMatchObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
3710
3734
  }
3711
3735
 
3712
- class NoMatch {
3736
+ /** replacement for firstValueFrom in rxjs 7. We must support rxjs v6 so we cannot use it */
3737
+ function firstValueFrom(source) {
3738
+ return new Promise((resolve, reject) => {
3739
+ source.pipe(first()).subscribe({
3740
+ next: (value) => resolve(value),
3741
+ error: (err) => reject(err),
3742
+ });
3743
+ });
3744
+ }
3745
+
3746
+ const NO_MATCH_ERROR_NAME = 'ɵNoMatch';
3747
+ let NoMatch$1 = class NoMatch extends Error {
3748
+ name = NO_MATCH_ERROR_NAME;
3713
3749
  segmentGroup;
3714
3750
  constructor(segmentGroup) {
3751
+ super();
3715
3752
  this.segmentGroup = segmentGroup || null;
3716
3753
  }
3717
- }
3718
- class AbsoluteRedirect extends Error {
3754
+ };
3755
+ const ABSOLUTE_REDIRECT_ERROR_NAME = 'ɵAbsoluteRedirect';
3756
+ let AbsoluteRedirect$1 = class AbsoluteRedirect extends Error {
3719
3757
  urlTree;
3758
+ name = ABSOLUTE_REDIRECT_ERROR_NAME;
3720
3759
  constructor(urlTree) {
3721
3760
  super();
3722
3761
  this.urlTree = urlTree;
3723
3762
  }
3763
+ };
3764
+ function namedOutletsRedirect$1(redirectTo) {
3765
+ throw new _RuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
3766
+ `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`);
3724
3767
  }
3725
- function noMatch$1(segmentGroup) {
3726
- return throwError(new NoMatch(segmentGroup));
3727
- }
3728
- function namedOutletsRedirect(redirectTo) {
3729
- return throwError(new _RuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
3730
- `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
3768
+ function canLoadFails$1(route) {
3769
+ throw navigationCancelingError((typeof ngDevMode === 'undefined' || ngDevMode) &&
3770
+ `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, NavigationCancellationCode.GuardRejected);
3731
3771
  }
3732
- function canLoadFails(route) {
3733
- return throwError(navigationCancelingError((typeof ngDevMode === 'undefined' || ngDevMode) &&
3734
- `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, NavigationCancellationCode.GuardRejected));
3735
- }
3736
- class ApplyRedirects {
3772
+ let ApplyRedirects$1 = class ApplyRedirects {
3737
3773
  urlSerializer;
3738
3774
  urlTree;
3739
3775
  constructor(urlSerializer, urlTree) {
3740
3776
  this.urlSerializer = urlSerializer;
3741
3777
  this.urlTree = urlTree;
3742
3778
  }
3743
- lineralizeSegments(route, urlTree) {
3779
+ async lineralizeSegments(route, urlTree) {
3744
3780
  let res = [];
3745
3781
  let c = urlTree.root;
3746
3782
  while (true) {
3747
3783
  res = res.concat(c.segments);
3748
3784
  if (c.numberOfChildren === 0) {
3749
- return of(res);
3785
+ return res;
3750
3786
  }
3751
3787
  if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
3752
- return namedOutletsRedirect(`${route.redirectTo}`);
3788
+ throw namedOutletsRedirect$1(`${route.redirectTo}`);
3753
3789
  }
3754
3790
  c = c.children[PRIMARY_OUTLET];
3755
3791
  }
3756
3792
  }
3757
- applyRedirectCommands(segments, redirectTo, posParams, currentSnapshot, injector) {
3758
- return getRedirectResult(redirectTo, currentSnapshot, injector).pipe(map((redirect) => {
3759
- if (redirect instanceof UrlTree) {
3760
- throw new AbsoluteRedirect(redirect);
3761
- }
3762
- const newTree = this.applyRedirectCreateUrlTree(redirect, this.urlSerializer.parse(redirect), segments, posParams);
3763
- if (redirect[0] === '/') {
3764
- throw new AbsoluteRedirect(newTree);
3765
- }
3766
- return newTree;
3767
- }));
3793
+ async applyRedirectCommands(segments, redirectTo, posParams, currentSnapshot, injector) {
3794
+ const redirect = await getRedirectResult$1(redirectTo, currentSnapshot, injector);
3795
+ if (redirect instanceof UrlTree) {
3796
+ throw new AbsoluteRedirect$1(redirect);
3797
+ }
3798
+ const newTree = this.applyRedirectCreateUrlTree(redirect, this.urlSerializer.parse(redirect), segments, posParams);
3799
+ if (redirect[0] === '/') {
3800
+ throw new AbsoluteRedirect$1(newTree);
3801
+ }
3802
+ return newTree;
3768
3803
  }
3769
3804
  applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
3770
3805
  const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
@@ -3815,24 +3850,24 @@ class ApplyRedirects {
3815
3850
  }
3816
3851
  return redirectToUrlSegment;
3817
3852
  }
3818
- }
3819
- function getRedirectResult(redirectTo, currentSnapshot, injector) {
3853
+ };
3854
+ function getRedirectResult$1(redirectTo, currentSnapshot, injector) {
3820
3855
  if (typeof redirectTo === 'string') {
3821
- return of(redirectTo);
3856
+ return Promise.resolve(redirectTo);
3822
3857
  }
3823
3858
  const redirectToFn = redirectTo;
3824
3859
  const { queryParams, fragment, routeConfig, url, outlet, params, data, title } = currentSnapshot;
3825
- return wrapIntoObservable(runInInjectionContext(injector, () => redirectToFn({ params, data, queryParams, fragment, routeConfig, url, outlet, title })));
3860
+ return firstValueFrom(wrapIntoObservable(runInInjectionContext(injector, () => redirectToFn({ params, data, queryParams, fragment, routeConfig, url, outlet, title }))));
3826
3861
  }
3827
3862
 
3828
- const noMatch = {
3863
+ const noMatch$1 = {
3829
3864
  matched: false,
3830
3865
  consumedSegments: [],
3831
3866
  remainingSegments: [],
3832
3867
  parameters: {},
3833
3868
  positionalParamSegments: {},
3834
3869
  };
3835
- function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
3870
+ function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer, abortSignal) {
3836
3871
  const result = match(segmentGroup, route, segments);
3837
3872
  if (!result.matched) {
3838
3873
  return of(result);
@@ -3840,7 +3875,7 @@ function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer)
3840
3875
  // Only create the Route's `EnvironmentInjector` if it matches the attempted
3841
3876
  // navigation
3842
3877
  injector = getOrCreateRouteInjectorIfNeeded(route, injector);
3843
- return runCanMatchGuards(injector, route, segments, urlSerializer).pipe(map((v) => (v === true ? result : { ...noMatch })));
3878
+ return runCanMatchGuards(injector, route, segments, urlSerializer, abortSignal).pipe(map((v) => (v === true ? result : { ...noMatch$1 })));
3844
3879
  }
3845
3880
  function match(segmentGroup, route, segments) {
3846
3881
  if (route.path === '**') {
@@ -3848,7 +3883,7 @@ function match(segmentGroup, route, segments) {
3848
3883
  }
3849
3884
  if (route.path === '') {
3850
3885
  if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
3851
- return { ...noMatch };
3886
+ return { ...noMatch$1 };
3852
3887
  }
3853
3888
  return {
3854
3889
  matched: true,
@@ -3861,7 +3896,7 @@ function match(segmentGroup, route, segments) {
3861
3896
  const matcher = route.matcher || defaultUrlMatcher;
3862
3897
  const res = matcher(segments, segmentGroup, route);
3863
3898
  if (!res)
3864
- return { ...noMatch };
3899
+ return { ...noMatch$1 };
3865
3900
  const posParams = {};
3866
3901
  Object.entries(res.posParams ?? {}).forEach(([k, v]) => {
3867
3902
  posParams[k] = v.path;
@@ -3938,6 +3973,449 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
3938
3973
  return segments.length === 0 && !segmentGroup.children[outlet];
3939
3974
  }
3940
3975
 
3976
+ /**
3977
+ * Class used to indicate there were no additional route config matches but that all segments of
3978
+ * the URL were consumed during matching so the route was URL matched. When this happens, we still
3979
+ * try to match child configs in case there are empty path children.
3980
+ */
3981
+ let NoLeftoversInUrl$1 = class NoLeftoversInUrl {
3982
+ };
3983
+ async function recognize$2(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', abortSignal) {
3984
+ return new Recognizer$1(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer, abortSignal).recognize();
3985
+ }
3986
+ const MAX_ALLOWED_REDIRECTS$1 = 31;
3987
+ let Recognizer$1 = class Recognizer {
3988
+ injector;
3989
+ configLoader;
3990
+ rootComponentType;
3991
+ config;
3992
+ urlTree;
3993
+ paramsInheritanceStrategy;
3994
+ urlSerializer;
3995
+ abortSignal;
3996
+ applyRedirects;
3997
+ absoluteRedirectCount = 0;
3998
+ allowRedirects = true;
3999
+ constructor(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer, abortSignal) {
4000
+ this.injector = injector;
4001
+ this.configLoader = configLoader;
4002
+ this.rootComponentType = rootComponentType;
4003
+ this.config = config;
4004
+ this.urlTree = urlTree;
4005
+ this.paramsInheritanceStrategy = paramsInheritanceStrategy;
4006
+ this.urlSerializer = urlSerializer;
4007
+ this.abortSignal = abortSignal;
4008
+ this.applyRedirects = new ApplyRedirects$1(this.urlSerializer, this.urlTree);
4009
+ }
4010
+ noMatchError(e) {
4011
+ return new _RuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, typeof ngDevMode === 'undefined' || ngDevMode
4012
+ ? `Cannot match any routes. URL Segment: '${e.segmentGroup}'`
4013
+ : `'${e.segmentGroup}'`);
4014
+ }
4015
+ async recognize() {
4016
+ const rootSegmentGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
4017
+ const { children, rootSnapshot } = await this.match(rootSegmentGroup);
4018
+ const rootNode = new TreeNode(rootSnapshot, children);
4019
+ const routeState = new RouterStateSnapshot('', rootNode);
4020
+ const tree = createUrlTreeFromSnapshot(rootSnapshot, [], this.urlTree.queryParams, this.urlTree.fragment);
4021
+ // https://github.com/angular/angular/issues/47307
4022
+ // Creating the tree stringifies the query params
4023
+ // We don't want to do this here so reassign them to the original.
4024
+ tree.queryParams = this.urlTree.queryParams;
4025
+ routeState.url = this.urlSerializer.serialize(tree);
4026
+ return { state: routeState, tree };
4027
+ }
4028
+ async match(rootSegmentGroup) {
4029
+ // Use Object.freeze to prevent readers of the Router state from modifying it outside
4030
+ // of a navigation, resulting in the router being out of sync with the browser.
4031
+ const rootSnapshot = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, Object.freeze({}), PRIMARY_OUTLET, this.rootComponentType, null, {});
4032
+ try {
4033
+ const children = await this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET, rootSnapshot);
4034
+ return { children, rootSnapshot };
4035
+ }
4036
+ catch (e) {
4037
+ if (e?.name === ABSOLUTE_REDIRECT_ERROR_NAME) {
4038
+ this.urlTree = e.urlTree;
4039
+ return this.match(e.urlTree.root);
4040
+ }
4041
+ if (e?.name === NO_MATCH_ERROR_NAME) {
4042
+ throw this.noMatchError(e);
4043
+ }
4044
+ throw e;
4045
+ }
4046
+ }
4047
+ async processSegmentGroup(injector, config, segmentGroup, outlet, parentRoute) {
4048
+ if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
4049
+ return this.processChildren(injector, config, segmentGroup, parentRoute);
4050
+ }
4051
+ const child = await this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true, parentRoute);
4052
+ return child instanceof TreeNode ? [child] : [];
4053
+ }
4054
+ /**
4055
+ * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
4056
+ * we cannot find a match for _any_ of the children.
4057
+ *
4058
+ * @param config - The `Routes` to match against
4059
+ * @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the
4060
+ * config.
4061
+ */
4062
+ async processChildren(injector, config, segmentGroup, parentRoute) {
4063
+ // Expand outlets one at a time, starting with the primary outlet. We need to do it this way
4064
+ // because an absolute redirect from the primary outlet takes precedence.
4065
+ const childOutlets = [];
4066
+ for (const child of Object.keys(segmentGroup.children)) {
4067
+ if (child === 'primary') {
4068
+ childOutlets.unshift(child);
4069
+ }
4070
+ else {
4071
+ childOutlets.push(child);
4072
+ }
4073
+ }
4074
+ let children = [];
4075
+ for (const childOutlet of childOutlets) {
4076
+ const child = segmentGroup.children[childOutlet];
4077
+ // Sort the config so that routes with outlets that match the one being activated
4078
+ // appear first, followed by routes for other outlets, which might match if they have
4079
+ // an empty path.
4080
+ const sortedConfig = sortByMatchingOutlets(config, childOutlet);
4081
+ const outletChildren = await this.processSegmentGroup(injector, sortedConfig, child, childOutlet, parentRoute);
4082
+ children.push(...outletChildren);
4083
+ }
4084
+ // Because we may have matched two outlets to the same empty path segment, we can have
4085
+ // multiple activated results for the same outlet. We should merge the children of
4086
+ // these results so the final return value is only one `TreeNode` per outlet.
4087
+ const mergedChildren = mergeEmptyPathMatches$1(children);
4088
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
4089
+ // This should really never happen - we are only taking the first match for each
4090
+ // outlet and merge the empty path matches.
4091
+ checkOutletNameUniqueness$1(mergedChildren);
4092
+ }
4093
+ sortActivatedRouteSnapshots$1(mergedChildren);
4094
+ return mergedChildren;
4095
+ }
4096
+ async processSegment(injector, routes, segmentGroup, segments, outlet, allowRedirects, parentRoute) {
4097
+ for (const r of routes) {
4098
+ try {
4099
+ return await this.processSegmentAgainstRoute(r._injector ?? injector, routes, r, segmentGroup, segments, outlet, allowRedirects, parentRoute);
4100
+ }
4101
+ catch (e) {
4102
+ if (e?.name === NO_MATCH_ERROR_NAME || isEmptyError(e)) {
4103
+ continue;
4104
+ }
4105
+ throw e;
4106
+ }
4107
+ }
4108
+ if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
4109
+ return new NoLeftoversInUrl$1();
4110
+ }
4111
+ throw new NoMatch$1(segmentGroup);
4112
+ }
4113
+ async processSegmentAgainstRoute(injector, routes, route, rawSegment, segments, outlet, allowRedirects, parentRoute) {
4114
+ // We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to
4115
+ // a config like
4116
+ // * `{path: '', children: [{path: 'b', outlet: 'b'}]}`
4117
+ // or even
4118
+ // * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]`
4119
+ //
4120
+ // The exception here is when the segment outlet is for the primary outlet. This would
4121
+ // result in a match inside the named outlet because all children there are written as primary
4122
+ // outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like
4123
+ // * `{path: '', outlet: 'x' children: [{path: 'b'}]}`
4124
+ // This should only match if the url is `/(x:b)`.
4125
+ if (getOutlet(route) !== outlet &&
4126
+ (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
4127
+ throw new NoMatch$1(rawSegment);
4128
+ }
4129
+ if (route.redirectTo === undefined) {
4130
+ return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute);
4131
+ }
4132
+ if (this.allowRedirects && allowRedirects) {
4133
+ return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet, parentRoute);
4134
+ }
4135
+ throw new NoMatch$1(rawSegment);
4136
+ }
4137
+ async expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet, parentRoute) {
4138
+ const { matched, parameters, consumedSegments, positionalParamSegments, remainingSegments } = match(segmentGroup, route, segments);
4139
+ if (!matched)
4140
+ throw new NoMatch$1(segmentGroup);
4141
+ // TODO(atscott): Move all of this under an if(ngDevMode) as a breaking change and allow stack
4142
+ // size exceeded in production
4143
+ if (typeof route.redirectTo === 'string' && route.redirectTo[0] === '/') {
4144
+ this.absoluteRedirectCount++;
4145
+ if (this.absoluteRedirectCount > MAX_ALLOWED_REDIRECTS$1) {
4146
+ if (ngDevMode) {
4147
+ throw new _RuntimeError(4016 /* RuntimeErrorCode.INFINITE_REDIRECT */, `Detected possible infinite redirect when redirecting from '${this.urlTree}' to '${route.redirectTo}'.\n` +
4148
+ `This is currently a dev mode only error but will become a` +
4149
+ ` call stack size exceeded error in production in a future major version.`);
4150
+ }
4151
+ this.allowRedirects = false;
4152
+ }
4153
+ }
4154
+ const currentSnapshot = new ActivatedRouteSnapshot(segments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData$1(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve$1(route));
4155
+ const inherited = getInherited(currentSnapshot, parentRoute, this.paramsInheritanceStrategy);
4156
+ currentSnapshot.params = Object.freeze(inherited.params);
4157
+ currentSnapshot.data = Object.freeze(inherited.data);
4158
+ if (this.abortSignal.aborted) {
4159
+ throw new Error(this.abortSignal.reason);
4160
+ }
4161
+ const newTree = await this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments, currentSnapshot, injector);
4162
+ const newSegments = await this.applyRedirects.lineralizeSegments(route, newTree);
4163
+ return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false, parentRoute);
4164
+ }
4165
+ async matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute) {
4166
+ if (this.abortSignal.aborted) {
4167
+ throw new Error(this.abortSignal.reason);
4168
+ }
4169
+ const result = await firstValueFrom(matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer, this.abortSignal));
4170
+ if (route.path === '**') {
4171
+ // Prior versions of the route matching algorithm would stop matching at the wildcard route.
4172
+ // We should investigate a better strategy for any existing children. Otherwise, these
4173
+ // child segments are silently dropped from the navigation.
4174
+ // https://github.com/angular/angular/issues/40089
4175
+ rawSegment.children = {};
4176
+ }
4177
+ if (!result?.matched) {
4178
+ throw new NoMatch$1(rawSegment);
4179
+ }
4180
+ // If the route has an injector created from providers, we should start using that.
4181
+ injector = route._injector ?? injector;
4182
+ const { routes: childConfig } = await this.getChildConfig(injector, route, segments);
4183
+ const childInjector = route._loadedInjector ?? injector;
4184
+ const { parameters, consumedSegments, remainingSegments } = result;
4185
+ const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData$1(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve$1(route));
4186
+ const inherited = getInherited(snapshot, parentRoute, this.paramsInheritanceStrategy);
4187
+ snapshot.params = Object.freeze(inherited.params);
4188
+ snapshot.data = Object.freeze(inherited.data);
4189
+ const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments, childConfig);
4190
+ if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
4191
+ const children = await this.processChildren(childInjector, childConfig, segmentGroup, snapshot);
4192
+ return new TreeNode(snapshot, children);
4193
+ }
4194
+ if (childConfig.length === 0 && slicedSegments.length === 0) {
4195
+ return new TreeNode(snapshot, []);
4196
+ }
4197
+ const matchedOnOutlet = getOutlet(route) === outlet;
4198
+ // If we matched a config due to empty path match on a different outlet, we need to
4199
+ // continue passing the current outlet for the segment rather than switch to PRIMARY.
4200
+ // Note that we switch to primary when we have a match because outlet configs look like
4201
+ // this: {path: 'a', outlet: 'a', children: [
4202
+ // {path: 'b', component: B},
4203
+ // {path: 'c', component: C},
4204
+ // ]}
4205
+ // Notice that the children of the named outlet are configured with the primary outlet
4206
+ const child = await this.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true, snapshot);
4207
+ return new TreeNode(snapshot, child instanceof TreeNode ? [child] : []);
4208
+ }
4209
+ async getChildConfig(injector, route, segments) {
4210
+ if (route.children) {
4211
+ // The children belong to the same module
4212
+ return { routes: route.children, injector };
4213
+ }
4214
+ if (route.loadChildren) {
4215
+ // lazy children belong to the loaded module
4216
+ if (route._loadedRoutes !== undefined) {
4217
+ return { routes: route._loadedRoutes, injector: route._loadedInjector };
4218
+ }
4219
+ if (this.abortSignal.aborted) {
4220
+ throw new Error(this.abortSignal.reason);
4221
+ }
4222
+ const shouldLoadResult = await firstValueFrom(runCanLoadGuards(injector, route, segments, this.urlSerializer, this.abortSignal));
4223
+ if (shouldLoadResult) {
4224
+ const cfg = await firstValueFrom(this.configLoader.loadChildren(injector, route));
4225
+ if (!cfg) {
4226
+ throw canLoadFails$1(route);
4227
+ }
4228
+ route._loadedRoutes = cfg.routes;
4229
+ route._loadedInjector = cfg.injector;
4230
+ return cfg;
4231
+ }
4232
+ throw canLoadFails$1(route);
4233
+ }
4234
+ return { routes: [], injector };
4235
+ }
4236
+ };
4237
+ function sortActivatedRouteSnapshots$1(nodes) {
4238
+ nodes.sort((a, b) => {
4239
+ if (a.value.outlet === PRIMARY_OUTLET)
4240
+ return -1;
4241
+ if (b.value.outlet === PRIMARY_OUTLET)
4242
+ return 1;
4243
+ return a.value.outlet.localeCompare(b.value.outlet);
4244
+ });
4245
+ }
4246
+ function hasEmptyPathConfig$1(node) {
4247
+ const config = node.value.routeConfig;
4248
+ return config && config.path === '';
4249
+ }
4250
+ /**
4251
+ * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with
4252
+ * the children from each duplicate. This is necessary because different outlets can match a
4253
+ * single empty path route config and the results need to then be merged.
4254
+ */
4255
+ function mergeEmptyPathMatches$1(nodes) {
4256
+ const result = [];
4257
+ // The set of nodes which contain children that were merged from two duplicate empty path nodes.
4258
+ const mergedNodes = new Set();
4259
+ for (const node of nodes) {
4260
+ if (!hasEmptyPathConfig$1(node)) {
4261
+ result.push(node);
4262
+ continue;
4263
+ }
4264
+ const duplicateEmptyPathNode = result.find((resultNode) => node.value.routeConfig === resultNode.value.routeConfig);
4265
+ if (duplicateEmptyPathNode !== undefined) {
4266
+ duplicateEmptyPathNode.children.push(...node.children);
4267
+ mergedNodes.add(duplicateEmptyPathNode);
4268
+ }
4269
+ else {
4270
+ result.push(node);
4271
+ }
4272
+ }
4273
+ // For each node which has children from multiple sources, we need to recompute a new `TreeNode`
4274
+ // by also merging those children. This is necessary when there are multiple empty path configs
4275
+ // in a row. Put another way: whenever we combine children of two nodes, we need to also check
4276
+ // if any of those children can be combined into a single node as well.
4277
+ for (const mergedNode of mergedNodes) {
4278
+ const mergedChildren = mergeEmptyPathMatches$1(mergedNode.children);
4279
+ result.push(new TreeNode(mergedNode.value, mergedChildren));
4280
+ }
4281
+ return result.filter((n) => !mergedNodes.has(n));
4282
+ }
4283
+ function checkOutletNameUniqueness$1(nodes) {
4284
+ const names = {};
4285
+ nodes.forEach((n) => {
4286
+ const routeWithSameOutletName = names[n.value.outlet];
4287
+ if (routeWithSameOutletName) {
4288
+ const p = routeWithSameOutletName.url.map((s) => s.toString()).join('/');
4289
+ const c = n.value.url.map((s) => s.toString()).join('/');
4290
+ throw new _RuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
4291
+ `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
4292
+ }
4293
+ names[n.value.outlet] = n.value;
4294
+ });
4295
+ }
4296
+ function getData$1(route) {
4297
+ return route.data || {};
4298
+ }
4299
+ function getResolve$1(route) {
4300
+ return route.resolve || {};
4301
+ }
4302
+
4303
+ class NoMatch {
4304
+ segmentGroup;
4305
+ constructor(segmentGroup) {
4306
+ this.segmentGroup = segmentGroup || null;
4307
+ }
4308
+ }
4309
+ class AbsoluteRedirect extends Error {
4310
+ urlTree;
4311
+ constructor(urlTree) {
4312
+ super();
4313
+ this.urlTree = urlTree;
4314
+ }
4315
+ }
4316
+ function noMatch(segmentGroup) {
4317
+ return throwError(new NoMatch(segmentGroup));
4318
+ }
4319
+ function namedOutletsRedirect(redirectTo) {
4320
+ return throwError(new _RuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
4321
+ `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
4322
+ }
4323
+ function canLoadFails(route) {
4324
+ return throwError(navigationCancelingError((typeof ngDevMode === 'undefined' || ngDevMode) &&
4325
+ `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, NavigationCancellationCode.GuardRejected));
4326
+ }
4327
+ class ApplyRedirects {
4328
+ urlSerializer;
4329
+ urlTree;
4330
+ constructor(urlSerializer, urlTree) {
4331
+ this.urlSerializer = urlSerializer;
4332
+ this.urlTree = urlTree;
4333
+ }
4334
+ lineralizeSegments(route, urlTree) {
4335
+ let res = [];
4336
+ let c = urlTree.root;
4337
+ while (true) {
4338
+ res = res.concat(c.segments);
4339
+ if (c.numberOfChildren === 0) {
4340
+ return of(res);
4341
+ }
4342
+ if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
4343
+ return namedOutletsRedirect(`${route.redirectTo}`);
4344
+ }
4345
+ c = c.children[PRIMARY_OUTLET];
4346
+ }
4347
+ }
4348
+ applyRedirectCommands(segments, redirectTo, posParams, currentSnapshot, injector) {
4349
+ return getRedirectResult(redirectTo, currentSnapshot, injector).pipe(map((redirect) => {
4350
+ if (redirect instanceof UrlTree) {
4351
+ throw new AbsoluteRedirect(redirect);
4352
+ }
4353
+ const newTree = this.applyRedirectCreateUrlTree(redirect, this.urlSerializer.parse(redirect), segments, posParams);
4354
+ if (redirect[0] === '/') {
4355
+ throw new AbsoluteRedirect(newTree);
4356
+ }
4357
+ return newTree;
4358
+ }));
4359
+ }
4360
+ applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
4361
+ const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
4362
+ return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
4363
+ }
4364
+ createQueryParams(redirectToParams, actualParams) {
4365
+ const res = {};
4366
+ Object.entries(redirectToParams).forEach(([k, v]) => {
4367
+ const copySourceValue = typeof v === 'string' && v[0] === ':';
4368
+ if (copySourceValue) {
4369
+ const sourceName = v.substring(1);
4370
+ res[k] = actualParams[sourceName];
4371
+ }
4372
+ else {
4373
+ res[k] = v;
4374
+ }
4375
+ });
4376
+ return res;
4377
+ }
4378
+ createSegmentGroup(redirectTo, group, segments, posParams) {
4379
+ const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
4380
+ let children = {};
4381
+ Object.entries(group.children).forEach(([name, child]) => {
4382
+ children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
4383
+ });
4384
+ return new UrlSegmentGroup(updatedSegments, children);
4385
+ }
4386
+ createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
4387
+ return redirectToSegments.map((s) => s.path[0] === ':'
4388
+ ? this.findPosParam(redirectTo, s, posParams)
4389
+ : this.findOrReturn(s, actualSegments));
4390
+ }
4391
+ findPosParam(redirectTo, redirectToUrlSegment, posParams) {
4392
+ const pos = posParams[redirectToUrlSegment.path.substring(1)];
4393
+ if (!pos)
4394
+ throw new _RuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
4395
+ `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
4396
+ return pos;
4397
+ }
4398
+ findOrReturn(redirectToUrlSegment, actualSegments) {
4399
+ let idx = 0;
4400
+ for (const s of actualSegments) {
4401
+ if (s.path === redirectToUrlSegment.path) {
4402
+ actualSegments.splice(idx);
4403
+ return s;
4404
+ }
4405
+ idx++;
4406
+ }
4407
+ return redirectToUrlSegment;
4408
+ }
4409
+ }
4410
+ function getRedirectResult(redirectTo, currentSnapshot, injector) {
4411
+ if (typeof redirectTo === 'string') {
4412
+ return of(redirectTo);
4413
+ }
4414
+ const redirectToFn = redirectTo;
4415
+ const { queryParams, fragment, routeConfig, url, outlet, params, data, title } = currentSnapshot;
4416
+ return wrapIntoObservable(runInInjectionContext(injector, () => redirectToFn({ params, data, queryParams, fragment, routeConfig, url, outlet, title })));
4417
+ }
4418
+
3941
4419
  /**
3942
4420
  * Class used to indicate there were no additional route config matches but that all segments of
3943
4421
  * the URL were consumed during matching so the route was URL matched. When this happens, we still
@@ -3945,7 +4423,7 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
3945
4423
  */
3946
4424
  class NoLeftoversInUrl {
3947
4425
  }
3948
- function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly') {
4426
+ function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', abortSignal) {
3949
4427
  return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer).recognize();
3950
4428
  }
3951
4429
  const MAX_ALLOWED_REDIRECTS = 31;
@@ -4044,7 +4522,7 @@ class Recognizer {
4044
4522
  return children;
4045
4523
  }), defaultIfEmpty(null), last$1(), mergeMap((children) => {
4046
4524
  if (children === null)
4047
- return noMatch$1(segmentGroup);
4525
+ return noMatch(segmentGroup);
4048
4526
  // Because we may have matched two outlets to the same empty path segment, we can have
4049
4527
  // multiple activated results for the same outlet. We should merge the children of
4050
4528
  // these results so the final return value is only one `TreeNode` per outlet.
@@ -4071,7 +4549,7 @@ class Recognizer {
4071
4549
  if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
4072
4550
  return of(new NoLeftoversInUrl());
4073
4551
  }
4074
- return noMatch$1(segmentGroup);
4552
+ return noMatch(segmentGroup);
4075
4553
  }
4076
4554
  throw e;
4077
4555
  }));
@@ -4090,7 +4568,7 @@ class Recognizer {
4090
4568
  // This should only match if the url is `/(x:b)`.
4091
4569
  if (getOutlet(route) !== outlet &&
4092
4570
  (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
4093
- return noMatch$1(rawSegment);
4571
+ return noMatch(rawSegment);
4094
4572
  }
4095
4573
  if (route.redirectTo === undefined) {
4096
4574
  return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute);
@@ -4098,12 +4576,12 @@ class Recognizer {
4098
4576
  if (this.allowRedirects && allowRedirects) {
4099
4577
  return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet, parentRoute);
4100
4578
  }
4101
- return noMatch$1(rawSegment);
4579
+ return noMatch(rawSegment);
4102
4580
  }
4103
4581
  expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet, parentRoute) {
4104
4582
  const { matched, parameters, consumedSegments, positionalParamSegments, remainingSegments } = match(segmentGroup, route, segments);
4105
4583
  if (!matched)
4106
- return noMatch$1(segmentGroup);
4584
+ return noMatch(segmentGroup);
4107
4585
  // TODO(atscott): Move all of this under an if(ngDevMode) as a breaking change and allow stack
4108
4586
  // size exceeded in production
4109
4587
  if (typeof route.redirectTo === 'string' && route.redirectTo[0] === '/') {
@@ -4137,7 +4615,7 @@ class Recognizer {
4137
4615
  }
4138
4616
  return matchResult.pipe(switchMap((result) => {
4139
4617
  if (!result.matched) {
4140
- return noMatch$1(rawSegment);
4618
+ return noMatch(rawSegment);
4141
4619
  }
4142
4620
  // If the route has an injector created from providers, we should start using that.
4143
4621
  injector = route._injector ?? injector;
@@ -4261,8 +4739,22 @@ function getResolve(route) {
4261
4739
  return route.resolve || {};
4262
4740
  }
4263
4741
 
4264
- function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy) {
4265
- return mergeMap((t) => recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy).pipe(map(({ state: targetSnapshot, tree: urlAfterRedirects }) => {
4742
+ const RECOGNIZE_IMPL = new InjectionToken('RECOGNIZE_IMPL', {
4743
+ providedIn: 'root',
4744
+ factory: () => {
4745
+ return recognize$2;
4746
+ },
4747
+ });
4748
+ /**
4749
+ * Provides a way to use the synchronous version of the recognize function using rxjs.
4750
+ */
4751
+ function provideSometimesSyncRecognize() {
4752
+ return makeEnvironmentProviders([{ provide: RECOGNIZE_IMPL, useValue: recognize$1 }]);
4753
+ }
4754
+ function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy, abortSignal) {
4755
+ // TODO(atscott): Simplify once we do not need to support both forms of recognize
4756
+ const recognizeImpl = injector.get(RECOGNIZE_IMPL);
4757
+ return mergeMap((t) => of(t).pipe(switchMap((t) => recognizeImpl(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy, abortSignal)), map(({ state: targetSnapshot, tree: urlAfterRedirects }) => {
4266
4758
  return { ...t, targetSnapshot, urlAfterRedirects };
4267
4759
  })));
4268
4760
  }
@@ -4808,7 +5300,7 @@ class NavigationTransitions {
4808
5300
  return Promise.resolve(t);
4809
5301
  }),
4810
5302
  // Recognize
4811
- recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy),
5303
+ recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy, overallTransitionState.abortController.signal),
4812
5304
  // Update URL if in `eager` update mode
4813
5305
  tap((t) => {
4814
5306
  overallTransitionState.targetSnapshot = t.targetSnapshot;
@@ -4945,12 +5437,7 @@ class NavigationTransitions {
4945
5437
  // Ensure that if some observable used to drive the transition doesn't
4946
5438
  // complete, the navigation still finalizes This should never happen, but
4947
5439
  // this is done as a safety measure to avoid surfacing this error (#49567).
4948
- take(1), takeUntil(new Observable((subscriber) => {
4949
- const abortSignal = overallTransitionState.abortController.signal;
4950
- const handler = () => subscriber.next();
4951
- abortSignal.addEventListener('abort', handler);
4952
- return () => abortSignal.removeEventListener('abort', handler);
4953
- }).pipe(
5440
+ take(1), takeUntil(abortSignalToObservable(overallTransitionState.abortController.signal).pipe(
4954
5441
  // Ignore aborts if we are already completed, canceled, or are in the activation stage (we have targetRouterState)
4955
5442
  filter(() => !completedOrAborted && !overallTransitionState.targetRouterState), tap(() => {
4956
5443
  this.cancelNavigationTransition(overallTransitionState, overallTransitionState.abortController.signal.reason + '', NavigationCancellationCode.Aborted);
@@ -4976,6 +5463,7 @@ class NavigationTransitions {
4976
5463
  takeUntil(this.transitionAbortWithErrorSubject.pipe(tap((err) => {
4977
5464
  throw err;
4978
5465
  }))), finalize(() => {
5466
+ overallTransitionState.abortController.abort();
4979
5467
  /* When the navigation stream finishes either through error or success,
4980
5468
  * we set the `completed` or `errored` flag. However, there are some
4981
5469
  * situations where we could get here without either of those being set.
@@ -5992,5 +6480,5 @@ function validateCommands(commands) {
5992
6480
  }
5993
6481
  }
5994
6482
 
5995
- export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, CREATE_VIEW_TRANSITION, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, EventType, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, INPUT_BINDER, NAVIGATION_ERROR_HANDLER, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTransitions, OutletContext, PRIMARY_OUTLET, ROUTER_CONFIGURATION, ROUTER_OUTLET_DATA, ROUTES, RedirectCommand, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, RoutedComponentInputBinder, Router, RouterConfigLoader, RouterEvent, RouterOutlet, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VIEW_TRANSITION_OPTIONS, afterNextNavigation, convertToParamMap, createUrlTreeFromSnapshot, createViewTransition, defaultUrlMatcher, isUrlTree, loadChildren, stringifyEvent, ɵEmptyOutletComponent };
6483
+ export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, CREATE_VIEW_TRANSITION, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, EventType, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, INPUT_BINDER, NAVIGATION_ERROR_HANDLER, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTransitions, OutletContext, PRIMARY_OUTLET, ROUTER_CONFIGURATION, ROUTER_OUTLET_DATA, ROUTES, RedirectCommand, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, RoutedComponentInputBinder, Router, RouterConfigLoader, RouterEvent, RouterOutlet, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VIEW_TRANSITION_OPTIONS, afterNextNavigation, convertToParamMap, createUrlTreeFromSnapshot, createViewTransition, defaultUrlMatcher, isUrlTree, loadChildren, provideSometimesSyncRecognize, stringifyEvent, ɵEmptyOutletComponent };
5996
6484
  //# sourceMappingURL=router2.mjs.map