@angular/router 16.2.1 → 16.2.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,15 +1,15 @@
1
1
  /**
2
- * @license Angular v16.2.1
2
+ * @license Angular v16.2.2
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
8
  import { ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, InjectionToken, reflectComponentType, Component, createEnvironmentInjector, ɵisNgModule, isStandalone, ɵisInjectable, Compiler, InjectFlags, NgModuleFactory, ɵConsole, ɵInitialRenderPendingTasks, NgZone, ɵɵsanitizeUrlOrResourceUrl, booleanAttribute, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, Injector, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
9
- import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, concat, defer, pipe, throwError, EMPTY, ConnectableObservable, Subject } from 'rxjs';
9
+ import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, concat, defer, pipe, throwError, EMPTY, ConnectableObservable, Subject, Subscription } from 'rxjs';
10
10
  import * as i3 from '@angular/common';
11
11
  import { Location, ViewportScroller, LOCATION_INITIALIZED, LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
12
- import { map, switchMap, take, startWith, filter, mergeMap, first, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, mapTo, finalize, refCount, mergeAll } from 'rxjs/operators';
12
+ import { map, switchMap, take, startWith, filter, mergeMap, first, concatMap, tap, catchError, scan, defaultIfEmpty, last as last$1, takeLast, mapTo, finalize, refCount, takeUntil, mergeAll } from 'rxjs/operators';
13
13
  import * as i1 from '@angular/platform-browser';
14
14
 
15
15
  /**
@@ -419,10 +419,10 @@ function mapChildrenIntoArray(segment, fn) {
419
419
  * @publicApi
420
420
  */
421
421
  class UrlSerializer {
422
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
423
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
422
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
423
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
424
424
  }
425
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlSerializer, decorators: [{
425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlSerializer, decorators: [{
426
426
  type: Injectable,
427
427
  args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
428
428
  }] });
@@ -1667,6 +1667,13 @@ class Scroll {
1667
1667
  return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
1668
1668
  }
1669
1669
  }
1670
+ class BeforeActivateRoutes {
1671
+ }
1672
+ class RedirectRequest {
1673
+ constructor(url) {
1674
+ this.url = url;
1675
+ }
1676
+ }
1670
1677
  function stringifyEvent(routerEvent) {
1671
1678
  switch (routerEvent.type) {
1672
1679
  case 14 /* EventType.ActivationEnd */:
@@ -1772,10 +1779,10 @@ class ChildrenOutletContexts {
1772
1779
  getContext(childName) {
1773
1780
  return this.contexts.get(childName) || null;
1774
1781
  }
1775
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1776
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1782
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1783
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1777
1784
  }
1778
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1779
1786
  type: Injectable,
1780
1787
  args: [{ providedIn: 'root' }]
1781
1788
  }] });
@@ -2482,10 +2489,10 @@ class RouterOutlet {
2482
2489
  this.inputBinder?.bindActivatedRouteToOutletComponent(this);
2483
2490
  this.activateEvents.emit(this.activated.instance);
2484
2491
  }
2485
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2486
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 }); }
2492
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2493
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.2", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 }); }
2487
2494
  }
2488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterOutlet, decorators: [{
2495
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterOutlet, decorators: [{
2489
2496
  type: Directive,
2490
2497
  args: [{
2491
2498
  selector: 'router-outlet',
@@ -2588,10 +2595,10 @@ class RoutedComponentInputBinder {
2588
2595
  });
2589
2596
  this.outletDataSubscriptions.set(outlet, dataSubscription);
2590
2597
  }
2591
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2592
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RoutedComponentInputBinder }); }
2598
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2599
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RoutedComponentInputBinder }); }
2593
2600
  }
2594
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2601
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2595
2602
  type: Injectable
2596
2603
  }] });
2597
2604
 
@@ -2671,10 +2678,10 @@ function isNavigationCancelingError$1(error) {
2671
2678
  * to this `EmptyOutletComponent`.
2672
2679
  */
2673
2680
  class ɵEmptyOutletComponent {
2674
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2675
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] }); }
2681
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2682
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.2", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] }); }
2676
2683
  }
2677
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2684
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2678
2685
  type: Component,
2679
2686
  args: [{
2680
2687
  template: `<router-outlet></router-outlet>`,
@@ -4148,10 +4155,10 @@ class RouterConfigLoader {
4148
4155
  }
4149
4156
  }));
4150
4157
  }
4151
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4152
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4158
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4159
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4153
4160
  }
4154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterConfigLoader, decorators: [{
4161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
4155
4162
  type: Injectable,
4156
4163
  args: [{ providedIn: 'root' }]
4157
4164
  }] });
@@ -4173,8 +4180,18 @@ class NavigationTransitions {
4173
4180
  }
4174
4181
  constructor() {
4175
4182
  this.currentNavigation = null;
4183
+ this.currentTransition = null;
4176
4184
  this.lastSuccessfulNavigation = null;
4185
+ /**
4186
+ * These events are used to communicate back to the Router about the state of the transition. The
4187
+ * Router wants to respond to these events in various ways. Because the `NavigationTransition`
4188
+ * class is not public, this event subject is not publicly exposed.
4189
+ */
4177
4190
  this.events = new Subject();
4191
+ /**
4192
+ * Used to abort the current transition with an error.
4193
+ */
4194
+ this.transitionAbortSubject = new Subject();
4178
4195
  this.configLoader = inject(RouterConfigLoader);
4179
4196
  this.environmentInjector = inject(EnvironmentInjector);
4180
4197
  this.urlSerializer = inject(UrlSerializer);
@@ -4202,23 +4219,24 @@ class NavigationTransitions {
4202
4219
  const id = ++this.navigationId;
4203
4220
  this.transitions?.next({ ...this.transitions.value, ...request, id });
4204
4221
  }
4205
- setupNavigations(router) {
4222
+ setupNavigations(router, initialUrlTree, initialRouterState) {
4206
4223
  this.transitions = new BehaviorSubject({
4207
4224
  id: 0,
4208
- currentUrlTree: router.currentUrlTree,
4209
- currentRawUrl: router.currentUrlTree,
4210
- extractedUrl: router.urlHandlingStrategy.extract(router.currentUrlTree),
4211
- urlAfterRedirects: router.urlHandlingStrategy.extract(router.currentUrlTree),
4212
- rawUrl: router.currentUrlTree,
4225
+ currentUrlTree: initialUrlTree,
4226
+ currentRawUrl: initialUrlTree,
4227
+ currentBrowserUrl: initialUrlTree,
4228
+ extractedUrl: router.urlHandlingStrategy.extract(initialUrlTree),
4229
+ urlAfterRedirects: router.urlHandlingStrategy.extract(initialUrlTree),
4230
+ rawUrl: initialUrlTree,
4213
4231
  extras: {},
4214
4232
  resolve: null,
4215
4233
  reject: null,
4216
4234
  promise: Promise.resolve(true),
4217
4235
  source: IMPERATIVE_NAVIGATION,
4218
4236
  restoredState: null,
4219
- currentSnapshot: router.routerState.snapshot,
4237
+ currentSnapshot: initialRouterState.snapshot,
4220
4238
  targetSnapshot: null,
4221
- currentRouterState: router.routerState,
4239
+ currentRouterState: initialRouterState,
4222
4240
  targetRouterState: null,
4223
4241
  guards: { canActivateChecks: [], canDeactivateChecks: [] },
4224
4242
  guardsResult: null,
@@ -4228,6 +4246,7 @@ class NavigationTransitions {
4228
4246
  map(t => ({ ...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl) })),
4229
4247
  // Using switchMap so we cancel executing navigations when a new one comes in
4230
4248
  switchMap(overallTransitionState => {
4249
+ this.currentTransition = overallTransitionState;
4231
4250
  let completed = false;
4232
4251
  let errored = false;
4233
4252
  return of(overallTransitionState)
@@ -4246,30 +4265,24 @@ class NavigationTransitions {
4246
4265
  },
4247
4266
  };
4248
4267
  }), switchMap(t => {
4249
- const browserUrlTree = router.browserUrlTree.toString();
4268
+ const browserUrlTree = t.currentBrowserUrl.toString();
4250
4269
  const urlTransition = !router.navigated ||
4251
4270
  t.extractedUrl.toString() !== browserUrlTree ||
4252
4271
  // Navigations which succeed or ones which fail and are cleaned up
4253
4272
  // correctly should result in `browserUrlTree` and `currentUrlTree`
4254
4273
  // matching. If this is not the case, assume something went wrong and
4255
4274
  // try processing the URL again.
4256
- browserUrlTree !== router.currentUrlTree.toString();
4275
+ browserUrlTree !== t.currentUrlTree.toString();
4257
4276
  const onSameUrlNavigation = t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;
4258
4277
  if (!urlTransition && onSameUrlNavigation !== 'reload') {
4259
4278
  const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
4260
4279
  `Navigation to ${t.rawUrl} was ignored because it is the same as the current Router URL.` :
4261
4280
  '';
4262
- this.events.next(new NavigationSkipped(t.id, router.serializeUrl(overallTransitionState.rawUrl), reason, 0 /* NavigationSkippedCode.IgnoredSameUrlNavigation */));
4263
- router.rawUrlTree = t.rawUrl;
4281
+ this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.rawUrl), reason, 0 /* NavigationSkippedCode.IgnoredSameUrlNavigation */));
4264
4282
  t.resolve(null);
4265
4283
  return EMPTY;
4266
4284
  }
4267
4285
  if (router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
4268
- // If the source of the navigation is from a browser event, the URL is
4269
- // already updated. We already need to sync the internal state.
4270
- if (isBrowserTriggeredNavigation(t.source)) {
4271
- router.browserUrlTree = t.extractedUrl;
4272
- }
4273
4286
  return of(t).pipe(
4274
4287
  // Fire NavigationStart event
4275
4288
  switchMap(t => {
@@ -4292,20 +4305,13 @@ class NavigationTransitions {
4292
4305
  ...this.currentNavigation,
4293
4306
  finalUrl: t.urlAfterRedirects
4294
4307
  };
4295
- if (router.urlUpdateStrategy === 'eager') {
4296
- if (!t.extras.skipLocationChange) {
4297
- const rawUrl = router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
4298
- router.setBrowserUrl(rawUrl, t);
4299
- }
4300
- router.browserUrlTree = t.urlAfterRedirects;
4301
- }
4302
4308
  // Fire RoutesRecognized
4303
4309
  const routesRecognized = new RoutesRecognized(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4304
4310
  this.events.next(routesRecognized);
4305
4311
  }));
4306
4312
  }
4307
4313
  else if (urlTransition &&
4308
- router.urlHandlingStrategy.shouldProcessUrl(router.rawUrlTree)) {
4314
+ router.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
4309
4315
  /* When the current URL shouldn't be processed, but the previous one
4310
4316
  * was, we handle this "error condition" by navigating to the
4311
4317
  * previously successful URL, but leaving the URL intact.*/
@@ -4313,7 +4319,7 @@ class NavigationTransitions {
4313
4319
  const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
4314
4320
  this.events.next(navStart);
4315
4321
  const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
4316
- overallTransitionState = {
4322
+ this.currentTransition = overallTransitionState = {
4317
4323
  ...t,
4318
4324
  targetSnapshot,
4319
4325
  urlAfterRedirects: extractedUrl,
@@ -4329,10 +4335,9 @@ class NavigationTransitions {
4329
4335
  */
4330
4336
  const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
4331
4337
  `Navigation was ignored because the UrlHandlingStrategy` +
4332
- ` indicated neither the current URL ${router.rawUrlTree} nor target URL ${t.rawUrl} should be processed.` :
4338
+ ` indicated neither the current URL ${t.currentRawUrl} nor target URL ${t.rawUrl} should be processed.` :
4333
4339
  '';
4334
- this.events.next(new NavigationSkipped(t.id, router.serializeUrl(overallTransitionState.extractedUrl), reason, 1 /* NavigationSkippedCode.IgnoredByUrlHandlingStrategy */));
4335
- router.rawUrlTree = t.rawUrl;
4340
+ this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, 1 /* NavigationSkippedCode.IgnoredByUrlHandlingStrategy */));
4336
4341
  t.resolve(null);
4337
4342
  return EMPTY;
4338
4343
  }
@@ -4342,7 +4347,7 @@ class NavigationTransitions {
4342
4347
  const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4343
4348
  this.events.next(guardsStart);
4344
4349
  }), map(t => {
4345
- overallTransitionState = {
4350
+ this.currentTransition = overallTransitionState = {
4346
4351
  ...t,
4347
4352
  guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
4348
4353
  };
@@ -4356,7 +4361,6 @@ class NavigationTransitions {
4356
4361
  this.events.next(guardsEnd);
4357
4362
  }), filter(t => {
4358
4363
  if (!t.guardsResult) {
4359
- router.restoreHistory(t);
4360
4364
  this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */);
4361
4365
  return false;
4362
4366
  }
@@ -4374,7 +4378,6 @@ class NavigationTransitions {
4374
4378
  next: () => dataResolved = true,
4375
4379
  complete: () => {
4376
4380
  if (!dataResolved) {
4377
- router.restoreHistory(t);
4378
4381
  this.cancelNavigationTransition(t, (typeof ngDevMode === 'undefined' || ngDevMode) ?
4379
4382
  `At least one route resolver didn't emit any value.` :
4380
4383
  '', 2 /* NavigationCancellationCode.NoDataFromResolver */);
@@ -4408,26 +4411,11 @@ class NavigationTransitions {
4408
4411
  .pipe(defaultIfEmpty(), take(1));
4409
4412
  }), switchTap(() => this.afterPreactivation()), map((t) => {
4410
4413
  const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4411
- overallTransitionState = { ...t, targetRouterState };
4412
- return (overallTransitionState);
4413
- }),
4414
- /* Once here, we are about to activate synchronously. The assumption is
4415
- this will succeed, and user code may read from the Router service.
4416
- Therefore before activation, we need to update router properties storing
4417
- the current URL and the RouterState, as well as updated the browser URL.
4418
- All this should happen *before* activating. */
4419
- tap((t) => {
4420
- router.currentUrlTree = t.urlAfterRedirects;
4421
- router.rawUrlTree =
4422
- router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
4423
- router.routerState =
4424
- t.targetRouterState;
4425
- if (router.urlUpdateStrategy === 'deferred') {
4426
- if (!t.extras.skipLocationChange) {
4427
- router.setBrowserUrl(router.rawUrlTree, t);
4428
- }
4429
- router.browserUrlTree = t.urlAfterRedirects;
4430
- }
4414
+ this.currentTransition =
4415
+ overallTransitionState = { ...t, targetRouterState };
4416
+ return overallTransitionState;
4417
+ }), tap(() => {
4418
+ this.events.next(new BeforeActivateRoutes());
4431
4419
  }), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt), this.inputBindingEnabled),
4432
4420
  // Ensure that if some observable used to drive the transition doesn't
4433
4421
  // complete, the navigation still finalizes This should never happen, but
@@ -4436,15 +4424,24 @@ class NavigationTransitions {
4436
4424
  next: (t) => {
4437
4425
  completed = true;
4438
4426
  this.lastSuccessfulNavigation = this.currentNavigation;
4439
- router.navigated = true;
4440
- this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(router.currentUrlTree)));
4427
+ this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
4441
4428
  router.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
4442
4429
  t.resolve(true);
4443
4430
  },
4444
4431
  complete: () => {
4445
4432
  completed = true;
4446
4433
  }
4447
- }), finalize(() => {
4434
+ }),
4435
+ // There used to be a lot more logic happening directly within the
4436
+ // transition Observable. Some of this logic has been refactored out to
4437
+ // other places but there may still be errors that happen there. This gives
4438
+ // us a way to cancel the transition from the outside. This may also be
4439
+ // required in the future to support something like the abort signal of the
4440
+ // Navigation API where the navigation gets aborted from outside the
4441
+ // transition.
4442
+ takeUntil(this.transitionAbortSubject.pipe(tap(err => {
4443
+ throw err;
4444
+ }))), finalize(() => {
4448
4445
  /* When the navigation stream finishes either through error or success,
4449
4446
  * we set the `completed` or `errored` flag. However, there are some
4450
4447
  * situations where we could get here without either of those being set.
@@ -4468,47 +4465,20 @@ class NavigationTransitions {
4468
4465
  /* This error type is issued during Redirect, and is handled as a
4469
4466
  * cancellation rather than an error. */
4470
4467
  if (isNavigationCancelingError$1(e)) {
4471
- if (!isRedirectingNavigationCancelingError$1(e)) {
4472
- // Set property only if we're not redirecting. If we landed on a page
4473
- // and redirect to `/` route, the new navigation is going to see the
4474
- // `/` isn't a change from the default currentUrlTree and won't
4475
- // navigate. This is only applicable with initial navigation, so
4476
- // setting `navigated` only when not redirecting resolves this
4477
- // scenario.
4478
- router.navigated = true;
4479
- router.restoreHistory(overallTransitionState, true);
4480
- }
4481
- const navCancel = new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
4482
- this.events.next(navCancel);
4468
+ this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode));
4483
4469
  // When redirecting, we need to delay resolving the navigation
4484
4470
  // promise and push it to the redirect navigation
4485
4471
  if (!isRedirectingNavigationCancelingError$1(e)) {
4486
4472
  overallTransitionState.resolve(false);
4487
4473
  }
4488
4474
  else {
4489
- const mergedTree = router.urlHandlingStrategy.merge(e.url, router.rawUrlTree);
4490
- const extras = {
4491
- skipLocationChange: overallTransitionState.extras.skipLocationChange,
4492
- // The URL is already updated at this point if we have 'eager' URL
4493
- // updates or if the navigation was triggered by the browser (back
4494
- // button, URL bar, etc). We want to replace that item in history
4495
- // if the navigation is rejected.
4496
- replaceUrl: router.urlUpdateStrategy === 'eager' ||
4497
- isBrowserTriggeredNavigation(overallTransitionState.source)
4498
- };
4499
- router.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
4500
- resolve: overallTransitionState.resolve,
4501
- reject: overallTransitionState.reject,
4502
- promise: overallTransitionState.promise
4503
- });
4475
+ this.events.next(new RedirectRequest(e.url));
4504
4476
  }
4505
4477
  /* All other errors should reset to the router's internal URL reference
4506
4478
  * to the pre-error state. */
4507
4479
  }
4508
4480
  else {
4509
- router.restoreHistory(overallTransitionState, true);
4510
- const navError = new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
4511
- this.events.next(navError);
4481
+ this.events.next(new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined));
4512
4482
  try {
4513
4483
  overallTransitionState.resolve(router.errorHandler(e));
4514
4484
  }
@@ -4526,10 +4496,10 @@ class NavigationTransitions {
4526
4496
  this.events.next(navCancel);
4527
4497
  t.resolve(false);
4528
4498
  }
4529
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4530
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4499
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4500
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4531
4501
  }
4532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NavigationTransitions, decorators: [{
4502
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NavigationTransitions, decorators: [{
4533
4503
  type: Injectable,
4534
4504
  args: [{ providedIn: 'root' }]
4535
4505
  }], ctorParameters: function () { return []; } });
@@ -4580,10 +4550,10 @@ class TitleStrategy {
4580
4550
  getResolvedTitleForRoute(snapshot) {
4581
4551
  return snapshot.data[RouteTitleKey];
4582
4552
  }
4583
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4584
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4553
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4554
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4585
4555
  }
4586
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: TitleStrategy, decorators: [{
4556
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: TitleStrategy, decorators: [{
4587
4557
  type: Injectable,
4588
4558
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4589
4559
  }] });
@@ -4606,10 +4576,10 @@ class DefaultTitleStrategy extends TitleStrategy {
4606
4576
  this.title.setTitle(title);
4607
4577
  }
4608
4578
  }
4609
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4610
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4579
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4580
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4611
4581
  }
4612
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4582
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4613
4583
  type: Injectable,
4614
4584
  args: [{ providedIn: 'root' }]
4615
4585
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -4622,10 +4592,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImpor
4622
4592
  * @publicApi
4623
4593
  */
4624
4594
  class RouteReuseStrategy {
4625
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4626
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4595
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4596
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4627
4597
  }
4628
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4598
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4629
4599
  type: Injectable,
4630
4600
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
4631
4601
  }] });
@@ -4676,10 +4646,10 @@ class BaseRouteReuseStrategy {
4676
4646
  }
4677
4647
  }
4678
4648
  class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4679
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4680
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4649
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4650
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4681
4651
  }
4682
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4652
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4683
4653
  type: Injectable,
4684
4654
  args: [{ providedIn: 'root' }]
4685
4655
  }] });
@@ -4702,10 +4672,10 @@ const ROUTER_CONFIGURATION = new InjectionToken((typeof ngDevMode === 'undefined
4702
4672
  * @publicApi
4703
4673
  */
4704
4674
  class UrlHandlingStrategy {
4705
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4706
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4675
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4676
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4707
4677
  }
4708
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4678
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4709
4679
  type: Injectable,
4710
4680
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4711
4681
  }] });
@@ -4722,10 +4692,10 @@ class DefaultUrlHandlingStrategy {
4722
4692
  merge(newUrlPart, wholeUrl) {
4723
4693
  return newUrlPart;
4724
4694
  }
4725
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4726
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4695
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4696
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4727
4697
  }
4728
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4698
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4729
4699
  type: Injectable,
4730
4700
  args: [{ providedIn: 'root' }]
4731
4701
  }] });
@@ -4814,9 +4784,9 @@ class Router {
4814
4784
  */
4815
4785
  get browserPageId() {
4816
4786
  if (this.canceledNavigationResolution !== 'computed') {
4817
- return undefined;
4787
+ return this.currentPageId;
4818
4788
  }
4819
- return this.location.getState()?.ɵrouterPageId;
4789
+ return this.location.getState()?.ɵrouterPageId ?? this.currentPageId;
4820
4790
  }
4821
4791
  /**
4822
4792
  * An event stream for routing events.
@@ -4826,7 +4796,7 @@ class Router {
4826
4796
  // cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't
4827
4797
  // allowed/supported but we still have to fix these or file bugs against the teams before making
4828
4798
  // the change.
4829
- return this.navigationTransitions.events;
4799
+ return this._events;
4830
4800
  }
4831
4801
  constructor() {
4832
4802
  this.disposed = false;
@@ -4841,6 +4811,12 @@ class Router {
4841
4811
  this.currentPageId = 0;
4842
4812
  this.console = inject(ɵConsole);
4843
4813
  this.isNgZoneEnabled = false;
4814
+ /**
4815
+ * The private `Subject` type for the public events exposed in the getter. This is used internally
4816
+ * to push events to. The separate field allows us to expose separate types in the public API
4817
+ * (i.e., an Observable rather than the Subject).
4818
+ */
4819
+ this._events = new Subject();
4844
4820
  this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4845
4821
  this.pendingTasks = inject(ɵInitialRenderPendingTasks);
4846
4822
  /**
@@ -4966,18 +4942,110 @@ class Router {
4966
4942
  * `bindToComponentInputs` in the `ExtraOptions` of `RouterModule.forRoot`.
4967
4943
  */
4968
4944
  this.componentInputBindingEnabled = !!inject(INPUT_BINDER, { optional: true });
4945
+ this.eventsSubscription = new Subscription();
4969
4946
  this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
4970
4947
  this.resetConfig(this.config);
4971
4948
  this.currentUrlTree = new UrlTree();
4972
4949
  this.rawUrlTree = this.currentUrlTree;
4973
4950
  this.browserUrlTree = this.currentUrlTree;
4974
4951
  this.routerState = createEmptyState(this.currentUrlTree, null);
4975
- this.navigationTransitions.setupNavigations(this).subscribe(t => {
4952
+ this.navigationTransitions.setupNavigations(this, this.currentUrlTree, this.routerState)
4953
+ .subscribe(t => {
4976
4954
  this.lastSuccessfulId = t.id;
4977
- this.currentPageId = this.browserPageId ?? 0;
4955
+ this.currentPageId = this.browserPageId;
4978
4956
  }, e => {
4979
4957
  this.console.warn(`Unhandled Navigation Error: ${e}`);
4980
4958
  });
4959
+ this.subscribeToNavigationEvents();
4960
+ }
4961
+ subscribeToNavigationEvents() {
4962
+ const subscription = this.navigationTransitions.events.subscribe(e => {
4963
+ try {
4964
+ const { currentTransition } = this.navigationTransitions;
4965
+ if (currentTransition === null) {
4966
+ if (isPublicRouterEvent(e)) {
4967
+ this._events.next(e);
4968
+ }
4969
+ return;
4970
+ }
4971
+ if (e instanceof NavigationStart) {
4972
+ // If the source of the navigation is from a browser event, the URL is
4973
+ // already updated. We already need to sync the internal state.
4974
+ if (isBrowserTriggeredNavigation(currentTransition.source)) {
4975
+ this.browserUrlTree = currentTransition.extractedUrl;
4976
+ }
4977
+ }
4978
+ else if (e instanceof NavigationSkipped) {
4979
+ this.rawUrlTree = currentTransition.rawUrl;
4980
+ }
4981
+ else if (e instanceof RoutesRecognized) {
4982
+ if (this.urlUpdateStrategy === 'eager') {
4983
+ if (!currentTransition.extras.skipLocationChange) {
4984
+ const rawUrl = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4985
+ this.setBrowserUrl(rawUrl, currentTransition);
4986
+ }
4987
+ this.browserUrlTree = currentTransition.urlAfterRedirects;
4988
+ }
4989
+ }
4990
+ else if (e instanceof BeforeActivateRoutes) {
4991
+ this.currentUrlTree = currentTransition.urlAfterRedirects;
4992
+ this.rawUrlTree = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4993
+ this.routerState = currentTransition.targetRouterState;
4994
+ if (this.urlUpdateStrategy === 'deferred') {
4995
+ if (!currentTransition.extras.skipLocationChange) {
4996
+ this.setBrowserUrl(this.rawUrlTree, currentTransition);
4997
+ }
4998
+ this.browserUrlTree = currentTransition.urlAfterRedirects;
4999
+ }
5000
+ }
5001
+ else if (e instanceof NavigationCancel) {
5002
+ if (e.code !== 0 /* NavigationCancellationCode.Redirect */ &&
5003
+ e.code !== 1 /* NavigationCancellationCode.SupersededByNewNavigation */) {
5004
+ // It seems weird that `navigated` is set to `true` when the navigation is rejected,
5005
+ // however it's how things were written initially. Investigation would need to be done
5006
+ // to determine if this can be removed.
5007
+ this.navigated = true;
5008
+ }
5009
+ if (e.code === 3 /* NavigationCancellationCode.GuardRejected */ ||
5010
+ e.code === 2 /* NavigationCancellationCode.NoDataFromResolver */) {
5011
+ this.restoreHistory(currentTransition);
5012
+ }
5013
+ }
5014
+ else if (e instanceof RedirectRequest) {
5015
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
5016
+ const extras = {
5017
+ skipLocationChange: currentTransition.extras.skipLocationChange,
5018
+ // The URL is already updated at this point if we have 'eager' URL
5019
+ // updates or if the navigation was triggered by the browser (back
5020
+ // button, URL bar, etc). We want to replace that item in history
5021
+ // if the navigation is rejected.
5022
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
5023
+ isBrowserTriggeredNavigation(currentTransition.source)
5024
+ };
5025
+ this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
5026
+ resolve: currentTransition.resolve,
5027
+ reject: currentTransition.reject,
5028
+ promise: currentTransition.promise
5029
+ });
5030
+ }
5031
+ if (e instanceof NavigationError) {
5032
+ this.restoreHistory(currentTransition, true);
5033
+ }
5034
+ if (e instanceof NavigationEnd) {
5035
+ this.navigated = true;
5036
+ }
5037
+ // Note that it's important to have the Router process the events _before_ the event is
5038
+ // pushed through the public observable. This ensures the correct router state is in place
5039
+ // before applications observe the events.
5040
+ if (isPublicRouterEvent(e)) {
5041
+ this._events.next(e);
5042
+ }
5043
+ }
5044
+ catch (e) {
5045
+ this.navigationTransitions.transitionAbortSubject.next(e);
5046
+ }
5047
+ });
5048
+ this.eventsSubscription.add(subscription);
4981
5049
  }
4982
5050
  /** @internal */
4983
5051
  resetRootComponentType(rootComponentType) {
@@ -5100,6 +5168,7 @@ class Router {
5100
5168
  this.locationSubscription = undefined;
5101
5169
  }
5102
5170
  this.disposed = true;
5171
+ this.eventsSubscription.unsubscribe();
5103
5172
  }
5104
5173
  /**
5105
5174
  * Appends URL segments to the current URL tree to create a new URL tree.
@@ -5333,6 +5402,7 @@ class Router {
5333
5402
  restoredState,
5334
5403
  currentUrlTree: this.currentUrlTree,
5335
5404
  currentRawUrl: this.currentUrlTree,
5405
+ currentBrowserUrl: this.browserUrlTree,
5336
5406
  rawUrl,
5337
5407
  extras,
5338
5408
  resolve,
@@ -5362,7 +5432,7 @@ class Router {
5362
5432
  else {
5363
5433
  const state = {
5364
5434
  ...transition.extras.state,
5365
- ...this.generateNgRouterState(transition.id, (this.browserPageId ?? 0) + 1)
5435
+ ...this.generateNgRouterState(transition.id, this.browserPageId + 1)
5366
5436
  };
5367
5437
  this.location.go(path, '', state);
5368
5438
  }
@@ -5374,7 +5444,7 @@ class Router {
5374
5444
  */
5375
5445
  restoreHistory(transition, restoringFromCaughtError = false) {
5376
5446
  if (this.canceledNavigationResolution === 'computed') {
5377
- const currentBrowserPageId = this.browserPageId ?? this.currentPageId;
5447
+ const currentBrowserPageId = this.browserPageId;
5378
5448
  const targetPagePosition = this.currentPageId - currentBrowserPageId;
5379
5449
  if (targetPagePosition !== 0) {
5380
5450
  this.location.historyGo(targetPagePosition);
@@ -5425,10 +5495,10 @@ class Router {
5425
5495
  }
5426
5496
  return { navigationId };
5427
5497
  }
5428
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5429
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: Router, providedIn: 'root' }); }
5498
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5499
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: Router, providedIn: 'root' }); }
5430
5500
  }
5431
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: Router, decorators: [{
5501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: Router, decorators: [{
5432
5502
  type: Injectable,
5433
5503
  args: [{ providedIn: 'root' }]
5434
5504
  }], ctorParameters: function () { return []; } });
@@ -5441,6 +5511,9 @@ function validateCommands(commands) {
5441
5511
  }
5442
5512
  }
5443
5513
  }
5514
+ function isPublicRouterEvent(e) {
5515
+ return (!(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest));
5516
+ }
5444
5517
 
5445
5518
  /**
5446
5519
  * @description
@@ -5696,10 +5769,10 @@ class RouterLink {
5696
5769
  preserveFragment: this.preserveFragment,
5697
5770
  });
5698
5771
  }
5699
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive }); }
5700
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5772
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive }); }
5773
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "16.2.2", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5701
5774
  }
5702
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterLink, decorators: [{
5775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterLink, decorators: [{
5703
5776
  type: Directive,
5704
5777
  args: [{
5705
5778
  selector: '[routerLink]',
@@ -5826,7 +5899,7 @@ class RouterLinkActive {
5826
5899
  *
5827
5900
  * These options are passed to the `Router.isActive()` function.
5828
5901
  *
5829
- * @see Router.isActive
5902
+ * @see {@link Router#isActive}
5830
5903
  */
5831
5904
  this.routerLinkActiveOptions = { exact: false };
5832
5905
  /**
@@ -5922,10 +5995,10 @@ class RouterLinkActive {
5922
5995
  const isActiveCheckFn = this.isLinkActive(this.router);
5923
5996
  return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
5924
5997
  }
5925
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
5926
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.1", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 }); }
5998
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
5999
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.2", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 }); }
5927
6000
  }
5928
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterLinkActive, decorators: [{
6001
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterLinkActive, decorators: [{
5929
6002
  type: Directive,
5930
6003
  args: [{
5931
6004
  selector: '[routerLinkActive]',
@@ -5977,10 +6050,10 @@ class PreloadAllModules {
5977
6050
  preload(route, fn) {
5978
6051
  return fn().pipe(catchError(() => of(null)));
5979
6052
  }
5980
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5981
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
6053
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6054
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
5982
6055
  }
5983
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: PreloadAllModules, decorators: [{
6056
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: PreloadAllModules, decorators: [{
5984
6057
  type: Injectable,
5985
6058
  args: [{ providedIn: 'root' }]
5986
6059
  }] });
@@ -5997,10 +6070,10 @@ class NoPreloading {
5997
6070
  preload(route, fn) {
5998
6071
  return of(null);
5999
6072
  }
6000
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6001
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6073
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6074
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6002
6075
  }
6003
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: NoPreloading, decorators: [{
6076
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: NoPreloading, decorators: [{
6004
6077
  type: Injectable,
6005
6078
  args: [{ providedIn: 'root' }]
6006
6079
  }] });
@@ -6093,10 +6166,10 @@ class RouterPreloader {
6093
6166
  }
6094
6167
  });
6095
6168
  }
6096
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6097
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6169
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6170
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6098
6171
  }
6099
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterPreloader, decorators: [{
6172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterPreloader, decorators: [{
6100
6173
  type: Injectable,
6101
6174
  args: [{ providedIn: 'root' }]
6102
6175
  }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
@@ -6189,10 +6262,10 @@ class RouterScroller {
6189
6262
  this.routerEventsSubscription?.unsubscribe();
6190
6263
  this.scrollEventsSubscription?.unsubscribe();
6191
6264
  }
6192
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6193
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterScroller }); }
6265
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6266
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterScroller }); }
6194
6267
  }
6195
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterScroller, decorators: [{
6268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterScroller, decorators: [{
6196
6269
  type: Injectable
6197
6270
  }], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
6198
6271
 
@@ -6799,11 +6872,11 @@ class RouterModule {
6799
6872
  providers: [{ provide: ROUTES, multi: true, useValue: routes }],
6800
6873
  };
6801
6874
  }
6802
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6803
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6804
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterModule }); }
6875
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6876
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.2", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6877
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterModule }); }
6805
6878
  }
6806
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RouterModule, decorators: [{
6879
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: RouterModule, decorators: [{
6807
6880
  type: NgModule,
6808
6881
  args: [{
6809
6882
  imports: ROUTER_DIRECTIVES,
@@ -6948,7 +7021,7 @@ function mapToResolve(provider) {
6948
7021
  /**
6949
7022
  * @publicApi
6950
7023
  */
6951
- const VERSION = new Version('16.2.1');
7024
+ const VERSION = new Version('16.2.2');
6952
7025
 
6953
7026
  /**
6954
7027
  * @module