Revert "refactor(router): compress synchronous end to router navigation to single operator"

This reverts commit 71362733cf.
This commit is contained in:
Andrew Scott 2025-12-02 10:03:21 -08:00 committed by Pawel Kozlowski
parent 71362733cf
commit c2a8934d12
3 changed files with 60 additions and 42 deletions

View file

@ -385,6 +385,7 @@
"_stripOrigin",
"_wasLastNodeCreated",
"abortSignalToObservable",
"activateRoutes",
"activeConsumer",
"addAfterRenderSequencesForView",
"addEmptyPathsToChildrenIfNeeded",

View file

@ -58,7 +58,7 @@ import {
isRedirectingNavigationCancelingError,
redirectingNavigationError,
} from './navigation_canceling_error';
import {ActivateRoutes} from './operators/activate_routes';
import {activateRoutes} from './operators/activate_routes';
import {checkGuards} from './operators/check_guards';
import {recognize} from './operators/recognize';
import {resolveData} from './operators/resolve_data';
@ -725,7 +725,6 @@ export class NavigationTransitions {
switchTap(() => this.afterPreactivation()),
// TODO(atscott): Move this into the last block below.
switchMap(() => {
const {currentSnapshot, targetSnapshot} = overallTransitionState;
const viewTransitionStarted = this.createViewTransition?.(
@ -741,57 +740,36 @@ export class NavigationTransitions {
: of(overallTransitionState);
}),
// Ensure that if some observable used to drive the transition doesn't
// complete, the navigation still finalizes This should never happen, but
// this is done as a safety measure to avoid surfacing this error (#49567).
take(1),
map((t: NavigationTransition) => {
const targetRouterState = createRouterState(
router.routeReuseStrategy,
t.targetSnapshot!,
t.currentRouterState,
);
this.currentTransition = overallTransitionState = t = {...t, targetRouterState};
this.currentTransition = overallTransitionState = {...t, targetRouterState};
this.currentNavigation.update((nav) => {
nav!.targetRouterState = targetRouterState;
return nav;
});
this.events.next(new BeforeActivateRoutes());
if (!shouldContinueNavigation()) {
return;
}
new ActivateRoutes(
router.routeReuseStrategy,
overallTransitionState.targetRouterState!,
overallTransitionState.currentRouterState,
(evt: Event) => this.events.next(evt),
this.inputBindingEnabled,
).activate(this.rootContexts);
if (!shouldContinueNavigation()) {
return;
}
completedOrAborted = true;
this.currentNavigation.update((nav) => {
(nav as Writable<Navigation>).abort = noop;
return nav;
});
this.lastSuccessfulNavigation.set(untracked(this.currentNavigation));
this.events.next(
new NavigationEnd(
t.id,
this.urlSerializer.serialize(t.extractedUrl),
this.urlSerializer.serialize(t.urlAfterRedirects!),
),
);
this.titleStrategy?.updateTitle(t.targetRouterState!.snapshot);
t.resolve(true);
return overallTransitionState;
}),
tap(() => {
this.events.next(new BeforeActivateRoutes());
}),
activateRoutes(
this.rootContexts,
router.routeReuseStrategy,
(evt: Event) => this.events.next(evt),
this.inputBindingEnabled,
),
// Ensure that if some observable used to drive the transition doesn't
// complete, the navigation still finalizes This should never happen, but
// this is done as a safety measure to avoid surfacing this error (#49567).
take(1),
takeUntil(
abortSignalToObservable(abortController.signal).pipe(
// Ignore aborts if we are already completed, canceled, or are in the activation stage (we have targetRouterState)
@ -807,6 +785,23 @@ export class NavigationTransitions {
),
tap({
next: (t: NavigationTransition) => {
completedOrAborted = true;
this.currentNavigation.update((nav) => {
(nav as Writable<Navigation>).abort = noop;
return nav;
});
this.lastSuccessfulNavigation.set(untracked(this.currentNavigation));
this.events.next(
new NavigationEnd(
t.id,
this.urlSerializer.serialize(t.extractedUrl),
this.urlSerializer.serialize(t.urlAfterRedirects!),
),
);
this.titleStrategy?.updateTitle(t.targetRouterState!.snapshot);
t.resolve(true);
},
complete: () => {
completedOrAborted = true;
},
@ -854,7 +849,6 @@ export class NavigationTransitions {
}
}),
catchError((e) => {
completedOrAborted = true;
// If the application is already destroyed, the catch block should not
// execute anything in practice because other resources have already
// been released and destroyed.
@ -863,6 +857,7 @@ export class NavigationTransitions {
return EMPTY;
}
completedOrAborted = true;
/* This error type is issued during Redirect, and is handled as a
* cancellation rather than an error. */
if (isNavigationCancelingError(e)) {

View file

@ -6,13 +6,35 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {MonoTypeOperatorFunction} from 'rxjs';
import {map} from 'rxjs/operators';
import {ActivationEnd, ChildActivationEnd, Event} from '../events';
import type {NavigationTransition} from '../navigation_transition';
import type {DetachedRouteHandleInternal, RouteReuseStrategy} from '../route_reuse_strategy';
import type {ChildrenOutletContexts} from '../router_outlet_context';
import {ActivatedRoute, advanceActivatedRoute, RouterState} from '../router_state';
import {nodeChildrenAsMap, TreeNode} from '../utils/tree';
let warnedAboutUnsupportedInputBinding = false;
export const activateRoutes = (
rootContexts: ChildrenOutletContexts,
routeReuseStrategy: RouteReuseStrategy,
forwardEvent: (evt: Event) => void,
inputBindingEnabled: boolean,
): MonoTypeOperatorFunction<NavigationTransition> =>
map((t) => {
new ActivateRoutes(
routeReuseStrategy,
t.targetRouterState!,
t.currentRouterState,
forwardEvent,
inputBindingEnabled,
).activate(rootContexts);
return t;
});
export class ActivateRoutes {
constructor(
private routeReuseStrategy: RouteReuseStrategy,