fix(router): freeze params and queryParams to prevent common source of bugs

This commit is contained in:
vsavkin 2016-07-14 13:33:05 -07:00
parent 44ff005ce3
commit 0668ba50e8
2 changed files with 18 additions and 4 deletions

View File

@ -44,10 +44,10 @@ export function recognize(rootComponentType: Type, config: Routes, urlTree: UrlT
const children = const children =
processSegment(config, urlTree.root, InheritedFromParent.empty(null), PRIMARY_OUTLET); processSegment(config, urlTree.root, InheritedFromParent.empty(null), PRIMARY_OUTLET);
const root = new ActivatedRouteSnapshot( const root = new ActivatedRouteSnapshot(
[], {}, {}, PRIMARY_OUTLET, rootComponentType, null, urlTree.root, -1, [], Object.freeze({}), {}, PRIMARY_OUTLET, rootComponentType, null, urlTree.root, -1,
InheritedResolve.empty); InheritedResolve.empty);
const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children); const rootNode = new TreeNode<ActivatedRouteSnapshot>(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) { } catch (e) {
if (e instanceof NoMatch) { if (e instanceof NoMatch) {
return new Observable<RouterStateSnapshot>( return new Observable<RouterStateSnapshot>(
@ -113,7 +113,7 @@ function processPathsWithParamsAgainstRoute(
if (route.path === '**') { if (route.path === '**') {
const params = paths.length > 0 ? last(paths).parameters : {}; const params = paths.length > 0 ? last(paths).parameters : {};
const snapshot = new ActivatedRouteSnapshot( 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, route.component, route, getSourceSegment(rawSegment), getPathIndexShift(rawSegment) - 1,
newInheritedResolve); newInheritedResolve);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])]; return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
@ -127,7 +127,7 @@ function processPathsWithParamsAgainstRoute(
const {segment, slicedPath} = split(rawSegment, consumedPaths, rawSlicedPath, childConfig); const {segment, slicedPath} = split(rawSegment, consumedPaths, rawSlicedPath, childConfig);
const snapshot = new ActivatedRouteSnapshot( 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, merge(inherited.allData, getData(route)), outlet, route.component, route,
getSourceSegment(rawSegment), getPathIndexShift(rawSegment) + pathIndex + lastChild - 1, getSourceSegment(rawSegment), getPathIndexShift(rawSegment) + pathIndex + lastChild - 1,
newInheritedResolve); newInheritedResolve);

View File

@ -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', () => { it('should support secondary routes', () => {
checkRecognize( checkRecognize(
[ [
@ -504,6 +512,12 @@ describe('recognize', () => {
expect(s.queryParams).toEqual({q: '11'}); 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', () => { describe('fragment', () => {