diff --git a/packages/router/src/url_tree.ts b/packages/router/src/url_tree.ts index 1f73b4d0be7..751bf6f2426 100644 --- a/packages/router/src/url_tree.ts +++ b/packages/router/src/url_tree.ts @@ -794,7 +794,10 @@ export function squashSegmentGroup(segmentGroup: UrlSegmentGroup): UrlSegmentGro newChildren[childOutlet] = childCandidate; } } - const s = new UrlSegmentGroup(segmentGroup.segments, newChildren); + const s = new UrlSegmentGroup( + segmentGroup.segments.map((s) => new UrlSegment(s.path, {...s.parameters})), + newChildren, + ); return mergeTrivialChildren(s); } diff --git a/packages/router/test/create_url_tree.spec.ts b/packages/router/test/create_url_tree.spec.ts index e50d1693d9f..665e0f98344 100644 --- a/packages/router/test/create_url_tree.spec.ts +++ b/packages/router/test/create_url_tree.spec.ts @@ -758,6 +758,24 @@ describe('createUrlTreeFromSnapshot', () => { await advance(fixture); expect(router.url).toEqual('/parent/sibling'); }); + it('should not affect the input snapshot when the result is mutated', async () => { + TestBed.configureTestingModule({ + providers: [provideRouter([{path: 'a', children: [{path: 'b', component: class {}}]}])], + }); + const router = TestBed.inject(Router); + await router.navigateByUrl('/a/b'); + const snapshot = router.routerState.snapshot.root.firstChild!; + + // createUrlTreeFromSnapshot will squash the segment group + const tree = createUrlTreeFromSnapshot(snapshot, []); + + // Mutate the result's segments array (e.g. simulating what applyRedirects might do) + tree.root.children[PRIMARY_OUTLET].segments[0].path = 'c'; + + // The input snapshot should remain unchanged + expect(snapshot.url.length).toBe(1); + expect(snapshot.url[0].path).toBe('a'); + }); }); async function advance(fixture: ComponentFixture) {