From 99898f33703e46b7fec81babe83701705519af9e Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Tue, 1 Nov 2022 10:27:28 -0700 Subject: [PATCH] refactor(router): Remove code to support relativeLinkResolution (#47933) The public API for enabling this option has already been removed. This change updates the internal Router code to not include any logic to support it. PR Close #47933 --- goldens/public-api/router/index.md | 2 +- packages/router/src/create_url_tree.ts | 11 --- packages/router/src/operators/recognize.ts | 7 +- .../src/patchable_relative_link_resolution.ts | 15 ---- packages/router/src/recognize.ts | 25 ++---- packages/router/src/router.ts | 13 +--- packages/router/src/router_config.ts | 4 +- packages/router/src/router_state.ts | 10 +-- packages/router/src/utils/config_matching.ts | 18 ++--- packages/router/test/recognize.spec.ts | 77 +++++++++---------- 10 files changed, 56 insertions(+), 126 deletions(-) delete mode 100644 packages/router/src/patchable_relative_link_resolution.ts diff --git a/goldens/public-api/router/index.md b/goldens/public-api/router/index.md index 9bac8718c47..6c1976b26d6 100644 --- a/goldens/public-api/router/index.md +++ b/goldens/public-api/router/index.md @@ -288,7 +288,7 @@ export const enum EventType { } // @public -export interface ExtraOptions extends InMemoryScrollingOptions, RouterConfigOptions, InternalExtraOptions { +export interface ExtraOptions extends InMemoryScrollingOptions, RouterConfigOptions { enableTracing?: boolean; errorHandler?: ErrorHandler; initialNavigation?: InitialNavigation; diff --git a/packages/router/src/create_url_tree.ts b/packages/router/src/create_url_tree.ts index e786b9c11e5..4fc56408dad 100644 --- a/packages/router/src/create_url_tree.ts +++ b/packages/router/src/create_url_tree.ts @@ -151,17 +151,6 @@ export function createUrlTree( // didn't before. const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex); - // Check if application is relying on `relativeLinkResolution: 'legacy'` - if (typeof ngDevMode === 'undefined' || !!ngDevMode) { - const correctedResult = createTreeUsingPathIndex(route.snapshot?._correctedLastPathIndex); - if (correctedResult.toString() !== result.toString()) { - console.warn( - `relativeLinkResolution: 'legacy' is deprecated and will be removed in a future version of Angular. The link to ${ - result.toString()} will change to ${ - correctedResult.toString()} if the code is not updated before then.`); - } - } - return result; } diff --git a/packages/router/src/operators/recognize.ts b/packages/router/src/operators/recognize.ts index 54adc35edd6..43927348ef0 100644 --- a/packages/router/src/operators/recognize.ts +++ b/packages/router/src/operators/recognize.ts @@ -17,12 +17,11 @@ import {UrlSerializer} from '../url_tree'; export function recognize( injector: EnvironmentInjector, rootComponentType: Type|null, config: Route[], - serializer: UrlSerializer, paramsInheritanceStrategy: 'emptyOnly'|'always', - relativeLinkResolution: 'legacy'|'corrected'): MonoTypeOperatorFunction { + serializer: UrlSerializer, paramsInheritanceStrategy: 'emptyOnly'|'always'): + MonoTypeOperatorFunction { return mergeMap( t => recognizeFn( injector, rootComponentType, config, t.urlAfterRedirects!, - serializer.serialize(t.urlAfterRedirects!), serializer, paramsInheritanceStrategy, - relativeLinkResolution) + serializer.serialize(t.urlAfterRedirects!), serializer, paramsInheritanceStrategy) .pipe(map(targetSnapshot => ({...t, targetSnapshot})))); } diff --git a/packages/router/src/patchable_relative_link_resolution.ts b/packages/router/src/patchable_relative_link_resolution.ts deleted file mode 100644 index 491c2de355a..00000000000 --- a/packages/router/src/patchable_relative_link_resolution.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -/** - * Exists to aid internal migration off of the deprecated relativeLinkResolution option. - */ -export function assignRelativeLinkResolution( - router: {relativeLinkResolution: 'legacy'|'corrected'}): void {} - -export interface InternalExtraOptions {} diff --git a/packages/router/src/recognize.ts b/packages/router/src/recognize.ts index 57af751fd53..fe921df8dfe 100644 --- a/packages/router/src/recognize.ts +++ b/packages/router/src/recognize.ts @@ -33,11 +33,11 @@ function newObservableError(e: unknown): Observable { export function recognize( injector: EnvironmentInjector, rootComponentType: Type|null, config: Routes, urlTree: UrlTree, url: string, urlSerializer: UrlSerializer, - paramsInheritanceStrategy: ParamsInheritanceStrategy = 'emptyOnly', - relativeLinkResolution: 'legacy'|'corrected' = 'legacy'): Observable { + paramsInheritanceStrategy: ParamsInheritanceStrategy = + 'emptyOnly'): Observable { return new Recognizer( injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, - relativeLinkResolution, urlSerializer) + urlSerializer) .recognize() .pipe(switchMap(result => { if (result === null) { @@ -53,14 +53,11 @@ export class Recognizer { private injector: EnvironmentInjector, private rootComponentType: Type|null, private config: Routes, private urlTree: UrlTree, private url: string, private paramsInheritanceStrategy: ParamsInheritanceStrategy, - private relativeLinkResolution: 'legacy'|'corrected', private readonly urlSerializer: UrlSerializer) {} recognize(): Observable { const rootSegmentGroup = - split( - this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined), - this.relativeLinkResolution) + split(this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined)) .segmentGroup; return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET) @@ -184,12 +181,7 @@ export class Recognizer { const snapshot = new ActivatedRouteSnapshot( segments, params, Object.freeze({...this.urlTree.queryParams}), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, - route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), - // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting - // production bundle size. This value is intended only to surface a warning to users - // depending on `relativeLinkResolution: 'legacy'` in dev mode. - (NG_DEV_MODE ? getCorrectedPathIndexShift(rawSegment) + segments.length : - pathIndexShift)); + route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route)); matchResult = of({ snapshot, consumedSegments: [], @@ -208,10 +200,7 @@ export class Recognizer { consumedSegments, parameters, Object.freeze({...this.urlTree.queryParams}), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, - getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), - (NG_DEV_MODE ? - getCorrectedPathIndexShift(rawSegment) + consumedSegments.length : - pathIndexShift)); + getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route)); return {snapshot, consumedSegments, remainingSegments}; })); } @@ -231,7 +220,7 @@ export class Recognizer { // Filter out routes with redirectTo because we are trying to create activated route // snapshots and don't handle redirects here. That should have been done in // `applyRedirects`. - childConfig.filter(c => c.redirectTo === undefined), this.relativeLinkResolution); + childConfig.filter(c => c.redirectTo === undefined)); if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { return this.processChildren(childInjector, childConfig, segmentGroup).pipe(map(children => { diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 0f832fa5e58..f7f665f4401 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -24,7 +24,6 @@ import {recognize} from './operators/recognize'; import {resolveData} from './operators/resolve_data'; import {switchTap} from './operators/switch_tap'; import {DefaultTitleStrategy, TitleStrategy} from './page_title_strategy'; -import {assignRelativeLinkResolution} from './patchable_relative_link_resolution'; import {DefaultRouteReuseStrategy, RouteReuseStrategy} from './route_reuse_strategy'; import {ErrorHandler, ExtraOptions, ROUTER_CONFIGURATION} from './router_config'; import {RouterConfigLoader, ROUTES} from './router_config_loader'; @@ -346,8 +345,6 @@ export function setupRouter() { assignExtraOptionsToRouter(opts, router); - assignRelativeLinkResolution(router); - return router; } @@ -526,13 +523,6 @@ export class Router { */ urlUpdateStrategy: 'deferred'|'eager' = 'deferred'; - /** - * TODO(atscott): Remove all references to relativeLinkResolution when internal cleanup is - * finished. - * @internal - */ - relativeLinkResolution: 'legacy'|'corrected' = 'corrected'; - /** * Configures how the Router attempts to restore state when a navigation is cancelled. * @@ -693,8 +683,7 @@ export class Router { // Recognize recognize( this.ngModule.injector, this.rootComponentType, this.config, - this.urlSerializer, this.paramsInheritanceStrategy, - this.relativeLinkResolution), + this.urlSerializer, this.paramsInheritanceStrategy), // Update URL if in `eager` update mode tap(t => { diff --git a/packages/router/src/router_config.ts b/packages/router/src/router_config.ts index db8e24c046f..4bd09646d77 100644 --- a/packages/router/src/router_config.ts +++ b/packages/router/src/router_config.ts @@ -8,7 +8,6 @@ import {InjectionToken} from '@angular/core'; -import {InternalExtraOptions} from './patchable_relative_link_resolution'; import {UrlSerializer, UrlTree} from './url_tree'; const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; @@ -171,8 +170,7 @@ export interface InMemoryScrollingOptions { * * @publicApi */ -export interface ExtraOptions extends InMemoryScrollingOptions, RouterConfigOptions, - InternalExtraOptions { +export interface ExtraOptions extends InMemoryScrollingOptions, RouterConfigOptions { /** * When true, log all internal navigation events to the console. * Use for debugging. diff --git a/packages/router/src/router_state.ts b/packages/router/src/router_state.ts index 2efce68fa65..feda957936a 100644 --- a/packages/router/src/router_state.ts +++ b/packages/router/src/router_state.ts @@ -285,13 +285,6 @@ export class ActivatedRouteSnapshot { _urlSegment: UrlSegmentGroup; /** @internal */ _lastPathIndex: number; - /** - * @internal - * - * Used only in dev mode to detect if application relies on `relativeLinkResolution: 'legacy'` - * Should be removed in v16. - */ - _correctedLastPathIndex: number; /** @internal */ _resolve: ResolveData; /** @internal */ @@ -348,11 +341,10 @@ export class ActivatedRouteSnapshot { public outlet: string, /** The component of the route */ public component: Type|null, routeConfig: Route|null, urlSegment: UrlSegmentGroup, - lastPathIndex: number, resolve: ResolveData, correctedLastPathIndex?: number) { + lastPathIndex: number, resolve: ResolveData) { this.routeConfig = routeConfig; this._urlSegment = urlSegment; this._lastPathIndex = lastPathIndex; - this._correctedLastPathIndex = correctedLastPathIndex ?? lastPathIndex; this._resolve = resolve; } diff --git a/packages/router/src/utils/config_matching.ts b/packages/router/src/utils/config_matching.ts index fa55dbcb234..f0d33a74cf6 100644 --- a/packages/router/src/utils/config_matching.ts +++ b/packages/router/src/utils/config_matching.ts @@ -91,7 +91,7 @@ export function match( export function split( segmentGroup: UrlSegmentGroup, consumedSegments: UrlSegment[], slicedSegments: UrlSegment[], - config: Route[], relativeLinkResolution: 'legacy'|'corrected' = 'corrected') { + config: Route[]) { if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) { const s = new UrlSegmentGroup( @@ -109,8 +109,7 @@ export function split( const s = new UrlSegmentGroup( segmentGroup.segments, addEmptyPathsToChildrenIfNeeded( - segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, - relativeLinkResolution)); + segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children)); s._sourceSegment = segmentGroup; s._segmentIndexShift = consumedSegments.length; return {segmentGroup: s, slicedSegments}; @@ -124,21 +123,14 @@ export function split( function addEmptyPathsToChildrenIfNeeded( segmentGroup: UrlSegmentGroup, consumedSegments: UrlSegment[], slicedSegments: UrlSegment[], - routes: Route[], children: {[name: string]: UrlSegmentGroup}, - relativeLinkResolution: 'legacy'|'corrected'): {[name: string]: UrlSegmentGroup} { + routes: Route[], + children: {[name: string]: UrlSegmentGroup}): {[name: string]: UrlSegmentGroup} { const res: {[name: string]: UrlSegmentGroup} = {}; for (const r of routes) { if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) { const s = new UrlSegmentGroup([], {}); s._sourceSegment = segmentGroup; - if (relativeLinkResolution === 'legacy') { - s._segmentIndexShift = segmentGroup.segments.length; - if (typeof ngDevMode === 'undefined' || !!ngDevMode) { - s._segmentIndexShiftCorrected = consumedSegments.length; - } - } else { - s._segmentIndexShift = consumedSegments.length; - } + s._segmentIndexShift = consumedSegments.length; res[getOutlet(r)] = s; } } diff --git a/packages/router/test/recognize.spec.ts b/packages/router/test/recognize.spec.ts index 2dc4015aac2..9ba3485ff03 100644 --- a/packages/router/test/recognize.spec.ts +++ b/packages/router/test/recognize.spec.ts @@ -408,46 +408,43 @@ describe('recognize', async () => { expect((c as any)._lastPathIndex).toBe(0); }); - it('should set url segment and index properly with the "corrected" option for nested empty-path segments', - async () => { - const url = tree('a/b'); - const s = await recognize( - [{ - path: 'a', - children: [{ - path: 'b', - component: ComponentB, - children: [{ - path: '', - component: ComponentC, - children: [{path: '', component: ComponentD}] - }] - }] - }], - 'a/b', 'emptyOnly', 'corrected'); - expect((s.root as any)._urlSegment.toString()).toEqual(url.root.toString()); - expect((s.root as any)._lastPathIndex).toBe(-1); + it('should set url segment and index properly for nested empty-path segments', async () => { + const url = tree('a/b'); + const s = await recognize( + [{ + path: 'a', + children: [{ + path: 'b', + component: ComponentB, + children: [ + {path: '', component: ComponentC, children: [{path: '', component: ComponentD}]} + ] + }] + }], + 'a/b', 'emptyOnly'); + expect((s.root as any)._urlSegment.toString()).toEqual(url.root.toString()); + expect((s.root as any)._lastPathIndex).toBe(-1); - const a = s.root.firstChild!; - expect((a as any)._urlSegment.toString()) - .toEqual(url.root.children[PRIMARY_OUTLET].toString()); - expect((a as any)._lastPathIndex).toBe(0); + const a = s.root.firstChild!; + expect((a as any)._urlSegment.toString()) + .toEqual(url.root.children[PRIMARY_OUTLET].toString()); + expect((a as any)._lastPathIndex).toBe(0); - const b = a.firstChild!; - expect((b as any)._urlSegment.toString()) - .toEqual(url.root.children[PRIMARY_OUTLET].toString()); - expect((b as any)._lastPathIndex).toBe(1); + const b = a.firstChild!; + expect((b as any)._urlSegment.toString()) + .toEqual(url.root.children[PRIMARY_OUTLET].toString()); + expect((b as any)._lastPathIndex).toBe(1); - const c = b.firstChild!; - expect((c as any)._urlSegment.toString()) - .toEqual(url.root.children[PRIMARY_OUTLET].toString()); - expect((c as any)._lastPathIndex).toBe(1); + const c = b.firstChild!; + expect((c as any)._urlSegment.toString()) + .toEqual(url.root.children[PRIMARY_OUTLET].toString()); + expect((c as any)._lastPathIndex).toBe(1); - const d = c.firstChild!; - expect((d as any)._urlSegment.toString()) - .toEqual(url.root.children[PRIMARY_OUTLET].toString()); - expect((d as any)._lastPathIndex).toBe(1); - }); + const d = c.firstChild!; + expect((d as any)._urlSegment.toString()) + .toEqual(url.root.children[PRIMARY_OUTLET].toString()); + expect((d as any)._lastPathIndex).toBe(1); + }); it('should set url segment and index properly when nested empty-path segments (2)', async () => { @@ -658,7 +655,7 @@ describe('recognize', async () => { children: [{path: 'b', component: ComponentB}], }, ], - tree('/b'), '/b', 'emptyOnly', 'corrected', new DefaultUrlSerializer()) + tree('/b'), '/b', 'emptyOnly', new DefaultUrlSerializer()) .recognize() .toPromise(); expect(s).toBeNull(); @@ -830,12 +827,12 @@ describe('recognize', async () => { }); async function recognize( - config: Routes, url: string, paramsInheritanceStrategy: 'emptyOnly'|'always' = 'emptyOnly', - relativeLinkResolution: 'legacy'|'corrected' = 'legacy'): Promise { + config: Routes, url: string, + paramsInheritanceStrategy: 'emptyOnly'|'always' = 'emptyOnly'): Promise { const serializer = new DefaultUrlSerializer(); const result = await new Recognizer( TestBed.inject(EnvironmentInjector), RootComponent, config, tree(url), url, - paramsInheritanceStrategy, relativeLinkResolution, serializer) + paramsInheritanceStrategy, serializer) .recognize() .toPromise(); expect(result).not.toBeNull();