Permalink
Browse files

fix(router): avoid freezing queryParams in-place (#22663)

The recognizer code used to call Object.freeze() on queryParams before
using them to construct ActivatedRoutes, with the intent being to help
avoid common invalid usage. Unfortunately, Object.freeze() works
in-place, so this was also freezing the queryParams on the actual
UrlTree object, making it more difficult to manipulate UrlTrees in
things like UrlHandlingStrategy.

This change simply shallow-copies the queryParams before freezing them.

Fixes #22617

PR Close #22663
  • Loading branch information...
voithos authored and IgorMinar committed Mar 8, 2018
1 parent 8733843 commit 3d8799b3a21d23bbeede337bc545b5f483d2232d
Showing with 13 additions and 4 deletions.
  1. +5 −4 packages/router/src/recognize.ts
  2. +8 −0 packages/router/test/recognize.spec.ts
@@ -38,8 +38,9 @@ class Recognizer {
const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
const root = new ActivatedRouteSnapshot(
[], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !,
{}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
[], Object.freeze({}), Object.freeze({...this.urlTree.queryParams}),
this.urlTree.fragment !, {}, PRIMARY_OUTLET, this.rootComponentType, null,
this.urlTree.root, -1, {});
const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children);
const routeState = new RouterStateSnapshot(this.url, rootNode);
@@ -116,7 +117,7 @@ class Recognizer {
if (route.path === '**') {
const params = segments.length > 0 ? last(segments) !.parameters : {};
snapshot = new ActivatedRouteSnapshot(
segments, params, Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !,
segments, params, Object.freeze({...this.urlTree.queryParams}), this.urlTree.fragment !,
getData(route), outlet, route.component !, route, getSourceSegmentGroup(rawSegment),
getPathIndexShift(rawSegment) + segments.length, getResolve(route));
} else {
@@ -125,7 +126,7 @@ class Recognizer {
rawSlicedSegments = segments.slice(result.lastChild);
snapshot = new ActivatedRouteSnapshot(
consumedSegments, result.parameters, Object.freeze(this.urlTree.queryParams),
consumedSegments, result.parameters, Object.freeze({...this.urlTree.queryParams}),
this.urlTree.fragment !, getData(route), outlet, route.component !, route,
getSourceSegmentGroup(rawSegment),
getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
@@ -748,6 +748,14 @@ describe('recognize', () => {
expect(Object.isFrozen(s.root.queryParams)).toBeTruthy();
});
});
it('should not freeze UrlTree query params', () => {
const url = tree('a?q=11');
recognize(RootComponent, [{path: 'a', component: ComponentA}], url, 'a?q=11')
.subscribe((s: RouterStateSnapshot) => {
expect(Object.isFrozen(url.queryParams)).toBe(false);
});
});
});
describe('fragment', () => {

0 comments on commit 3d8799b

Please sign in to comment.