refactor(router): misc refactoring (#13330)
This commit is contained in:
		
							parent
							
								
									56c361ff6a
								
							
						
					
					
						commit
						b5c4bf1c59
					
				| @ -9,8 +9,6 @@ | ||||
| import {Injector, THROW_IF_NOT_FOUND} from '../di/injector'; | ||||
| import {AppView} from './view'; | ||||
| 
 | ||||
| const _UNDEFINED = new Object(); | ||||
| 
 | ||||
| export class ElementInjector extends Injector { | ||||
|   constructor(private _view: AppView<any>, private _nodeIndex: number) { super(); } | ||||
| 
 | ||||
|  | ||||
| @ -9,7 +9,6 @@ | ||||
| import {ApplicationRef} from '../application_ref'; | ||||
| import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/change_detection'; | ||||
| import {Injector, THROW_IF_NOT_FOUND} from '../di/injector'; | ||||
| import {ListWrapper} from '../facade/collection'; | ||||
| import {isPresent} from '../facade/lang'; | ||||
| import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile'; | ||||
| import {DirectRenderer, RenderComponentType, RenderDebugInfo, Renderer} from '../render/api'; | ||||
|  | ||||
| @ -18,7 +18,7 @@ import {map} from 'rxjs/operator/map'; | ||||
| import {mergeMap} from 'rxjs/operator/mergeMap'; | ||||
| import {EmptyError} from 'rxjs/util/EmptyError'; | ||||
| 
 | ||||
| import {Route, Routes, UrlMatchResult} from './config'; | ||||
| import {Route, Routes} from './config'; | ||||
| import {LoadedRouterConfig, RouterConfigLoader} from './router_config_loader'; | ||||
| import {NavigationCancelingError, PRIMARY_OUTLET, Params, defaultUrlMatcher} from './shared'; | ||||
| import {UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree} from './url_tree'; | ||||
| @ -54,7 +54,6 @@ function canLoadFails(route: Route): Observable<LoadedRouterConfig> { | ||||
|           `Cannot load children because the guard of the route "path: '${route.path}'" returned false`))); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export function applyRedirects( | ||||
|     injector: Injector, configLoader: RouterConfigLoader, urlSerializer: UrlSerializer, | ||||
|     urlTree: UrlTree, config: Routes): Observable<UrlTree> { | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| import {ActivatedRoute} from './router_state'; | ||||
| import {PRIMARY_OUTLET, Params} from './shared'; | ||||
| import {UrlSegment, UrlSegmentGroup, UrlTree} from './url_tree'; | ||||
| import {forEach, shallowEqual} from './utils/collection'; | ||||
| import {forEach, shallowEqual, last} from './utils/collection'; | ||||
| 
 | ||||
| export function createUrlTree( | ||||
|     route: ActivatedRoute, urlTree: UrlTree, commands: any[], queryParams: Params, | ||||
| @ -18,36 +18,24 @@ export function createUrlTree( | ||||
|     return tree(urlTree.root, urlTree.root, urlTree, queryParams, fragment); | ||||
|   } | ||||
| 
 | ||||
|   const normalizedCommands = normalizeCommands(commands); | ||||
|   validateCommands(normalizedCommands); | ||||
|   const nav = computeNavigation(commands); | ||||
| 
 | ||||
|   if (navigateToRoot(normalizedCommands)) { | ||||
|   if (nav.toRoot()) { | ||||
|     return tree(urlTree.root, new UrlSegmentGroup([], {}), urlTree, queryParams, fragment); | ||||
|   } | ||||
| 
 | ||||
|   const startingPosition = findStartingPosition(normalizedCommands, urlTree, route); | ||||
|   const startingPosition = findStartingPosition(nav, urlTree, route); | ||||
| 
 | ||||
|   const segmentGroup = startingPosition.processChildren ? | ||||
|       updateSegmentGroupChildren( | ||||
|           startingPosition.segmentGroup, startingPosition.index, normalizedCommands.commands) : | ||||
|           startingPosition.segmentGroup, startingPosition.index, nav.commands) : | ||||
|       updateSegmentGroup( | ||||
|           startingPosition.segmentGroup, startingPosition.index, normalizedCommands.commands); | ||||
|           startingPosition.segmentGroup, startingPosition.index, nav.commands); | ||||
|   return tree(startingPosition.segmentGroup, segmentGroup, urlTree, queryParams, fragment); | ||||
| } | ||||
| 
 | ||||
| function validateCommands(n: NormalizedNavigationCommands): void { | ||||
|   if (n.isAbsolute && n.commands.length > 0 && isMatrixParams(n.commands[0])) { | ||||
|     throw new Error('Root segment cannot have matrix parameters'); | ||||
|   } | ||||
| 
 | ||||
|   const c = n.commands.filter(c => typeof c === 'object' && c.outlets !== undefined); | ||||
|   if (c.length > 0 && c[0] !== n.commands[n.commands.length - 1]) { | ||||
|     throw new Error('{outlets:{}} has to be the last command'); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function isMatrixParams(command: any): boolean { | ||||
|   return typeof command === 'object' && command.outlets === undefined && | ||||
|       command.segmentPath === undefined; | ||||
|   return typeof command === 'object' && !command.outlets && !command.segmentPath; | ||||
| } | ||||
| 
 | ||||
| function tree( | ||||
| @ -55,11 +43,11 @@ function tree( | ||||
|     queryParams: Params, fragment: string): UrlTree { | ||||
|   if (urlTree.root === oldSegmentGroup) { | ||||
|     return new UrlTree(newSegmentGroup, stringify(queryParams), fragment); | ||||
|   } else { | ||||
|     return new UrlTree( | ||||
|         replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), stringify(queryParams), | ||||
|         fragment); | ||||
|   } | ||||
| 
 | ||||
|   return new UrlTree( | ||||
|       replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), stringify(queryParams), | ||||
|       fragment); | ||||
| } | ||||
| 
 | ||||
| function replaceSegment( | ||||
| @ -76,72 +64,71 @@ function replaceSegment( | ||||
|   return new UrlSegmentGroup(current.segments, children); | ||||
| } | ||||
| 
 | ||||
| function navigateToRoot(normalizedChange: NormalizedNavigationCommands): boolean { | ||||
|   return normalizedChange.isAbsolute && normalizedChange.commands.length === 1 && | ||||
|       normalizedChange.commands[0] == '/'; | ||||
| class Navigation { | ||||
|   constructor(public isAbsolute: boolean, public numberOfDoubleDots: number, public commands: any[]) { | ||||
|     if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) { | ||||
|       throw new Error('Root segment cannot have matrix parameters'); | ||||
|     } | ||||
| 
 | ||||
|     const cmdWithOutlet = commands.find(c => typeof c === 'object' && c.outlets); | ||||
|     if (cmdWithOutlet && cmdWithOutlet !== last(commands)) { | ||||
|       throw new Error('{outlets:{}} has to be the last command'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public toRoot(): boolean { | ||||
|     return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/'; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class NormalizedNavigationCommands { | ||||
|   constructor( | ||||
|       public isAbsolute: boolean, public numberOfDoubleDots: number, public commands: any[]) {} | ||||
| } | ||||
| 
 | ||||
| function normalizeCommands(commands: any[]): NormalizedNavigationCommands { | ||||
|   if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] == '/') { | ||||
|     return new NormalizedNavigationCommands(true, 0, commands); | ||||
| /** Transforms commands to a normalized `Navigation` */ | ||||
| function computeNavigation(commands: any[]): Navigation { | ||||
|   if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') { | ||||
|     return new Navigation(true, 0, commands); | ||||
|   } | ||||
| 
 | ||||
|   let numberOfDoubleDots = 0; | ||||
|   let isAbsolute = false; | ||||
|   const res: any[] = []; | ||||
| 
 | ||||
|   for (let i = 0; i < commands.length; ++i) { | ||||
|     const c = commands[i]; | ||||
|   const res: any[] = commands.reduce((res, cmd, cmdIdx) => { | ||||
|     if (typeof cmd === 'object') { | ||||
|       if (cmd.outlets) { | ||||
|         const outlets: {[k: string]: any} = {}; | ||||
|         forEach(cmd.outlets, (commands: any, name: string) => { | ||||
|           outlets[name] = typeof commands === 'string' ? commands.split('/') : commands; | ||||
|         }); | ||||
|         return [...res, {outlets}]; | ||||
|       } | ||||
| 
 | ||||
|     if (typeof c === 'object' && c.outlets !== undefined) { | ||||
|       const r: {[k: string]: any} = {}; | ||||
|       forEach(c.outlets, (commands: any, name: string) => { | ||||
|         if (typeof commands === 'string') { | ||||
|           r[name] = commands.split('/'); | ||||
|         } else { | ||||
|           r[name] = commands; | ||||
|       if (cmd.segmentPath) { | ||||
|         return [...res, cmd.segmentPath]; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!(typeof cmd === 'string')) { | ||||
|       return [...res, cmd]; | ||||
|     } | ||||
| 
 | ||||
|     if (cmdIdx === 0) { | ||||
|       cmd.split('/').forEach((urlPart, partIndex) => { | ||||
|         if (partIndex == 0 && urlPart === '.') { | ||||
|           // skip './a'
 | ||||
|         } else if (partIndex == 0 && urlPart === '') {  //  '/a'
 | ||||
|           isAbsolute = true; | ||||
|         } else if (urlPart === '..') {  //  '../a'
 | ||||
|           numberOfDoubleDots++; | ||||
|         } else if (urlPart != '') { | ||||
|           res.push(urlPart); | ||||
|         } | ||||
|       }); | ||||
|       res.push({outlets: r}); | ||||
|       continue; | ||||
| 
 | ||||
|       return res; | ||||
|     } | ||||
| 
 | ||||
|     if (typeof c === 'object' && c.segmentPath !== undefined) { | ||||
|       res.push(c.segmentPath); | ||||
|       continue; | ||||
|     } | ||||
|     return [...res, cmd]; | ||||
|   }, []); | ||||
| 
 | ||||
|     if (!(typeof c === 'string')) { | ||||
|       res.push(c); | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     if (i === 0) { | ||||
|       const parts = c.split('/'); | ||||
|       for (let j = 0; j < parts.length; ++j) { | ||||
|         const cc = parts[j]; | ||||
| 
 | ||||
|         if (j == 0 && cc == '.') {  //  './a'
 | ||||
|           // skip it
 | ||||
|         } else if (j == 0 && cc == '') {  //  '/a'
 | ||||
|           isAbsolute = true; | ||||
|         } else if (cc == '..') {  //  '../a'
 | ||||
|           numberOfDoubleDots++; | ||||
|         } else if (cc != '') { | ||||
|           res.push(cc); | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       res.push(c); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return new NormalizedNavigationCommands(isAbsolute, numberOfDoubleDots, res); | ||||
|   return new Navigation(isAbsolute, numberOfDoubleDots, res); | ||||
| } | ||||
| 
 | ||||
| class Position { | ||||
| @ -150,19 +137,19 @@ class Position { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function findStartingPosition( | ||||
|     normalizedChange: NormalizedNavigationCommands, urlTree: UrlTree, | ||||
|     route: ActivatedRoute): Position { | ||||
|   if (normalizedChange.isAbsolute) { | ||||
|     return new Position(urlTree.root, true, 0); | ||||
|   } else if (route.snapshot._lastPathIndex === -1) { | ||||
|     return new Position(route.snapshot._urlSegment, true, 0); | ||||
|   } else { | ||||
|     const modifier = isMatrixParams(normalizedChange.commands[0]) ? 0 : 1; | ||||
|     const index = route.snapshot._lastPathIndex + modifier; | ||||
|     return createPositionApplyingDoubleDots( | ||||
|         route.snapshot._urlSegment, index, normalizedChange.numberOfDoubleDots); | ||||
| function findStartingPosition(nav: Navigation, tree: UrlTree, route: ActivatedRoute): Position { | ||||
|   if (nav.isAbsolute) { | ||||
|     return new Position(tree.root, true, 0); | ||||
|   } | ||||
| 
 | ||||
|   if (route.snapshot._lastPathIndex === -1) { | ||||
|     return new Position(route.snapshot._urlSegment, true, 0); | ||||
|   } | ||||
| 
 | ||||
|   const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1; | ||||
|   const index = route.snapshot._lastPathIndex + modifier; | ||||
|   return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| function createPositionApplyingDoubleDots( | ||||
| @ -276,7 +263,7 @@ function createNewSegmentGroup( | ||||
|   let i = 0; | ||||
|   while (i < commands.length) { | ||||
|     if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) { | ||||
|       const children = createNewSegmentChldren(commands[i].outlets); | ||||
|       const children = createNewSegmentChildren(commands[i].outlets); | ||||
|       return new UrlSegmentGroup(paths, children); | ||||
|     } | ||||
| 
 | ||||
| @ -301,7 +288,7 @@ function createNewSegmentGroup( | ||||
|   return new UrlSegmentGroup(paths, {}); | ||||
| } | ||||
| 
 | ||||
| function createNewSegmentChldren(outlets: {[name: string]: any}): any { | ||||
| function createNewSegmentChildren(outlets: {[name: string]: any}): any { | ||||
|   const children: {[key: string]: UrlSegmentGroup} = {}; | ||||
|   forEach(outlets, (commands: any, outlet: string) => { | ||||
|     if (commands !== null) { | ||||
|  | ||||
| @ -12,9 +12,12 @@ import {ROUTES} from './router_config_loader'; | ||||
| import {ROUTER_PROVIDERS} from './router_module'; | ||||
| import {flatten} from './utils/collection'; | ||||
| 
 | ||||
| export var __router_private__: | ||||
|     {ROUTER_PROVIDERS: typeof ROUTER_PROVIDERS; ROUTES: typeof ROUTES; flatten: typeof flatten;} = { | ||||
|       ROUTER_PROVIDERS: ROUTER_PROVIDERS, | ||||
|       ROUTES: ROUTES, | ||||
|       flatten: flatten | ||||
|     }; | ||||
| export const __router_private__: { | ||||
|   ROUTER_PROVIDERS: typeof ROUTER_PROVIDERS, | ||||
|   ROUTES: typeof ROUTES, | ||||
|   flatten: typeof flatten, | ||||
| } = { | ||||
|   ROUTER_PROVIDERS: ROUTER_PROVIDERS, | ||||
|   ROUTES: ROUTES, | ||||
|   flatten: flatten, | ||||
| }; | ||||
|  | ||||
| @ -7,4 +7,4 @@ | ||||
|  */ | ||||
| import {__platform_browser_private__ as r} from '@angular/platform-browser'; | ||||
| 
 | ||||
| export var getDOM: typeof r.getDOM = r.getDOM; | ||||
| export const getDOM: typeof r.getDOM = r.getDOM; | ||||
|  | ||||
| @ -11,9 +11,9 @@ import {Observable} from 'rxjs/Observable'; | ||||
| import {Observer} from 'rxjs/Observer'; | ||||
| import {of } from 'rxjs/observable/of'; | ||||
| 
 | ||||
| import {Data, ResolveData, Route, Routes, UrlMatchResult} from './config'; | ||||
| import {Data, ResolveData, Route, Routes} from './config'; | ||||
| import {ActivatedRouteSnapshot, RouterStateSnapshot, inheritedParamsDataResolve} from './router_state'; | ||||
| import {PRIMARY_OUTLET, Params, defaultUrlMatcher} from './shared'; | ||||
| import {PRIMARY_OUTLET, defaultUrlMatcher} from './shared'; | ||||
| import {UrlSegment, UrlSegmentGroup, UrlTree, mapChildrenIntoArray} from './url_tree'; | ||||
| import {forEach, last, merge} from './utils/collection'; | ||||
| import {TreeNode} from './utils/tree'; | ||||
|  | ||||
| @ -11,7 +11,6 @@ import {ComponentRef} from '@angular/core'; | ||||
| import {ActivatedRoute, ActivatedRouteSnapshot} from './router_state'; | ||||
| import {TreeNode} from './utils/tree'; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * @whatItDoes Represents the detached route tree. | ||||
|  * | ||||
| @ -22,43 +21,30 @@ import {TreeNode} from './utils/tree'; | ||||
|  */ | ||||
| export type DetachedRouteHandle = {}; | ||||
| 
 | ||||
| /** | ||||
|  * @internal | ||||
|  */ | ||||
| /** @internal */ | ||||
| export type DetachedRouteHandleInternal = { | ||||
|   componentRef: ComponentRef<any>, | ||||
|   route: TreeNode<ActivatedRoute> | ||||
|   route: TreeNode<ActivatedRoute>, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * @whatItDoes Provides a way to customize when activated routes get reused. | ||||
|  * | ||||
|  * @experimental | ||||
|  */ | ||||
| export abstract class RouteReuseStrategy { | ||||
|   /** | ||||
|    * Determines if this route (and its subtree) should be detached to be reused later. | ||||
|    */ | ||||
|   /** Determines if this route (and its subtree) should be detached to be reused later */ | ||||
|   abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; | ||||
| 
 | ||||
|   /** | ||||
|    * Stores the detached route. | ||||
|    */ | ||||
|   /** Stores the detached route */ | ||||
|   abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void; | ||||
| 
 | ||||
|   /** | ||||
|    * Determines if this route (and its subtree) should be reattached. | ||||
|    */ | ||||
|   /** Determines if this route (and its subtree) should be reattached */ | ||||
|   abstract shouldAttach(route: ActivatedRouteSnapshot): boolean; | ||||
| 
 | ||||
|   /** | ||||
|    * Retrieves the previously stored route. | ||||
|    */ | ||||
|   /** Retrieves the previously stored route */ | ||||
|   abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle; | ||||
| 
 | ||||
|   /** | ||||
|    * Determines if a route should be reused. | ||||
|    */ | ||||
|   /** Determines if a route should be reused */ | ||||
|   abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; | ||||
| } | ||||
| @ -13,7 +13,6 @@ import {Observable} from 'rxjs/Observable'; | ||||
| import {Subject} from 'rxjs/Subject'; | ||||
| import {Subscription} from 'rxjs/Subscription'; | ||||
| import {from} from 'rxjs/observable/from'; | ||||
| import {fromPromise} from 'rxjs/observable/fromPromise'; | ||||
| import {of } from 'rxjs/observable/of'; | ||||
| import {concatMap} from 'rxjs/operator/concatMap'; | ||||
| import {every} from 'rxjs/operator/every'; | ||||
| @ -148,7 +147,6 @@ export class NavigationStart { | ||||
|   constructor( | ||||
|       /** @docsNotRequired */ | ||||
|       public id: number, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public url: string) {} | ||||
| 
 | ||||
| @ -166,10 +164,8 @@ export class NavigationEnd { | ||||
|   constructor( | ||||
|       /** @docsNotRequired */ | ||||
|       public id: number, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public url: string, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public urlAfterRedirects: string) {} | ||||
| 
 | ||||
| @ -189,10 +185,8 @@ export class NavigationCancel { | ||||
|   constructor( | ||||
|       /** @docsNotRequired */ | ||||
|       public id: number, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public url: string, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public reason: string) {} | ||||
| 
 | ||||
| @ -210,10 +204,8 @@ export class NavigationError { | ||||
|   constructor( | ||||
|       /** @docsNotRequired */ | ||||
|       public id: number, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public url: string, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public error: any) {} | ||||
| 
 | ||||
| @ -233,7 +225,6 @@ export class RoutesRecognized { | ||||
|   constructor( | ||||
|       /** @docsNotRequired */ | ||||
|       public id: number, | ||||
| 
 | ||||
|       /** @docsNotRequired */ | ||||
|       public url: string, | ||||
|       /** @docsNotRequired */ | ||||
| @ -282,7 +273,7 @@ type NavigationParams = { | ||||
|   resolve: any, | ||||
|   reject: any, | ||||
|   promise: Promise<boolean>, | ||||
|   imperative: boolean | ||||
|   imperative: boolean, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| @ -312,9 +303,8 @@ export class Router { | ||||
|   private currentUrlTree: UrlTree; | ||||
|   private rawUrlTree: UrlTree; | ||||
| 
 | ||||
|   private navigations: BehaviorSubject<NavigationParams> = | ||||
|       new BehaviorSubject<NavigationParams>(null); | ||||
|   private routerEvents: Subject<Event> = new Subject<Event>(); | ||||
|   private navigations = new BehaviorSubject<NavigationParams>(null); | ||||
|   private routerEvents = new Subject<Event>(); | ||||
| 
 | ||||
|   private currentRouterState: RouterState; | ||||
|   private locationSubscription: Subscription; | ||||
| @ -353,7 +343,6 @@ export class Router { | ||||
|     this.rawUrlTree = this.currentUrlTree; | ||||
|     this.configLoader = new RouterConfigLoader(loader, compiler); | ||||
|     this.currentRouterState = createEmptyState(this.currentUrlTree, this.rootComponentType); | ||||
| 
 | ||||
|     this.processNavigations(); | ||||
|   } | ||||
| 
 | ||||
| @ -403,19 +392,13 @@ export class Router { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns the current route state. | ||||
|    */ | ||||
|   /** The current route state */ | ||||
|   get routerState(): RouterState { return this.currentRouterState; } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns the current url. | ||||
|    */ | ||||
|   /** The current url */ | ||||
|   get url(): string { return this.serializeUrl(this.currentUrlTree); } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns an observable of route events | ||||
|    */ | ||||
|   /** An observable of router events */ | ||||
|   get events(): Observable<Event> { return this.routerEvents; } | ||||
| 
 | ||||
|   /** | ||||
| @ -428,7 +411,7 @@ export class Router { | ||||
|    *  { path: 'team/:id', component: TeamCmp, children: [ | ||||
|    *    { path: 'simple', component: SimpleCmp }, | ||||
|    *    { path: 'user/:name', component: UserCmp } | ||||
|    *  ] } | ||||
|    *  ]} | ||||
|    * ]); | ||||
|    * ``` | ||||
|    */ | ||||
| @ -437,14 +420,10 @@ export class Router { | ||||
|     this.config = config; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   /** @docsNotRequired */ | ||||
|   ngOnDestroy() { this.dispose(); } | ||||
| 
 | ||||
|   /** | ||||
|    * Disposes of the router. | ||||
|    */ | ||||
|   /** Disposes of the router */ | ||||
|   dispose(): void { | ||||
|     if (this.locationSubscription) { | ||||
|       this.locationSubscription.unsubscribe(); | ||||
| @ -496,7 +475,7 @@ export class Router { | ||||
|   createUrlTree( | ||||
|       commands: any[], {relativeTo, queryParams, fragment, preserveQueryParams, | ||||
|                         preserveFragment}: NavigationExtras = {}): UrlTree { | ||||
|     const a = relativeTo ? relativeTo : this.routerState.root; | ||||
|     const a = relativeTo || this.routerState.root; | ||||
|     const q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams; | ||||
|     const f = preserveFragment ? this.currentUrlTree.fragment : fragment; | ||||
|     return createUrlTree(a, this.currentUrlTree, commands, q, f); | ||||
| @ -506,9 +485,9 @@ export class Router { | ||||
|    * Navigate based on the provided url. This navigation is always absolute. | ||||
|    * | ||||
|    * Returns a promise that: | ||||
|    * - is resolved with 'true' when navigation succeeds | ||||
|    * - is resolved with 'false' when navigation fails | ||||
|    * - is rejected when an error happens | ||||
|    * - resolves to 'true' when navigation succeeds, | ||||
|    * - resolves to 'false' when navigation fails, | ||||
|    * - is rejected when an error happens. | ||||
|    * | ||||
|    * ### Usage | ||||
|    * | ||||
| @ -527,11 +506,11 @@ export class Router { | ||||
|     if (url instanceof UrlTree) { | ||||
|       return this.scheduleNavigation( | ||||
|           this.urlHandlingStrategy.merge(url, this.rawUrlTree), true, extras); | ||||
|     } else { | ||||
|       const urlTree = this.urlSerializer.parse(url); | ||||
|       return this.scheduleNavigation( | ||||
|           this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree), true, extras); | ||||
|     } | ||||
| 
 | ||||
|     const urlTree = this.urlSerializer.parse(url); | ||||
|     return this.scheduleNavigation( | ||||
|         this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree), true, extras); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
| @ -539,9 +518,9 @@ export class Router { | ||||
|    * If no starting route is provided, the navigation is absolute. | ||||
|    * | ||||
|    * Returns a promise that: | ||||
|    * - is resolved with 'true' when navigation succeeds | ||||
|    * - is resolved with 'false' when navigation fails | ||||
|    * - is rejected when an error happens | ||||
|    * - resolves to 'true' when navigation succeeds, | ||||
|    * - resolves to 'false' when navigation fails, | ||||
|    * - is rejected when an error happens. | ||||
|    * | ||||
|    * ### Usage | ||||
|    * | ||||
| @ -549,11 +528,11 @@ export class Router { | ||||
|    * router.navigate(['team', 33, 'user', 11], {relativeTo: route}); | ||||
|    * | ||||
|    * // Navigate without updating the URL
 | ||||
|    * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true }); | ||||
|    * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true}); | ||||
|    * ``` | ||||
|    * | ||||
|    * In opposite to `navigateByUrl`, `navigate` always takes a delta | ||||
|    * that is applied to the current URL. | ||||
|    * In opposite to `navigateByUrl`, `navigate` always takes a delta that is applied to the current | ||||
|    * URL. | ||||
|    */ | ||||
|   navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}): | ||||
|       Promise<boolean> { | ||||
| @ -563,19 +542,13 @@ export class Router { | ||||
|     return this.navigateByUrl(this.createUrlTree(commands, extras), extras); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Serializes a {@link UrlTree} into a string. | ||||
|    */ | ||||
|   /** Serializes a {@link UrlTree} into a string */ | ||||
|   serializeUrl(url: UrlTree): string { return this.urlSerializer.serialize(url); } | ||||
| 
 | ||||
|   /** | ||||
|    * Parses a string into a {@link UrlTree}. | ||||
|    */ | ||||
|   /** Parses a string into a {@link UrlTree} */ | ||||
|   parseUrl(url: string): UrlTree { return this.urlSerializer.parse(url); } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns if the url is activated or not. | ||||
|    */ | ||||
|   /** Returns whether the url is activated */ | ||||
|   isActive(url: string|UrlTree, exact: boolean): boolean { | ||||
|     if (url instanceof UrlTree) { | ||||
|       return containsTree(this.currentUrlTree, url, exact); | ||||
|  | ||||
| @ -16,7 +16,6 @@ import {UrlSegment, UrlSegmentGroup, UrlTree, equalSegments} from './url_tree'; | ||||
| import {merge, shallowEqual, shallowEqualArrays} from './utils/collection'; | ||||
| import {Tree, TreeNode} from './utils/tree'; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * @whatItDoes Represents the state of the router. | ||||
|  * | ||||
| @ -45,14 +44,10 @@ import {Tree, TreeNode} from './utils/tree'; | ||||
|  * @stable | ||||
|  */ | ||||
| export class RouterState extends Tree<ActivatedRoute> { | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   constructor( | ||||
|       root: TreeNode<ActivatedRoute>, | ||||
|       /** | ||||
|        * The current snapshot of the router state. | ||||
|        */ | ||||
|       /** The current snapshot of the router state */ | ||||
|       public snapshot: RouterStateSnapshot) { | ||||
|     super(root); | ||||
|     setRouterStateSnapshot<RouterState, ActivatedRoute>(this, root); | ||||
| @ -90,17 +85,18 @@ export function createEmptyStateSnapshot( | ||||
| /** | ||||
|  * @whatItDoes Contains the information about a route associated with a component loaded in an | ||||
|  * outlet. | ||||
|  * ActivatedRoute can also be used to traverse the router state tree. | ||||
|  * An `ActivatedRoute` can also be used to traverse the router state tree. | ||||
|  * | ||||
|  * @howToUse | ||||
|  * | ||||
|  * ``` | ||||
|  * @Component({templateUrl:'./my-component.html'}) | ||||
|  * @Component({...}) | ||||
|  * class MyComponent { | ||||
|  *   constructor(route: ActivatedRoute) { | ||||
|  *     const id: Observable<string> = route.params.map(p => p.id); | ||||
|  *     const url: Observable<string> = route.url.map(s => s.join('')); | ||||
|  *     const user = route.data.map(d => d.user); //includes `data` and `resolve`
 | ||||
|  *     const url: Observable<string> = route.url.map(segments => segments.join('')); | ||||
|  *     // route.data includes both `data` and `resolve`
 | ||||
|  *     const user = route.data.map(d => d.user); | ||||
|  *   } | ||||
|  * } | ||||
|  * ``` | ||||
| @ -108,112 +104,64 @@ export function createEmptyStateSnapshot( | ||||
|  * @stable | ||||
|  */ | ||||
| export class ActivatedRoute { | ||||
|   /** The current snapshot of this route */ | ||||
|   snapshot: ActivatedRouteSnapshot; | ||||
|   /** @internal */ | ||||
|   _futureSnapshot: ActivatedRouteSnapshot; | ||||
| 
 | ||||
|   /** | ||||
|    * The current snapshot of this route. | ||||
|    */ | ||||
|   snapshot: ActivatedRouteSnapshot; | ||||
| 
 | ||||
|   /** @internal */ | ||||
|   _routerState: RouterState; | ||||
| 
 | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   constructor( | ||||
|       /** | ||||
|        *  The URL segments matched by this route. The observable will emit a new value when | ||||
|        *  the array of segments changes. | ||||
|        */ | ||||
|       /** An observable of the URL segments matched by this route */ | ||||
|       public url: Observable<UrlSegment[]>, | ||||
| 
 | ||||
|       /** | ||||
|        * The matrix parameters scoped to this route. The observable will emit a new value when | ||||
|        * the set of the parameters changes. | ||||
|        */ | ||||
|       /** An observable of the matrix parameters scoped to this route */ | ||||
|       public params: Observable<Params>, | ||||
| 
 | ||||
|       /** | ||||
|        * The query parameters shared by all the routes. The observable will emit a new value when | ||||
|        * the set of the parameters changes. | ||||
|        */ | ||||
|       /** An observable of the query parameters shared by all the routes */ | ||||
|       public queryParams: Observable<Params>, | ||||
| 
 | ||||
|       /** | ||||
|        * The URL fragment shared by all the routes. The observable will emit a new value when | ||||
|        * the URL fragment changes. | ||||
|        */ | ||||
|       /** An observable of the URL fragment shared by all the routes */ | ||||
|       public fragment: Observable<string>, | ||||
| 
 | ||||
|       /** | ||||
|        * The static and resolved data of this route. The observable will emit a new value when | ||||
|        * any of the resolvers returns a new object. | ||||
|        */ | ||||
|       /** An observable of the static and resolved data of this route. */ | ||||
|       public data: Observable<Data>, | ||||
| 
 | ||||
|       /** | ||||
|        * The outlet name of the route. It's a constant. | ||||
|        */ | ||||
|       /** The outlet name of the route. It's a constant */ | ||||
|       public outlet: string, | ||||
| 
 | ||||
|       /** | ||||
|        * The component of the route. It's a constant. | ||||
|        */ | ||||
|       public component: Type<any>|string,  // TODO: vsavkin: remove |string
 | ||||
|       futureSnapshot: ActivatedRouteSnapshot) { | ||||
|       /** The component of the route. It's a constant */ | ||||
|       // TODO(vsavkin): remove |string
 | ||||
|       public component: Type<any>|string, futureSnapshot: ActivatedRouteSnapshot) { | ||||
|     this._futureSnapshot = futureSnapshot; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * The configuration used to match this route. | ||||
|    */ | ||||
|   /** The configuration used to match this route */ | ||||
|   get routeConfig(): Route { return this._futureSnapshot.routeConfig; } | ||||
| 
 | ||||
|   /** | ||||
|    * The root of the router state. | ||||
|    */ | ||||
|   /** The root of the router state */ | ||||
|   get root(): ActivatedRoute { return this._routerState.root; } | ||||
| 
 | ||||
|   /** | ||||
|    * The parent of this route in the router state tree. | ||||
|    */ | ||||
|   /** The parent of this route in the router state tree */ | ||||
|   get parent(): ActivatedRoute { return this._routerState.parent(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The first child of this route in the router state tree. | ||||
|    */ | ||||
|   /** The first child of this route in the router state tree */ | ||||
|   get firstChild(): ActivatedRoute { return this._routerState.firstChild(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The children of this route in the router state tree. | ||||
|    */ | ||||
|   /** The children of this route in the router state tree */ | ||||
|   get children(): ActivatedRoute[] { return this._routerState.children(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The path from the root of the router state tree to this route. | ||||
|    */ | ||||
|   /** The path from the root of the router state tree to this route */ | ||||
|   get pathFromRoot(): ActivatedRoute[] { return this._routerState.pathFromRoot(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   toString(): string { | ||||
|     return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @internal | ||||
|  */ | ||||
| /** @internal */ | ||||
| export type Inherited = { | ||||
|   params: Params; data: Data; resolve: Data; | ||||
|   params: Params, | ||||
|   data: Data, | ||||
|   resolve: Data, | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @internal | ||||
|  */ | ||||
| /** @internal */ | ||||
| export function | ||||
| inheritedParamsDataResolve(route: ActivatedRouteSnapshot): | ||||
|     Inherited { | ||||
| @ -269,59 +217,32 @@ inheritedParamsDataResolve(route: ActivatedRouteSnapshot): | ||||
| export class ActivatedRouteSnapshot { | ||||
|   /** @internal **/ | ||||
|   _routeConfig: Route; | ||||
| 
 | ||||
|   /** @internal **/ | ||||
|   _urlSegment: UrlSegmentGroup; | ||||
| 
 | ||||
|   /** @internal */ | ||||
|   _lastPathIndex: number; | ||||
| 
 | ||||
|   /** @internal */ | ||||
|   _resolve: ResolveData; | ||||
| 
 | ||||
|   /** @internal */ | ||||
|   _resolvedData: Data; | ||||
| 
 | ||||
|   /** @internal */ | ||||
|   _routerState: RouterStateSnapshot; | ||||
| 
 | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   constructor( | ||||
|       /** | ||||
|        *  The URL segments matched by this route. | ||||
|        */ | ||||
|       /** The URL segments matched by this route */ | ||||
|       public url: UrlSegment[], | ||||
| 
 | ||||
|       /** | ||||
|        * The matrix parameters scoped to this route. | ||||
|        */ | ||||
|       /** The matrix parameters scoped to this route */ | ||||
|       public params: Params, | ||||
| 
 | ||||
|       /** | ||||
|        * The query parameters shared by all the routes. | ||||
|        */ | ||||
|       /** The query parameters shared by all the routes */ | ||||
|       public queryParams: Params, | ||||
| 
 | ||||
|       /** | ||||
|        * The URL fragment shared by all the routes. | ||||
|        */ | ||||
|       /** The URL fragment shared by all the routes */ | ||||
|       public fragment: string, | ||||
| 
 | ||||
|       /** | ||||
|        * The static and resolved data of this route. | ||||
|        */ | ||||
|       /** The static and resolved data of this route */ | ||||
|       public data: Data, | ||||
| 
 | ||||
|       /** | ||||
|        * The outlet name of the route. | ||||
|        */ | ||||
|       /** The outlet name of the route */ | ||||
|       public outlet: string, | ||||
| 
 | ||||
|       /** | ||||
|        * The component of the route. | ||||
|        */ | ||||
|       /** The component of the route */ | ||||
|       public component: Type<any>|string, routeConfig: Route, urlSegment: UrlSegmentGroup, | ||||
|       lastPathIndex: number, resolve: ResolveData) { | ||||
|     this._routeConfig = routeConfig; | ||||
| @ -330,41 +251,26 @@ export class ActivatedRouteSnapshot { | ||||
|     this._resolve = resolve; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * The configuration used to match this route. | ||||
|    */ | ||||
|   /** The configuration used to match this route */ | ||||
|   get routeConfig(): Route { return this._routeConfig; } | ||||
| 
 | ||||
|   /** | ||||
|    * The root of the router state. | ||||
|    */ | ||||
|   /** The root of the router state */ | ||||
|   get root(): ActivatedRouteSnapshot { return this._routerState.root; } | ||||
| 
 | ||||
|   /** | ||||
|    * The parent of this route in the router state tree. | ||||
|    */ | ||||
|   /** The parent of this route in the router state tree */ | ||||
|   get parent(): ActivatedRouteSnapshot { return this._routerState.parent(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The first child of this route in the router state tree. | ||||
|    */ | ||||
|   /** The first child of this route in the router state tree */ | ||||
|   get firstChild(): ActivatedRouteSnapshot { return this._routerState.firstChild(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The children of this route in the router state tree. | ||||
|    */ | ||||
|   /** The children of this route in the router state tree */ | ||||
|   get children(): ActivatedRouteSnapshot[] { return this._routerState.children(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * The path from the root of the router state tree to this route. | ||||
|    */ | ||||
|   /** The path from the root of the router state tree to this route */ | ||||
|   get pathFromRoot(): ActivatedRouteSnapshot[] { return this._routerState.pathFromRoot(this); } | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   toString(): string { | ||||
|     const url = this.url.map(s => s.toString()).join('/'); | ||||
|     const url = this.url.map(segment => segment.toString()).join('/'); | ||||
|     const matched = this._routeConfig ? this._routeConfig.path : ''; | ||||
|     return `Route(url:'${url}', path:'${matched}')`; | ||||
|   } | ||||
| @ -396,11 +302,8 @@ export class ActivatedRouteSnapshot { | ||||
|  * @stable | ||||
|  */ | ||||
| export class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> { | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   constructor( | ||||
| 
 | ||||
|       /** The url from which this snapshot was created */ | ||||
|       public url: string, root: TreeNode<ActivatedRouteSnapshot>) { | ||||
|     super(root); | ||||
|  | ||||
| @ -17,10 +17,10 @@ export function containsTree(container: UrlTree, containee: UrlTree, exact: bool | ||||
|   if (exact) { | ||||
|     return equalQueryParams(container.queryParams, containee.queryParams) && | ||||
|         equalSegmentGroups(container.root, containee.root); | ||||
|   } else { | ||||
|     return containsQueryParams(container.queryParams, containee.queryParams) && | ||||
|         containsSegmentGroup(container.root, containee.root); | ||||
|   } | ||||
| 
 | ||||
|   return containsQueryParams(container.queryParams, containee.queryParams) && | ||||
|         containsSegmentGroup(container.root, containee.root); | ||||
| } | ||||
| 
 | ||||
| function equalQueryParams( | ||||
| @ -83,7 +83,7 @@ function containsSegmentGroupHelper( | ||||
|  * class MyComponent { | ||||
|  *   constructor(router: Router) { | ||||
|  *     const tree: UrlTree = | ||||
|  * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment'); | ||||
|  *       router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment'); | ||||
|  *     const f = tree.fragment; // return 'fragment'
 | ||||
|  *     const q = tree.queryParams; // returns {debug: 'true'}
 | ||||
|  *     const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET]; | ||||
| @ -103,79 +103,49 @@ function containsSegmentGroupHelper( | ||||
|  * @stable | ||||
|  */ | ||||
| export class UrlTree { | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   constructor( | ||||
|       /** | ||||
|       * The root segment group of the URL tree. | ||||
|        */ | ||||
|       /** The root segment group of the URL tree */ | ||||
|       public root: UrlSegmentGroup, | ||||
|       /** | ||||
|        * The query params of the URL. | ||||
|        */ | ||||
|       /** The query params of the URL */ | ||||
|       public queryParams: {[key: string]: string}, | ||||
|       /** | ||||
|        * The fragment of the URL. | ||||
|        */ | ||||
|       /** The fragment of the URL */ | ||||
|       public fragment: string) {} | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   /** @docsNotRequired */ | ||||
|   toString(): string { return new DefaultUrlSerializer().serialize(this); } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @whatItDoes Represents the parsed URL segment. | ||||
|  * @whatItDoes Represents the parsed URL segment group. | ||||
|  * | ||||
|  * See {@link UrlTree} for more information. | ||||
|  * | ||||
|  * @stable | ||||
|  */ | ||||
| export class UrlSegmentGroup { | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   _sourceSegment: UrlSegmentGroup; | ||||
| 
 | ||||
|   /** | ||||
|    * @internal | ||||
|    */ | ||||
|   /** @internal */ | ||||
|   _segmentIndexShift: number; | ||||
| 
 | ||||
|   /** | ||||
|    * The parent node in the url tree. | ||||
|    */ | ||||
|   public parent: UrlSegmentGroup = null; | ||||
|   /** The parent node in the url tree */ | ||||
|   parent: UrlSegmentGroup = null; | ||||
| 
 | ||||
|   constructor( | ||||
|       /** | ||||
|        * The URL segments of this group. See {@link UrlSegment} for more information. | ||||
|        */ | ||||
|       /** The URL segments of this group. See {@link UrlSegment} for more information */ | ||||
|       public segments: UrlSegment[], | ||||
|       /** | ||||
|        * The list of children of this group. | ||||
|        */ | ||||
|       public children: {[key: string]: UrlSegmentGroup} | ||||
| 
 | ||||
|       ) { | ||||
|       /** The list of children of this group */ | ||||
|       public children: {[key: string]: UrlSegmentGroup}) { | ||||
|     forEach(children, (v: any, k: any) => v.parent = this); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Return true if the segment has child segments | ||||
|    */ | ||||
|   /** Wether the segment has child segments */ | ||||
|   hasChildren(): boolean { return this.numberOfChildren > 0; } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns the number of child sements. | ||||
|    */ | ||||
|   /** Number of child segments */ | ||||
|   get numberOfChildren(): number { return Object.keys(this.children).length; } | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   /** @docsNotRequired */ | ||||
|   toString(): string { return serializePaths(this); } | ||||
| } | ||||
| 
 | ||||
| @ -200,26 +170,20 @@ export class UrlSegmentGroup { | ||||
|  * | ||||
|  * @description | ||||
|  * | ||||
|  * A UrlSegment is a part of a URL between the two slashes. It contains a path and | ||||
|  * the matrix parameters associated with the segment. | ||||
|  * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix | ||||
|  * parameters associated with the segment. | ||||
|  * | ||||
|  * @stable | ||||
|  */ | ||||
| export class UrlSegment { | ||||
|   constructor( | ||||
|       /** | ||||
|        * The path part of a URL segment. | ||||
|        */ | ||||
|       /** The path part of a URL segment */ | ||||
|       public path: string, | ||||
| 
 | ||||
|       /** | ||||
|        * The matrix parameters associated with a segment. | ||||
|        */ | ||||
|       public parameters: {[key: string]: string}) {} | ||||
|       /** The matrix parameters associated with a segment */ | ||||
|       public parameters: {[name: string]: string}) {} | ||||
| 
 | ||||
|   /** | ||||
|    * @docsNotRequired | ||||
|    */ | ||||
|   /** @docsNotRequired */ | ||||
|   toString(): string { return serializePath(this); } | ||||
| } | ||||
| 
 | ||||
| @ -268,14 +232,10 @@ export function mapChildrenIntoArray<T>( | ||||
|  * @stable | ||||
|  */ | ||||
| export abstract class UrlSerializer { | ||||
|   /** | ||||
|    * Parse a url into a {@link UrlTree}. | ||||
|    */ | ||||
|   /** Parse a url into a {@link UrlTree} */ | ||||
|   abstract parse(url: string): UrlTree; | ||||
| 
 | ||||
|   /** | ||||
|    * Converts a {@link UrlTree} into a url. | ||||
|    */ | ||||
|   /** Converts a {@link UrlTree} into a url */ | ||||
|   abstract serialize(tree: UrlTree): string; | ||||
| } | ||||
| 
 | ||||
| @ -298,17 +258,13 @@ export abstract class UrlSerializer { | ||||
|  * @stable | ||||
|  */ | ||||
| export class DefaultUrlSerializer implements UrlSerializer { | ||||
|   /** | ||||
|    * Parse a url into a {@link UrlTree}. | ||||
|    */ | ||||
|   /** Parses a url into a {@link UrlTree} */ | ||||
|   parse(url: string): UrlTree { | ||||
|     const p = new UrlParser(url); | ||||
|     return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment()); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Converts a {@link UrlTree} into a url. | ||||
|    */ | ||||
|   /** Converts a {@link UrlTree} into a url */ | ||||
|   serialize(tree: UrlTree): string { | ||||
|     const segment = `/${serializeSegment(tree.root, true)}`; | ||||
|     const query = serializeQueryParams(tree.queryParams); | ||||
| @ -383,6 +339,7 @@ function serializeQueryParams(params: {[key: string]: any}): string { | ||||
| class Pair<A, B> { | ||||
|   constructor(public first: A, public second: B) {} | ||||
| } | ||||
| 
 | ||||
| function pairs<T>(obj: {[key: string]: T}): Pair<string, T>[] { | ||||
|   const res: Pair<string, T>[] = []; | ||||
|   for (const prop in obj) { | ||||
| @ -436,9 +393,9 @@ class UrlParser { | ||||
| 
 | ||||
|     if (this.remaining === '' || this.remaining.startsWith('?') || this.remaining.startsWith('#')) { | ||||
|       return new UrlSegmentGroup([], {}); | ||||
|     } else { | ||||
|       return new UrlSegmentGroup([], this.parseChildren()); | ||||
|     } | ||||
| 
 | ||||
|     return new UrlSegmentGroup([], this.parseChildren()); | ||||
|   } | ||||
| 
 | ||||
|   parseChildren(): {[key: string]: UrlSegmentGroup} { | ||||
| @ -508,9 +465,9 @@ class UrlParser { | ||||
|   parseFragment(): string { | ||||
|     if (this.peekStartsWith('#')) { | ||||
|       return decodeURI(this.remaining.substring(1)); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
| 
 | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   parseMatrixParams(): {[key: string]: any} { | ||||
|  | ||||
| @ -60,7 +60,7 @@ export function last<T>(a: T[]): T { | ||||
| } | ||||
| 
 | ||||
| export function and(bools: boolean[]): boolean { | ||||
|   return bools.reduce((a, b) => a && b, true); | ||||
|   return !bools.some(v => !v); | ||||
| } | ||||
| 
 | ||||
| export function merge<V>(m1: {[key: string]: V}, m2: {[key: string]: V}): {[key: string]: V} { | ||||
| @ -81,8 +81,7 @@ export function merge<V>(m1: {[key: string]: V}, m2: {[key: string]: V}): {[key: | ||||
|   return m; | ||||
| } | ||||
| 
 | ||||
| export function forEach<K, V>( | ||||
|     map: {[key: string]: V}, callback: /*(V, K) => void*/ Function): void { | ||||
| export function forEach<K, V>(map: {[key: string]: V}, callback: (v: V, k: string) => void): void { | ||||
|   for (const prop in map) { | ||||
|     if (map.hasOwnProperty(prop)) { | ||||
|       callback(map[prop], prop); | ||||
| @ -117,9 +116,9 @@ export function waitForMap<A, B>( | ||||
|     const concatted$ = concatAll.call(of (...waitFor)); | ||||
|     const last$ = l.last.call(concatted$); | ||||
|     return map.call(last$, () => res); | ||||
|   } else { | ||||
|     return of (res); | ||||
|   } | ||||
| 
 | ||||
|   return of (res); | ||||
| } | ||||
| 
 | ||||
| export function andObservables(observables: Observable<Observable<any>>): Observable<boolean> { | ||||
| @ -130,9 +129,11 @@ export function andObservables(observables: Observable<Observable<any>>): Observ | ||||
| export function wrapIntoObservable<T>(value: T | Promise<T>| Observable<T>): Observable<T> { | ||||
|   if (value instanceof Observable) { | ||||
|     return value; | ||||
|   } else if (value instanceof Promise) { | ||||
|     return fromPromise(value); | ||||
|   } else { | ||||
|     return of (value); | ||||
|   } | ||||
| 
 | ||||
|   if (value instanceof Promise) { | ||||
|     return fromPromise(value); | ||||
|   } | ||||
| 
 | ||||
|   return of (value); | ||||
| } | ||||
							
								
								
									
										4
									
								
								tools/public_api_guard/router/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								tools/public_api_guard/router/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -366,13 +366,13 @@ export declare abstract class UrlHandlingStrategy { | ||||
| /** @stable */ | ||||
| export declare class UrlSegment { | ||||
|     parameters: { | ||||
|         [key: string]: string; | ||||
|         [name: string]: string; | ||||
|     }; | ||||
|     path: string; | ||||
|     constructor( | ||||
|         path: string, | ||||
|         parameters: { | ||||
|         [key: string]: string; | ||||
|         [name: string]: string; | ||||
|     }); | ||||
|     toString(): string; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user