Skip to content

Commit 97fd1de

Browse files
atscottkirjs
authored andcommitted
Revert "refactor(router): Add support for precommitHandler in Navigation integration"
This reverts commit 522fa71.
1 parent 397dbc4 commit 97fd1de

10 files changed

Lines changed: 50 additions & 200 deletions

File tree

packages/core/test/bundling/router/bundle.golden_symbols.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
"BROWSER_MODULE_PROVIDERS",
3030
"BaseRouteReuseStrategy",
3131
"BeforeActivateRoutes",
32-
"BeforeRoutesRecognized",
3332
"BehaviorSubject",
3433
"BrowserDomAdapter",
3534
"BrowserPlatformLocation",

packages/router/src/events.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -630,20 +630,15 @@ export class Scroll {
630630
}
631631

632632
export class BeforeActivateRoutes {}
633-
export class BeforeRoutesRecognized {}
634633
export class RedirectRequest {
635634
constructor(
636635
readonly url: UrlTree,
637636
readonly navigationBehaviorOptions: NavigationBehaviorOptions | undefined,
638637
) {}
639638
}
640-
export type PrivateRouterEvents = BeforeActivateRoutes | RedirectRequest | BeforeRoutesRecognized;
639+
export type PrivateRouterEvents = BeforeActivateRoutes | RedirectRequest;
641640
export function isPublicRouterEvent(e: Event | PrivateRouterEvents): e is Event {
642-
return (
643-
!(e instanceof BeforeActivateRoutes) &&
644-
!(e instanceof RedirectRequest) &&
645-
!(e instanceof BeforeRoutesRecognized)
646-
);
641+
return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest);
647642
}
648643

649644
/**

packages/router/src/navigation_transition.ts

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import {createRouterState} from './create_router_state';
2727
import {INPUT_BINDER} from './directives/router_outlet';
2828
import {
2929
BeforeActivateRoutes,
30-
BeforeRoutesRecognized,
3130
Event,
3231
GuardsCheckEnd,
3332
GuardsCheckStart,
@@ -297,11 +296,6 @@ export interface Navigation {
297296
* This function is a no-op if the navigation is beyond the point where it can be aborted.
298297
*/
299298
readonly abort: () => void;
300-
301-
/** @internal */
302-
routesRecognizeHandler: {deferredHandle?: Promise<void>};
303-
/** @internal */
304-
beforeActivateHandler: {deferredHandle?: Promise<void>};
305299
}
306300

307301
const noop = () => {};
@@ -325,9 +319,6 @@ export interface NavigationTransition {
325319
targetRouterState: RouterState | null;
326320
guards: Checks;
327321
guardsResult: GuardResult | null;
328-
329-
routesRecognizeHandler: {deferredHandle?: Promise<void>};
330-
beforeActivateHandler: {deferredHandle?: Promise<void>};
331322
}
332323

333324
export const NAVIGATION_ERROR_HANDLER = new InjectionToken<
@@ -427,9 +418,6 @@ export class NavigationTransitions {
427418
guards: {canActivateChecks: [], canDeactivateChecks: []},
428419
guardsResult: null,
429420
id,
430-
431-
routesRecognizeHandler: {},
432-
beforeActivateHandler: {},
433421
});
434422
});
435423
}
@@ -484,9 +472,6 @@ export class NavigationTransitions {
484472
previousNavigation: null,
485473
},
486474
abort: () => abortController.abort(),
487-
488-
routesRecognizeHandler: t.routesRecognizeHandler,
489-
beforeActivateHandler: t.beforeActivateHandler,
490475
});
491476
const urlTransition =
492477
!router.navigated || this.isUpdatingInternalState() || this.isUpdatedBrowserUrl();
@@ -549,16 +534,7 @@ export class NavigationTransitions {
549534
nav!.finalUrl = t.urlAfterRedirects;
550535
return nav;
551536
});
552-
this.events.next(new BeforeRoutesRecognized());
553-
}),
554537

555-
switchMap((value) =>
556-
from(
557-
overallTransitionState.routesRecognizeHandler.deferredHandle ?? of(void 0),
558-
).pipe(map(() => value)),
559-
),
560-
561-
tap(() => {
562538
// Fire RoutesRecognized
563539
const routesRecognized = new RoutesRecognized(
564540
t.id,
@@ -759,7 +735,7 @@ export class NavigationTransitions {
759735
// this is done as a safety measure to avoid surfacing this error (#49567).
760736
take(1),
761737

762-
switchMap(async (t: NavigationTransition) => {
738+
map((t: NavigationTransition) => {
763739
const targetRouterState = createRouterState(
764740
router.routeReuseStrategy,
765741
t.targetSnapshot!,
@@ -775,12 +751,7 @@ export class NavigationTransitions {
775751
if (!shouldContinueNavigation()) {
776752
return;
777753
}
778-
if (overallTransitionState.beforeActivateHandler.deferredHandle) {
779-
await overallTransitionState.beforeActivateHandler.deferredHandle;
780-
}
781-
if (!shouldContinueNavigation()) {
782-
return;
783-
}
754+
784755
new ActivateRoutes(
785756
router.routeReuseStrategy,
786757
overallTransitionState.targetRouterState!,

packages/router/src/router.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ export class Router {
293293
this.location.path(true),
294294
IMPERATIVE_NAVIGATION,
295295
this.stateManager.restoredState(),
296-
{replaceUrl: true},
297296
);
298297
}
299298
}
@@ -308,11 +307,9 @@ export class Router {
308307
// already patch onPopState, so location change callback will
309308
// run into ngZone
310309
this.nonRouterCurrentEntryChangeSubscription ??=
311-
this.stateManager.registerNonRouterCurrentEntryChangeListener(
312-
(url, state, source, extras) => {
313-
this.navigateToSyncWithBrowser(url, source, state, extras);
314-
},
315-
);
310+
this.stateManager.registerNonRouterCurrentEntryChangeListener((url, state, source) => {
311+
this.navigateToSyncWithBrowser(url, source, state);
312+
});
316313
}
317314

318315
/**
@@ -326,8 +323,9 @@ export class Router {
326323
url: string,
327324
source: NavigationTrigger,
328325
state: RestoredState | null | undefined,
329-
extras: NavigationExtras,
330326
) {
327+
const extras: NavigationExtras = {replaceUrl: true};
328+
331329
// TODO: restoredState should always include the entire state, regardless
332330
// of navigationId. This requires a breaking change to update the type on
333331
// NavigationStart’s restoredState, which currently requires navigationId

packages/router/src/statemanager/navigation_state_manager.ts

Lines changed: 26 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,9 @@ import {
2020
ɵPRECOMMIT_HANDLER_SUPPORTED as PRECOMMIT_HANDLER_SUPPORTED,
2121
} from '@angular/common';
2222
import {StateManager} from './state_manager';
23-
import {
24-
NavigationExtras,
25-
RestoredState,
26-
Navigation as RouterNavigation,
27-
} from '../navigation_transition';
23+
import {RestoredState, Navigation as RouterNavigation} from '../navigation_transition';
2824
import {
2925
BeforeActivateRoutes,
30-
BeforeRoutesRecognized,
3126
isRedirectingEvent,
3227
NavigationCancel,
3328
NavigationCancellationCode,
@@ -37,6 +32,7 @@ import {
3732
NavigationStart,
3833
NavigationTrigger,
3934
PrivateRouterEvents,
35+
RoutesRecognized,
4036
} from '../events';
4137
import {Subject, SubscriptionLike} from 'rxjs';
4238
import {UrlTree} from '../url_tree';
@@ -89,7 +85,6 @@ export class NavigationStateManager extends StateManager {
8985
/** Function to resolve the intercepted navigation event. */
9086
resolveHandler?: (v: void) => void;
9187
navigationEvent?: NavigateEvent;
92-
commitUrl?: () => Promise<void>;
9388
} = {};
9489

9590
/**
@@ -129,18 +124,12 @@ export class NavigationStateManager extends StateManager {
129124
url: string,
130125
state: RestoredState | null | undefined,
131126
trigger: NavigationTrigger,
132-
extras: NavigationExtras,
133127
) => void,
134128
): SubscriptionLike {
135129
this.activeHistoryEntry = this.navigation.currentEntry!;
136130
this.nonRouterEntryChangeListener = this.nonRouterCurrentEntryChangeSubject.subscribe(
137131
({path, state}) => {
138-
listener(
139-
path,
140-
state,
141-
'popstate',
142-
!this.precommitHandlerSupported ? {replaceUrl: true} : {},
143-
);
132+
listener(path, state, 'popstate');
144133
},
145134
);
146135
return this.nonRouterEntryChangeListener;
@@ -161,46 +150,20 @@ export class NavigationStateManager extends StateManager {
161150
this.currentNavigation = {...this.currentNavigation, routerTransition: transition};
162151
if (e instanceof NavigationStart) {
163152
this.updateStateMemento();
164-
// If we have precommit handler support, we can create a navigation
165-
// immediately and redirect it later.
166-
if (this.precommitHandlerSupported) {
167-
this.maybeCreateNavigationForTransition(transition);
168-
}
169153
} else if (e instanceof NavigationSkipped) {
170154
this.finishNavigation();
171155
this.commitTransition(transition);
172-
} else if (e instanceof BeforeRoutesRecognized) {
173-
transition.routesRecognizeHandler.deferredHandle = new Promise<void>(async (resolve) => {
174-
if (this.urlUpdateStrategy === 'eager') {
175-
try {
176-
this.maybeCreateNavigationForTransition(transition);
177-
await this.currentNavigation.commitUrl?.();
178-
} catch {
179-
// If commit fails (e.g., precommitHandler rejects), abort.
180-
// The AbortSignal will notify
181-
return;
182-
}
183-
}
184-
resolve();
185-
});
156+
} else if (e instanceof RoutesRecognized) {
157+
if (this.urlUpdateStrategy === 'eager' && !transition.extras.skipLocationChange) {
158+
this.createNavigationForTransition(transition);
159+
}
186160
} else if (e instanceof BeforeActivateRoutes) {
187-
transition.beforeActivateHandler.deferredHandle = new Promise<void>(async (resolve) => {
188-
// If URL update strategy is 'deferred', commit the URL now (before activation).
189-
if (this.urlUpdateStrategy === 'deferred') {
190-
try {
191-
this.maybeCreateNavigationForTransition(transition);
192-
await this.currentNavigation.commitUrl?.();
193-
} catch {
194-
return;
195-
}
196-
}
197-
// Commit the internal router state.
198-
this.commitTransition(transition);
199-
resolve();
200-
});
161+
// Commit the internal router state.
162+
this.commitTransition(transition);
163+
if (this.urlUpdateStrategy === 'deferred' && !transition.extras.skipLocationChange) {
164+
this.createNavigationForTransition(transition);
165+
}
201166
} else if (e instanceof NavigationCancel || e instanceof NavigationError) {
202-
// TODO(atscott): We want to keep the navigation event on redirects if
203-
// the URL wasn't committed yet rather than cancelling it.
204167
void this.cancel(transition, e);
205168
} else if (e instanceof NavigationEnd) {
206169
const {resolveHandler, removeAbortListener} = this.currentNavigation;
@@ -220,19 +183,17 @@ export class NavigationStateManager extends StateManager {
220183
}
221184
}
222185

223-
private maybeCreateNavigationForTransition(transition: RouterNavigation) {
224-
const {navigationEvent, commitUrl} = this.currentNavigation;
186+
private createNavigationForTransition(transition: RouterNavigation) {
187+
const {navigationEvent} = this.currentNavigation;
188+
// If we are currently handling a traversal navigation, we do not need a new navigation for it
189+
// because we are strictly restoring a previous state. If we are instead handling a navigation
190+
// initiated outside the router, we do need to replace it with a router-triggered navigation
191+
// to add the router-specific state.
225192
if (
226-
// Presence of commitUrl function indicates the navigateEvent supports redirect
227-
commitUrl ||
228-
// If we are currently handling a traversal navigation, we do not need a new navigation for it
229-
// because we are strictly restoring a previous state. If we are instead handling a navigation
230-
// initiated outside the router, we do need to replace it with a router-triggered navigation
231-
// to add the router-specific state.
232-
(navigationEvent &&
233-
(navigationEvent.navigationType === 'traverse' ||
234-
navigationEvent.navigationType === 'reload') &&
235-
this.eventAndRouterDestinationsMatch(navigationEvent, transition))
193+
navigationEvent &&
194+
(navigationEvent.navigationType === 'traverse' ||
195+
navigationEvent.navigationType === 'reload') &&
196+
this.eventAndRouterDestinationsMatch(navigationEvent, transition)
236197
) {
237198
return;
238199
}
@@ -297,7 +258,6 @@ export class NavigationStateManager extends StateManager {
297258
* and resolving the post-commit handler promise. Clears the `currentNavigation` state.
298259
*/
299260
private finishNavigation() {
300-
this.currentNavigation.commitUrl?.();
301261
this.currentNavigation?.resolveHandler?.();
302262
this.currentNavigation = {};
303263
}
@@ -426,66 +386,18 @@ export class NavigationStateManager extends StateManager {
426386
resolve: resolveHandler,
427387
reject: rejectHandler,
428388
} = promiseWithResolvers<void>();
429-
430-
const {
431-
promise: precommitHandlerPromise,
432-
resolve: resolvePrecommitHandler,
433-
reject: rejectPrecommitHandler,
434-
} = promiseWithResolvers<void>();
435-
this.currentNavigation.rejectNavigateEvent = () => {
436-
event.signal.removeEventListener('abort', abortHandler);
437-
rejectPrecommitHandler();
438-
rejectHandler();
439-
};
440389
this.currentNavigation.resolveHandler = () => {
441390
this.currentNavigation.removeAbortListener?.();
442391
resolveHandler();
443392
};
393+
this.currentNavigation.rejectNavigateEvent = () => {
394+
this.currentNavigation.removeAbortListener?.();
395+
rejectHandler();
396+
};
444397
// Prevent unhandled promise rejections from internal promises.
445398
handlerPromise.catch(() => {});
446-
precommitHandlerPromise.catch(() => {});
447399
interceptOptions.handler = () => handlerPromise;
448400

449-
if (this.deferredCommitSupported(event)) {
450-
const redirect = new Promise<
451-
(url: string, options: {state: unknown; history?: 'push' | 'replace'}) => void
452-
>((resolve) => {
453-
// The `precommitHandler` option is not in the standard DOM types yet
454-
(interceptOptions as any).precommitHandler = (controller: any) => {
455-
resolve(controller.redirect.bind(controller));
456-
return precommitHandlerPromise;
457-
};
458-
});
459-
// `commitUrl` is a function that will be called by the router's lifecycle
460-
// (e.g., in `BeforeRoutesRecognized` or `BeforeActivateRoutes` depending on `urlUpdateStrategy`)
461-
// to actually perform the URL change via the Navigation API.
462-
this.currentNavigation.commitUrl = async () => {
463-
this.currentNavigation.commitUrl = undefined; // Ensure it's only called once.
464-
const transition = this.currentNavigation.routerTransition;
465-
466-
// If not skipping location change, use the `redirect` function (from `precommitHandler`'s
467-
// controller) to perform the URL update with the correct state and history action.
468-
if (transition && !transition.extras.skipLocationChange) {
469-
const internalPath = this.createBrowserPath(transition);
470-
const history =
471-
this.location.isCurrentPathEqualTo(internalPath) || !!transition.extras.replaceUrl
472-
? 'replace'
473-
: 'push';
474-
const state = {
475-
...transition.extras.state,
476-
navigationId: transition.id,
477-
};
478-
// this might be a path or an actual URL depending on the baseHref
479-
const pathOrUrl = this.location.prepareExternalUrl(internalPath);
480-
(await redirect)(pathOrUrl, {state, history});
481-
}
482-
resolvePrecommitHandler();
483-
// Wait for the Navigation API's own `committed` promise if available (part of transition object)
484-
// This ensures we respect the browser's timing for when the commit actually happens.
485-
return await this.navigation.transition?.committed;
486-
};
487-
}
488-
489401
// Intercept the navigation event with the configured options.
490402
event.intercept(interceptOptions);
491403

@@ -527,16 +439,6 @@ export class NavigationStateManager extends StateManager {
527439
const routerDestination = this.location.prepareExternalUrl(internalPath);
528440
return new URL(routerDestination, eventDestination.origin).href === eventDestination.href;
529441
}
530-
531-
private deferredCommitSupported(event: NavigateEvent): boolean {
532-
return (
533-
this.precommitHandlerSupported &&
534-
// Cannot defer commit if not cancelable by the Navigation API's rules.
535-
event.cancelable &&
536-
// Deferring a traversal commit is currently problematic or not fully supported.
537-
event.navigationType !== 'traverse'
538-
);
539-
}
540442
}
541443

542444
/**

0 commit comments

Comments
 (0)