From 0668ba50e89656f2126a7aa9baf20aa2484448f4 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Thu, 14 Jul 2016 13:33:05 -0700 Subject: [PATCH] fix(router): freeze params and queryParams to prevent common source of bugs --- modules/@angular/router/src/recognize.ts | 8 ++++---- modules/@angular/router/test/recognize.spec.ts | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/@angular/router/src/recognize.ts b/modules/@angular/router/src/recognize.ts index 4856fd12d9..824138f424 100644 --- a/modules/@angular/router/src/recognize.ts +++ b/modules/@angular/router/src/recognize.ts @@ -44,10 +44,10 @@ export function recognize(rootComponentType: Type, config: Routes, urlTree: UrlT const children = processSegment(config, urlTree.root, InheritedFromParent.empty(null), PRIMARY_OUTLET); const root = new ActivatedRouteSnapshot( - [], {}, {}, PRIMARY_OUTLET, rootComponentType, null, urlTree.root, -1, + [], Object.freeze({}), {}, PRIMARY_OUTLET, rootComponentType, null, urlTree.root, -1, InheritedResolve.empty); const rootNode = new TreeNode(root, children); - return of (new RouterStateSnapshot(url, rootNode, urlTree.queryParams, urlTree.fragment)); + return of (new RouterStateSnapshot(url, rootNode, Object.freeze(urlTree.queryParams), urlTree.fragment)); } catch (e) { if (e instanceof NoMatch) { return new Observable( @@ -113,7 +113,7 @@ function processPathsWithParamsAgainstRoute( if (route.path === '**') { const params = paths.length > 0 ? last(paths).parameters : {}; const snapshot = new ActivatedRouteSnapshot( - paths, merge(inherited.allParams, params), merge(inherited.allData, getData(route)), outlet, + paths, Object.freeze(merge(inherited.allParams, params)), merge(inherited.allData, getData(route)), outlet, route.component, route, getSourceSegment(rawSegment), getPathIndexShift(rawSegment) - 1, newInheritedResolve); return [new TreeNode(snapshot, [])]; @@ -127,7 +127,7 @@ function processPathsWithParamsAgainstRoute( const {segment, slicedPath} = split(rawSegment, consumedPaths, rawSlicedPath, childConfig); const snapshot = new ActivatedRouteSnapshot( - consumedPaths, merge(inherited.allParams, parameters), + consumedPaths, Object.freeze(merge(inherited.allParams, parameters)), merge(inherited.allData, getData(route)), outlet, route.component, route, getSourceSegment(rawSegment), getPathIndexShift(rawSegment) + pathIndex + lastChild - 1, newInheritedResolve); diff --git a/modules/@angular/router/test/recognize.spec.ts b/modules/@angular/router/test/recognize.spec.ts index d3df9332a6..b08e27734f 100644 --- a/modules/@angular/router/test/recognize.spec.ts +++ b/modules/@angular/router/test/recognize.spec.ts @@ -12,6 +12,14 @@ describe('recognize', () => { }); }); + it('should freeze params object', () => { + checkRecognize([{path: 'a/:id', component: ComponentA}], 'a/10', (s: RouterStateSnapshot) => { + checkActivatedRoute(s.root, '', {}, RootComponent); + const child = s.firstChild(s.root); + expect(() => child.params['prop'] = "new").toThrowError(/Can't add property/); + }); + }); + it('should support secondary routes', () => { checkRecognize( [ @@ -504,6 +512,12 @@ describe('recognize', () => { expect(s.queryParams).toEqual({q: '11'}); }); }); + + it('should freeze query params object', () => { + checkRecognize([{path: 'a', component: ComponentA}], 'a?q=11', (s: RouterStateSnapshot) => { + expect(() => s.queryParams['prop'] = "new").toThrowError(/Can't add property/); + }); + }); }); describe('fragment', () => {