UNPKG

254 kBJavaScriptView Raw
1/**
2 * @license Angular v8.1.3
3 * (c) 2010-2019 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { LocationStrategy, Location, PlatformLocation, APP_BASE_HREF, ViewportScroller, HashLocationStrategy, PathLocationStrategy, LOCATION_INITIALIZED } from '@angular/common';
8import { Component, ɵisObservable, ɵisPromise, NgModuleRef, InjectionToken, NgModuleFactory, ɵConsole, NgZone, isDevMode, Directive, Attribute, Renderer2, ElementRef, Input, HostListener, HostBinding, Optional, ContentChildren, EventEmitter, ViewContainerRef, ComponentFactoryResolver, ChangeDetectorRef, Output, Injectable, NgModuleFactoryLoader, Compiler, Injector, ApplicationRef, SystemJsNgModuleLoader, NgProbeToken, ANALYZE_FOR_ENTRY_COMPONENTS, SkipSelf, Inject, APP_INITIALIZER, APP_BOOTSTRAP_LISTENER, NgModule, Version } from '@angular/core';
9import { of, from, BehaviorSubject, EmptyError, Observable, combineLatest, defer, Subject, EMPTY } from 'rxjs';
10import { map, concatAll, last as last$1, catchError, first, mergeMap, every, switchMap, take, startWith, scan, filter, concatMap, reduce, tap, finalize, mergeAll } from 'rxjs/operators';
11import { ɵgetDOM } from '@angular/platform-browser';
12
13/**
14 * @fileoverview added by tsickle
15 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
16 */
17/**
18 * @license
19 * Copyright Google Inc. All Rights Reserved.
20 *
21 * Use of this source code is governed by an MIT-style license that can be
22 * found in the LICENSE file at https://angular.io/license
23 */
24/**
25 * Base for events the router goes through, as opposed to events tied to a specific
26 * route. Fired one time for any given navigation.
27 *
28 * \@usageNotes
29 *
30 * ```ts
31 * class MyService {
32 * constructor(public router: Router, logger: Logger) {
33 * router.events.pipe(
34 * filter(e => e instanceof RouterEvent)
35 * ).subscribe(e => {
36 * logger.log(e.id, e.url);
37 * });
38 * }
39 * }
40 * ```
41 *
42 * @see `Event`
43 * \@publicApi
44 */
45class RouterEvent {
46 /**
47 * @param {?} id
48 * @param {?} url
49 */
50 constructor(id, url) {
51 this.id = id;
52 this.url = url;
53 }
54}
55/**
56 * An event triggered when a navigation starts.
57 *
58 * \@publicApi
59 */
60class NavigationStart extends RouterEvent {
61 /**
62 * @param {?} id
63 * @param {?} url
64 * @param {?=} navigationTrigger
65 * @param {?=} restoredState
66 */
67 constructor(
68 /** @docsNotRequired */
69 id,
70 /** @docsNotRequired */
71 url,
72 /** @docsNotRequired */
73 navigationTrigger = 'imperative',
74 /** @docsNotRequired */
75 restoredState = null) {
76 super(id, url);
77 this.navigationTrigger = navigationTrigger;
78 this.restoredState = restoredState;
79 }
80 /**
81 * \@docsNotRequired
82 * @return {?}
83 */
84 toString() { return `NavigationStart(id: ${this.id}, url: '${this.url}')`; }
85}
86/**
87 * An event triggered when a navigation ends successfully.
88 *
89 * \@publicApi
90 */
91class NavigationEnd extends RouterEvent {
92 /**
93 * @param {?} id
94 * @param {?} url
95 * @param {?} urlAfterRedirects
96 */
97 constructor(
98 /** @docsNotRequired */
99 id,
100 /** @docsNotRequired */
101 url, urlAfterRedirects) {
102 super(id, url);
103 this.urlAfterRedirects = urlAfterRedirects;
104 }
105 /**
106 * \@docsNotRequired
107 * @return {?}
108 */
109 toString() {
110 return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
111 }
112}
113/**
114 * An event triggered when a navigation is canceled.
115 *
116 * \@publicApi
117 */
118class NavigationCancel extends RouterEvent {
119 /**
120 * @param {?} id
121 * @param {?} url
122 * @param {?} reason
123 */
124 constructor(
125 /** @docsNotRequired */
126 id,
127 /** @docsNotRequired */
128 url, reason) {
129 super(id, url);
130 this.reason = reason;
131 }
132 /**
133 * \@docsNotRequired
134 * @return {?}
135 */
136 toString() { return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; }
137}
138/**
139 * An event triggered when a navigation fails due to an unexpected error.
140 *
141 * \@publicApi
142 */
143class NavigationError extends RouterEvent {
144 /**
145 * @param {?} id
146 * @param {?} url
147 * @param {?} error
148 */
149 constructor(
150 /** @docsNotRequired */
151 id,
152 /** @docsNotRequired */
153 url, error) {
154 super(id, url);
155 this.error = error;
156 }
157 /**
158 * \@docsNotRequired
159 * @return {?}
160 */
161 toString() {
162 return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
163 }
164}
165/**
166 * An event triggered when routes are recognized.
167 *
168 * \@publicApi
169 */
170class RoutesRecognized extends RouterEvent {
171 /**
172 * @param {?} id
173 * @param {?} url
174 * @param {?} urlAfterRedirects
175 * @param {?} state
176 */
177 constructor(
178 /** @docsNotRequired */
179 id,
180 /** @docsNotRequired */
181 url, urlAfterRedirects, state) {
182 super(id, url);
183 this.urlAfterRedirects = urlAfterRedirects;
184 this.state = state;
185 }
186 /**
187 * \@docsNotRequired
188 * @return {?}
189 */
190 toString() {
191 return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
192 }
193}
194/**
195 * An event triggered at the start of the Guard phase of routing.
196 *
197 * \@publicApi
198 */
199class GuardsCheckStart extends RouterEvent {
200 /**
201 * @param {?} id
202 * @param {?} url
203 * @param {?} urlAfterRedirects
204 * @param {?} state
205 */
206 constructor(
207 /** @docsNotRequired */
208 id,
209 /** @docsNotRequired */
210 url, urlAfterRedirects, state) {
211 super(id, url);
212 this.urlAfterRedirects = urlAfterRedirects;
213 this.state = state;
214 }
215 /**
216 * @return {?}
217 */
218 toString() {
219 return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
220 }
221}
222/**
223 * An event triggered at the end of the Guard phase of routing.
224 *
225 * \@publicApi
226 */
227class GuardsCheckEnd extends RouterEvent {
228 /**
229 * @param {?} id
230 * @param {?} url
231 * @param {?} urlAfterRedirects
232 * @param {?} state
233 * @param {?} shouldActivate
234 */
235 constructor(
236 /** @docsNotRequired */
237 id,
238 /** @docsNotRequired */
239 url, urlAfterRedirects, state, shouldActivate) {
240 super(id, url);
241 this.urlAfterRedirects = urlAfterRedirects;
242 this.state = state;
243 this.shouldActivate = shouldActivate;
244 }
245 /**
246 * @return {?}
247 */
248 toString() {
249 return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
250 }
251}
252/**
253 * An event triggered at the the start of the Resolve phase of routing.
254 *
255 * Runs in the "resolve" phase whether or not there is anything to resolve.
256 * In future, may change to only run when there are things to be resolved.
257 *
258 * \@publicApi
259 */
260class ResolveStart extends RouterEvent {
261 /**
262 * @param {?} id
263 * @param {?} url
264 * @param {?} urlAfterRedirects
265 * @param {?} state
266 */
267 constructor(
268 /** @docsNotRequired */
269 id,
270 /** @docsNotRequired */
271 url, urlAfterRedirects, state) {
272 super(id, url);
273 this.urlAfterRedirects = urlAfterRedirects;
274 this.state = state;
275 }
276 /**
277 * @return {?}
278 */
279 toString() {
280 return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
281 }
282}
283/**
284 * An event triggered at the end of the Resolve phase of routing.
285 * @see `ResolveStart`.
286 *
287 * \@publicApi
288 */
289class ResolveEnd extends RouterEvent {
290 /**
291 * @param {?} id
292 * @param {?} url
293 * @param {?} urlAfterRedirects
294 * @param {?} state
295 */
296 constructor(
297 /** @docsNotRequired */
298 id,
299 /** @docsNotRequired */
300 url, urlAfterRedirects, state) {
301 super(id, url);
302 this.urlAfterRedirects = urlAfterRedirects;
303 this.state = state;
304 }
305 /**
306 * @return {?}
307 */
308 toString() {
309 return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
310 }
311}
312/**
313 * An event triggered before lazy loading a route configuration.
314 *
315 * \@publicApi
316 */
317class RouteConfigLoadStart {
318 /**
319 * @param {?} route
320 */
321 constructor(route) {
322 this.route = route;
323 }
324 /**
325 * @return {?}
326 */
327 toString() { return `RouteConfigLoadStart(path: ${this.route.path})`; }
328}
329/**
330 * An event triggered when a route has been lazy loaded.
331 *
332 * \@publicApi
333 */
334class RouteConfigLoadEnd {
335 /**
336 * @param {?} route
337 */
338 constructor(route) {
339 this.route = route;
340 }
341 /**
342 * @return {?}
343 */
344 toString() { return `RouteConfigLoadEnd(path: ${this.route.path})`; }
345}
346/**
347 * An event triggered at the start of the child-activation
348 * part of the Resolve phase of routing.
349 * @see `ChildActivationEnd`
350 * @see `ResolveStart`
351 *
352 * \@publicApi
353 */
354class ChildActivationStart {
355 /**
356 * @param {?} snapshot
357 */
358 constructor(snapshot) {
359 this.snapshot = snapshot;
360 }
361 /**
362 * @return {?}
363 */
364 toString() {
365 /** @type {?} */
366 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
367 return `ChildActivationStart(path: '${path}')`;
368 }
369}
370/**
371 * An event triggered at the end of the child-activation part
372 * of the Resolve phase of routing.
373 * @see `ChildActivationStart`
374 * @see `ResolveStart` *
375 * \@publicApi
376 */
377class ChildActivationEnd {
378 /**
379 * @param {?} snapshot
380 */
381 constructor(snapshot) {
382 this.snapshot = snapshot;
383 }
384 /**
385 * @return {?}
386 */
387 toString() {
388 /** @type {?} */
389 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
390 return `ChildActivationEnd(path: '${path}')`;
391 }
392}
393/**
394 * An event triggered at the start of the activation part
395 * of the Resolve phase of routing.
396 * @see ActivationEnd`
397 * @see `ResolveStart`
398 *
399 * \@publicApi
400 */
401class ActivationStart {
402 /**
403 * @param {?} snapshot
404 */
405 constructor(snapshot) {
406 this.snapshot = snapshot;
407 }
408 /**
409 * @return {?}
410 */
411 toString() {
412 /** @type {?} */
413 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
414 return `ActivationStart(path: '${path}')`;
415 }
416}
417/**
418 * An event triggered at the end of the activation part
419 * of the Resolve phase of routing.
420 * @see `ActivationStart`
421 * @see `ResolveStart`
422 *
423 * \@publicApi
424 */
425class ActivationEnd {
426 /**
427 * @param {?} snapshot
428 */
429 constructor(snapshot) {
430 this.snapshot = snapshot;
431 }
432 /**
433 * @return {?}
434 */
435 toString() {
436 /** @type {?} */
437 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
438 return `ActivationEnd(path: '${path}')`;
439 }
440}
441/**
442 * An event triggered by scrolling.
443 *
444 * \@publicApi
445 */
446class Scroll {
447 /**
448 * @param {?} routerEvent
449 * @param {?} position
450 * @param {?} anchor
451 */
452 constructor(routerEvent, position, anchor) {
453 this.routerEvent = routerEvent;
454 this.position = position;
455 this.anchor = anchor;
456 }
457 /**
458 * @return {?}
459 */
460 toString() {
461 /** @type {?} */
462 const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
463 return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
464 }
465}
466
467/**
468 * @fileoverview added by tsickle
469 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
470 */
471/**
472 * This component is used internally within the router to be a placeholder when an empty
473 * router-outlet is needed. For example, with a config such as:
474 *
475 * `{path: 'parent', outlet: 'nav', children: [...]}`
476 *
477 * In order to render, there needs to be a component on this config, which will default
478 * to this `EmptyOutletComponent`.
479 */
480class ɵEmptyOutletComponent {
481}
482ɵEmptyOutletComponent.decorators = [
483 { type: Component, args: [{ template: `<router-outlet></router-outlet>` }] }
484];
485
486/**
487 * @fileoverview added by tsickle
488 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
489 */
490/**
491 * @license
492 * Copyright Google Inc. All Rights Reserved.
493 *
494 * Use of this source code is governed by an MIT-style license that can be
495 * found in the LICENSE file at https://angular.io/license
496 */
497/**
498 * The primary routing outlet.
499 *
500 * \@publicApi
501 * @type {?}
502 */
503const PRIMARY_OUTLET = 'primary';
504class ParamsAsMap {
505 /**
506 * @param {?} params
507 */
508 constructor(params) { this.params = params || {}; }
509 /**
510 * @param {?} name
511 * @return {?}
512 */
513 has(name) { return this.params.hasOwnProperty(name); }
514 /**
515 * @param {?} name
516 * @return {?}
517 */
518 get(name) {
519 if (this.has(name)) {
520 /** @type {?} */
521 const v = this.params[name];
522 return Array.isArray(v) ? v[0] : v;
523 }
524 return null;
525 }
526 /**
527 * @param {?} name
528 * @return {?}
529 */
530 getAll(name) {
531 if (this.has(name)) {
532 /** @type {?} */
533 const v = this.params[name];
534 return Array.isArray(v) ? v : [v];
535 }
536 return [];
537 }
538 /**
539 * @return {?}
540 */
541 get keys() { return Object.keys(this.params); }
542}
543/**
544 * Converts a `Params` instance to a `ParamMap`.
545 * \@publicApi
546 * @param {?} params The instance to convert.
547 * @return {?} The new map instance.
548 *
549 */
550function convertToParamMap(params) {
551 return new ParamsAsMap(params);
552}
553/** @type {?} */
554const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
555/**
556 * @param {?} message
557 * @return {?}
558 */
559function navigationCancelingError(message) {
560 /** @type {?} */
561 const error = Error('NavigationCancelingError: ' + message);
562 ((/** @type {?} */ (error)))[NAVIGATION_CANCELING_ERROR] = true;
563 return error;
564}
565/**
566 * @param {?} error
567 * @return {?}
568 */
569function isNavigationCancelingError(error) {
570 return error && ((/** @type {?} */ (error)))[NAVIGATION_CANCELING_ERROR];
571}
572// Matches the route configuration (`route`) against the actual URL (`segments`).
573/**
574 * @param {?} segments
575 * @param {?} segmentGroup
576 * @param {?} route
577 * @return {?}
578 */
579function defaultUrlMatcher(segments, segmentGroup, route) {
580 /** @type {?} */
581 const parts = (/** @type {?} */ (route.path)).split('/');
582 if (parts.length > segments.length) {
583 // The actual URL is shorter than the config, no match
584 return null;
585 }
586 if (route.pathMatch === 'full' &&
587 (segmentGroup.hasChildren() || parts.length < segments.length)) {
588 // The config is longer than the actual URL but we are looking for a full match, return null
589 return null;
590 }
591 /** @type {?} */
592 const posParams = {};
593 // Check each config part against the actual URL
594 for (let index = 0; index < parts.length; index++) {
595 /** @type {?} */
596 const part = parts[index];
597 /** @type {?} */
598 const segment = segments[index];
599 /** @type {?} */
600 const isParameter = part.startsWith(':');
601 if (isParameter) {
602 posParams[part.substring(1)] = segment;
603 }
604 else if (part !== segment.path) {
605 // The actual URL part does not match the config, no match
606 return null;
607 }
608 }
609 return { consumed: segments.slice(0, parts.length), posParams };
610}
611
612/**
613 * @fileoverview added by tsickle
614 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
615 */
616class LoadedRouterConfig {
617 /**
618 * @param {?} routes
619 * @param {?} module
620 */
621 constructor(routes, module) {
622 this.routes = routes;
623 this.module = module;
624 }
625}
626/**
627 * @param {?} config
628 * @param {?=} parentPath
629 * @return {?}
630 */
631function validateConfig(config, parentPath = '') {
632 // forEach doesn't iterate undefined values
633 for (let i = 0; i < config.length; i++) {
634 /** @type {?} */
635 const route = config[i];
636 /** @type {?} */
637 const fullPath = getFullPath(parentPath, route);
638 validateNode(route, fullPath);
639 }
640}
641/**
642 * @param {?} route
643 * @param {?} fullPath
644 * @return {?}
645 */
646function validateNode(route, fullPath) {
647 if (!route) {
648 throw new Error(`
649 Invalid configuration of route '${fullPath}': Encountered undefined route.
650 The reason might be an extra comma.
651
652 Example:
653 const routes: Routes = [
654 { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
655 { path: 'dashboard', component: DashboardComponent },, << two commas
656 { path: 'detail/:id', component: HeroDetailComponent }
657 ];
658 `);
659 }
660 if (Array.isArray(route)) {
661 throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`);
662 }
663 if (!route.component && !route.children && !route.loadChildren &&
664 (route.outlet && route.outlet !== PRIMARY_OUTLET)) {
665 throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
666 }
667 if (route.redirectTo && route.children) {
668 throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
669 }
670 if (route.redirectTo && route.loadChildren) {
671 throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
672 }
673 if (route.children && route.loadChildren) {
674 throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
675 }
676 if (route.redirectTo && route.component) {
677 throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`);
678 }
679 if (route.path && route.matcher) {
680 throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
681 }
682 if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) {
683 throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`);
684 }
685 if (route.path === void 0 && route.matcher === void 0) {
686 throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
687 }
688 if (typeof route.path === 'string' && route.path.charAt(0) === '/') {
689 throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`);
690 }
691 if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
692 /** @type {?} */
693 const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
694 throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
695 }
696 if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') {
697 throw new Error(`Invalid configuration of route '${fullPath}': pathMatch can only be set to 'prefix' or 'full'`);
698 }
699 if (route.children) {
700 validateConfig(route.children, fullPath);
701 }
702}
703/**
704 * @param {?} parentPath
705 * @param {?} currentRoute
706 * @return {?}
707 */
708function getFullPath(parentPath, currentRoute) {
709 if (!currentRoute) {
710 return parentPath;
711 }
712 if (!parentPath && !currentRoute.path) {
713 return '';
714 }
715 else if (parentPath && !currentRoute.path) {
716 return `${parentPath}/`;
717 }
718 else if (!parentPath && currentRoute.path) {
719 return currentRoute.path;
720 }
721 else {
722 return `${parentPath}/${currentRoute.path}`;
723 }
724}
725/**
726 * Makes a copy of the config and adds any default required properties.
727 * @param {?} r
728 * @return {?}
729 */
730function standardizeConfig(r) {
731 /** @type {?} */
732 const children = r.children && r.children.map(standardizeConfig);
733 /** @type {?} */
734 const c = children ? Object.assign({}, r, { children }) : Object.assign({}, r);
735 if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) {
736 c.component = ɵEmptyOutletComponent;
737 }
738 return c;
739}
740
741/**
742 * @fileoverview added by tsickle
743 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
744 */
745/**
746 * @param {?} a
747 * @param {?} b
748 * @return {?}
749 */
750function shallowEqualArrays(a, b) {
751 if (a.length !== b.length)
752 return false;
753 for (let i = 0; i < a.length; ++i) {
754 if (!shallowEqual(a[i], b[i]))
755 return false;
756 }
757 return true;
758}
759/**
760 * @param {?} a
761 * @param {?} b
762 * @return {?}
763 */
764function shallowEqual(a, b) {
765 // Casting Object.keys return values to include `undefined` as there are some cases
766 // in IE 11 where this can happen. Cannot provide a test because the behavior only
767 // exists in certain circumstances in IE 11, therefore doing this cast ensures the
768 // logic is correct for when this edge case is hit.
769 /** @type {?} */
770 const k1 = (/** @type {?} */ (Object.keys(a)));
771 /** @type {?} */
772 const k2 = (/** @type {?} */ (Object.keys(b)));
773 if (!k1 || !k2 || k1.length != k2.length) {
774 return false;
775 }
776 /** @type {?} */
777 let key;
778 for (let i = 0; i < k1.length; i++) {
779 key = k1[i];
780 if (a[key] !== b[key]) {
781 return false;
782 }
783 }
784 return true;
785}
786/**
787 * Flattens single-level nested arrays.
788 * @template T
789 * @param {?} arr
790 * @return {?}
791 */
792function flatten(arr) {
793 return Array.prototype.concat.apply([], arr);
794}
795/**
796 * Return the last element of an array.
797 * @template T
798 * @param {?} a
799 * @return {?}
800 */
801function last(a) {
802 return a.length > 0 ? a[a.length - 1] : null;
803}
804/**
805 * @template K, V
806 * @param {?} map
807 * @param {?} callback
808 * @return {?}
809 */
810function forEach(map, callback) {
811 for (const prop in map) {
812 if (map.hasOwnProperty(prop)) {
813 callback(map[prop], prop);
814 }
815 }
816}
817/**
818 * @template A, B
819 * @param {?} obj
820 * @param {?} fn
821 * @return {?}
822 */
823function waitForMap(obj, fn) {
824 if (Object.keys(obj).length === 0) {
825 return of({});
826 }
827 /** @type {?} */
828 const waitHead = [];
829 /** @type {?} */
830 const waitTail = [];
831 /** @type {?} */
832 const res = {};
833 forEach(obj, (/**
834 * @param {?} a
835 * @param {?} k
836 * @return {?}
837 */
838 (a, k) => {
839 /** @type {?} */
840 const mapped = fn(k, a).pipe(map((/**
841 * @param {?} r
842 * @return {?}
843 */
844 (r) => res[k] = r)));
845 if (k === PRIMARY_OUTLET) {
846 waitHead.push(mapped);
847 }
848 else {
849 waitTail.push(mapped);
850 }
851 }));
852 // Closure compiler has problem with using spread operator here. So just using Array.concat.
853 return of.apply(null, waitHead.concat(waitTail)).pipe(concatAll(), last$1(), map((/**
854 * @return {?}
855 */
856 () => res)));
857}
858/**
859 * @template T
860 * @param {?} value
861 * @return {?}
862 */
863function wrapIntoObservable(value) {
864 if (ɵisObservable(value)) {
865 return value;
866 }
867 if (ɵisPromise(value)) {
868 // Use `Promise.resolve()` to wrap promise-like instances.
869 // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the
870 // change detection.
871 return from(Promise.resolve(value));
872 }
873 return of(value);
874}
875
876/**
877 * @fileoverview added by tsickle
878 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
879 */
880/**
881 * @return {?}
882 */
883function createEmptyUrlTree() {
884 return new UrlTree(new UrlSegmentGroup([], {}), {}, null);
885}
886/**
887 * @param {?} container
888 * @param {?} containee
889 * @param {?} exact
890 * @return {?}
891 */
892function containsTree(container, containee, exact) {
893 if (exact) {
894 return equalQueryParams(container.queryParams, containee.queryParams) &&
895 equalSegmentGroups(container.root, containee.root);
896 }
897 return containsQueryParams(container.queryParams, containee.queryParams) &&
898 containsSegmentGroup(container.root, containee.root);
899}
900/**
901 * @param {?} container
902 * @param {?} containee
903 * @return {?}
904 */
905function equalQueryParams(container, containee) {
906 // TODO: This does not handle array params correctly.
907 return shallowEqual(container, containee);
908}
909/**
910 * @param {?} container
911 * @param {?} containee
912 * @return {?}
913 */
914function equalSegmentGroups(container, containee) {
915 if (!equalPath(container.segments, containee.segments))
916 return false;
917 if (container.numberOfChildren !== containee.numberOfChildren)
918 return false;
919 for (const c in containee.children) {
920 if (!container.children[c])
921 return false;
922 if (!equalSegmentGroups(container.children[c], containee.children[c]))
923 return false;
924 }
925 return true;
926}
927/**
928 * @param {?} container
929 * @param {?} containee
930 * @return {?}
931 */
932function containsQueryParams(container, containee) {
933 // TODO: This does not handle array params correctly.
934 return Object.keys(containee).length <= Object.keys(container).length &&
935 Object.keys(containee).every((/**
936 * @param {?} key
937 * @return {?}
938 */
939 key => containee[key] === container[key]));
940}
941/**
942 * @param {?} container
943 * @param {?} containee
944 * @return {?}
945 */
946function containsSegmentGroup(container, containee) {
947 return containsSegmentGroupHelper(container, containee, containee.segments);
948}
949/**
950 * @param {?} container
951 * @param {?} containee
952 * @param {?} containeePaths
953 * @return {?}
954 */
955function containsSegmentGroupHelper(container, containee, containeePaths) {
956 if (container.segments.length > containeePaths.length) {
957 /** @type {?} */
958 const current = container.segments.slice(0, containeePaths.length);
959 if (!equalPath(current, containeePaths))
960 return false;
961 if (containee.hasChildren())
962 return false;
963 return true;
964 }
965 else if (container.segments.length === containeePaths.length) {
966 if (!equalPath(container.segments, containeePaths))
967 return false;
968 for (const c in containee.children) {
969 if (!container.children[c])
970 return false;
971 if (!containsSegmentGroup(container.children[c], containee.children[c]))
972 return false;
973 }
974 return true;
975 }
976 else {
977 /** @type {?} */
978 const current = containeePaths.slice(0, container.segments.length);
979 /** @type {?} */
980 const next = containeePaths.slice(container.segments.length);
981 if (!equalPath(container.segments, current))
982 return false;
983 if (!container.children[PRIMARY_OUTLET])
984 return false;
985 return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next);
986 }
987}
988/**
989 * \@description
990 *
991 * Represents the parsed URL.
992 *
993 * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a
994 * serialized tree.
995 * UrlTree is a data structure that provides a lot of affordances in dealing with URLs
996 *
997 * \@usageNotes
998 * ### Example
999 *
1000 * ```
1001 * \@Component({templateUrl:'template.html'})
1002 * class MyComponent {
1003 * constructor(router: Router) {
1004 * const tree: UrlTree =
1005 * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment');
1006 * const f = tree.fragment; // return 'fragment'
1007 * const q = tree.queryParams; // returns {debug: 'true'}
1008 * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
1009 * const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33'
1010 * g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor'
1011 * g.children['support'].segments; // return 1 segment 'help'
1012 * }
1013 * }
1014 * ```
1015 *
1016 * \@publicApi
1017 */
1018class UrlTree {
1019 /**
1020 * \@internal
1021 * @param {?} root
1022 * @param {?} queryParams
1023 * @param {?} fragment
1024 */
1025 constructor(root, queryParams, fragment) {
1026 this.root = root;
1027 this.queryParams = queryParams;
1028 this.fragment = fragment;
1029 }
1030 /**
1031 * @return {?}
1032 */
1033 get queryParamMap() {
1034 if (!this._queryParamMap) {
1035 this._queryParamMap = convertToParamMap(this.queryParams);
1036 }
1037 return this._queryParamMap;
1038 }
1039 /**
1040 * \@docsNotRequired
1041 * @return {?}
1042 */
1043 toString() { return DEFAULT_SERIALIZER.serialize(this); }
1044}
1045/**
1046 * \@description
1047 *
1048 * Represents the parsed URL segment group.
1049 *
1050 * See `UrlTree` for more information.
1051 *
1052 * \@publicApi
1053 */
1054class UrlSegmentGroup {
1055 /**
1056 * @param {?} segments
1057 * @param {?} children
1058 */
1059 constructor(segments, children) {
1060 this.segments = segments;
1061 this.children = children;
1062 /**
1063 * The parent node in the url tree
1064 */
1065 this.parent = null;
1066 forEach(children, (/**
1067 * @template THIS
1068 * @this {THIS}
1069 * @param {?} v
1070 * @param {?} k
1071 * @return {THIS}
1072 */
1073 (v, k) => v.parent = this));
1074 }
1075 /**
1076 * Whether the segment has child segments
1077 * @return {?}
1078 */
1079 hasChildren() { return this.numberOfChildren > 0; }
1080 /**
1081 * Number of child segments
1082 * @return {?}
1083 */
1084 get numberOfChildren() { return Object.keys(this.children).length; }
1085 /**
1086 * \@docsNotRequired
1087 * @return {?}
1088 */
1089 toString() { return serializePaths(this); }
1090}
1091/**
1092 * \@description
1093 *
1094 * Represents a single URL segment.
1095 *
1096 * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix
1097 * parameters associated with the segment.
1098 *
1099 * \@usageNotes
1100 *  ### Example
1101 *
1102 * ```
1103 * \@Component({templateUrl:'template.html'})
1104 * class MyComponent {
1105 * constructor(router: Router) {
1106 * const tree: UrlTree = router.parseUrl('/team;id=33');
1107 * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];
1108 * const s: UrlSegment[] = g.segments;
1109 * s[0].path; // returns 'team'
1110 * s[0].parameters; // returns {id: 33}
1111 * }
1112 * }
1113 * ```
1114 *
1115 * \@publicApi
1116 */
1117class UrlSegment {
1118 /**
1119 * @param {?} path
1120 * @param {?} parameters
1121 */
1122 constructor(path, parameters) {
1123 this.path = path;
1124 this.parameters = parameters;
1125 }
1126 /**
1127 * @return {?}
1128 */
1129 get parameterMap() {
1130 if (!this._parameterMap) {
1131 this._parameterMap = convertToParamMap(this.parameters);
1132 }
1133 return this._parameterMap;
1134 }
1135 /**
1136 * \@docsNotRequired
1137 * @return {?}
1138 */
1139 toString() { return serializePath(this); }
1140}
1141/**
1142 * @param {?} as
1143 * @param {?} bs
1144 * @return {?}
1145 */
1146function equalSegments(as, bs) {
1147 return equalPath(as, bs) && as.every((/**
1148 * @param {?} a
1149 * @param {?} i
1150 * @return {?}
1151 */
1152 (a, i) => shallowEqual(a.parameters, bs[i].parameters)));
1153}
1154/**
1155 * @param {?} as
1156 * @param {?} bs
1157 * @return {?}
1158 */
1159function equalPath(as, bs) {
1160 if (as.length !== bs.length)
1161 return false;
1162 return as.every((/**
1163 * @param {?} a
1164 * @param {?} i
1165 * @return {?}
1166 */
1167 (a, i) => a.path === bs[i].path));
1168}
1169/**
1170 * @template T
1171 * @param {?} segment
1172 * @param {?} fn
1173 * @return {?}
1174 */
1175function mapChildrenIntoArray(segment, fn) {
1176 /** @type {?} */
1177 let res = [];
1178 forEach(segment.children, (/**
1179 * @param {?} child
1180 * @param {?} childOutlet
1181 * @return {?}
1182 */
1183 (child, childOutlet) => {
1184 if (childOutlet === PRIMARY_OUTLET) {
1185 res = res.concat(fn(child, childOutlet));
1186 }
1187 }));
1188 forEach(segment.children, (/**
1189 * @param {?} child
1190 * @param {?} childOutlet
1191 * @return {?}
1192 */
1193 (child, childOutlet) => {
1194 if (childOutlet !== PRIMARY_OUTLET) {
1195 res = res.concat(fn(child, childOutlet));
1196 }
1197 }));
1198 return res;
1199}
1200/**
1201 * \@description
1202 *
1203 * Serializes and deserializes a URL string into a URL tree.
1204 *
1205 * The url serialization strategy is customizable. You can
1206 * make all URLs case insensitive by providing a custom UrlSerializer.
1207 *
1208 * See `DefaultUrlSerializer` for an example of a URL serializer.
1209 *
1210 * \@publicApi
1211 * @abstract
1212 */
1213class UrlSerializer {
1214}
1215/**
1216 * \@description
1217 *
1218 * A default implementation of the `UrlSerializer`.
1219 *
1220 * Example URLs:
1221 *
1222 * ```
1223 * /inbox/33(popup:compose)
1224 * /inbox/33;open=true/messages/44
1225 * ```
1226 *
1227 * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the
1228 * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to
1229 * specify route specific parameters.
1230 *
1231 * \@publicApi
1232 */
1233class DefaultUrlSerializer {
1234 /**
1235 * Parses a url into a `UrlTree`
1236 * @param {?} url
1237 * @return {?}
1238 */
1239 parse(url) {
1240 /** @type {?} */
1241 const p = new UrlParser(url);
1242 return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
1243 }
1244 /**
1245 * Converts a `UrlTree` into a url
1246 * @param {?} tree
1247 * @return {?}
1248 */
1249 serialize(tree) {
1250 /** @type {?} */
1251 const segment = `/${serializeSegment(tree.root, true)}`;
1252 /** @type {?} */
1253 const query = serializeQueryParams(tree.queryParams);
1254 /** @type {?} */
1255 const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment((/** @type {?} */ (tree.fragment)))}` : '';
1256 return `${segment}${query}${fragment}`;
1257 }
1258}
1259/** @type {?} */
1260const DEFAULT_SERIALIZER = new DefaultUrlSerializer();
1261/**
1262 * @param {?} segment
1263 * @return {?}
1264 */
1265function serializePaths(segment) {
1266 return segment.segments.map((/**
1267 * @param {?} p
1268 * @return {?}
1269 */
1270 p => serializePath(p))).join('/');
1271}
1272/**
1273 * @param {?} segment
1274 * @param {?} root
1275 * @return {?}
1276 */
1277function serializeSegment(segment, root) {
1278 if (!segment.hasChildren()) {
1279 return serializePaths(segment);
1280 }
1281 if (root) {
1282 /** @type {?} */
1283 const primary = segment.children[PRIMARY_OUTLET] ?
1284 serializeSegment(segment.children[PRIMARY_OUTLET], false) :
1285 '';
1286 /** @type {?} */
1287 const children = [];
1288 forEach(segment.children, (/**
1289 * @param {?} v
1290 * @param {?} k
1291 * @return {?}
1292 */
1293 (v, k) => {
1294 if (k !== PRIMARY_OUTLET) {
1295 children.push(`${k}:${serializeSegment(v, false)}`);
1296 }
1297 }));
1298 return children.length > 0 ? `${primary}(${children.join('//')})` : primary;
1299 }
1300 else {
1301 /** @type {?} */
1302 const children = mapChildrenIntoArray(segment, (/**
1303 * @param {?} v
1304 * @param {?} k
1305 * @return {?}
1306 */
1307 (v, k) => {
1308 if (k === PRIMARY_OUTLET) {
1309 return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
1310 }
1311 return [`${k}:${serializeSegment(v, false)}`];
1312 }));
1313 return `${serializePaths(segment)}/(${children.join('//')})`;
1314 }
1315}
1316/**
1317 * Encodes a URI string with the default encoding. This function will only ever be called from
1318 * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need
1319 * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't
1320 * have to be encoded per https://url.spec.whatwg.org.
1321 * @param {?} s
1322 * @return {?}
1323 */
1324function encodeUriString(s) {
1325 return encodeURIComponent(s)
1326 .replace(/%40/g, '@')
1327 .replace(/%3A/gi, ':')
1328 .replace(/%24/g, '$')
1329 .replace(/%2C/gi, ',');
1330}
1331/**
1332 * This function should be used to encode both keys and values in a query string key/value. In
1333 * the following URL, you need to call encodeUriQuery on "k" and "v":
1334 *
1335 * http://www.site.org/html;mk=mv?k=v#f
1336 * @param {?} s
1337 * @return {?}
1338 */
1339function encodeUriQuery(s) {
1340 return encodeUriString(s).replace(/%3B/gi, ';');
1341}
1342/**
1343 * This function should be used to encode a URL fragment. In the following URL, you need to call
1344 * encodeUriFragment on "f":
1345 *
1346 * http://www.site.org/html;mk=mv?k=v#f
1347 * @param {?} s
1348 * @return {?}
1349 */
1350function encodeUriFragment(s) {
1351 return encodeURI(s);
1352}
1353/**
1354 * This function should be run on any URI segment as well as the key and value in a key/value
1355 * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html",
1356 * "mk", and "mv":
1357 *
1358 * http://www.site.org/html;mk=mv?k=v#f
1359 * @param {?} s
1360 * @return {?}
1361 */
1362function encodeUriSegment(s) {
1363 return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
1364}
1365/**
1366 * @param {?} s
1367 * @return {?}
1368 */
1369function decode(s) {
1370 return decodeURIComponent(s);
1371}
1372// Query keys/values should have the "+" replaced first, as "+" in a query string is " ".
1373// decodeURIComponent function will not decode "+" as a space.
1374/**
1375 * @param {?} s
1376 * @return {?}
1377 */
1378function decodeQuery(s) {
1379 return decode(s.replace(/\+/g, '%20'));
1380}
1381/**
1382 * @param {?} path
1383 * @return {?}
1384 */
1385function serializePath(path) {
1386 return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
1387}
1388/**
1389 * @param {?} params
1390 * @return {?}
1391 */
1392function serializeMatrixParams(params) {
1393 return Object.keys(params)
1394 .map((/**
1395 * @param {?} key
1396 * @return {?}
1397 */
1398 key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`))
1399 .join('');
1400}
1401/**
1402 * @param {?} params
1403 * @return {?}
1404 */
1405function serializeQueryParams(params) {
1406 /** @type {?} */
1407 const strParams = Object.keys(params).map((/**
1408 * @param {?} name
1409 * @return {?}
1410 */
1411 (name) => {
1412 /** @type {?} */
1413 const value = params[name];
1414 return Array.isArray(value) ?
1415 value.map((/**
1416 * @param {?} v
1417 * @return {?}
1418 */
1419 v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`)).join('&') :
1420 `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
1421 }));
1422 return strParams.length ? `?${strParams.join("&")}` : '';
1423}
1424/** @type {?} */
1425const SEGMENT_RE = /^[^\/()?;=#]+/;
1426/**
1427 * @param {?} str
1428 * @return {?}
1429 */
1430function matchSegments(str) {
1431 /** @type {?} */
1432 const match = str.match(SEGMENT_RE);
1433 return match ? match[0] : '';
1434}
1435/** @type {?} */
1436const QUERY_PARAM_RE = /^[^=?&#]+/;
1437// Return the name of the query param at the start of the string or an empty string
1438/**
1439 * @param {?} str
1440 * @return {?}
1441 */
1442function matchQueryParams(str) {
1443 /** @type {?} */
1444 const match = str.match(QUERY_PARAM_RE);
1445 return match ? match[0] : '';
1446}
1447/** @type {?} */
1448const QUERY_PARAM_VALUE_RE = /^[^?&#]+/;
1449// Return the value of the query param at the start of the string or an empty string
1450/**
1451 * @param {?} str
1452 * @return {?}
1453 */
1454function matchUrlQueryParamValue(str) {
1455 /** @type {?} */
1456 const match = str.match(QUERY_PARAM_VALUE_RE);
1457 return match ? match[0] : '';
1458}
1459class UrlParser {
1460 /**
1461 * @param {?} url
1462 */
1463 constructor(url) {
1464 this.url = url;
1465 this.remaining = url;
1466 }
1467 /**
1468 * @return {?}
1469 */
1470 parseRootSegment() {
1471 this.consumeOptional('/');
1472 if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
1473 return new UrlSegmentGroup([], {});
1474 }
1475 // The root segment group never has segments
1476 return new UrlSegmentGroup([], this.parseChildren());
1477 }
1478 /**
1479 * @return {?}
1480 */
1481 parseQueryParams() {
1482 /** @type {?} */
1483 const params = {};
1484 if (this.consumeOptional('?')) {
1485 do {
1486 this.parseQueryParam(params);
1487 } while (this.consumeOptional('&'));
1488 }
1489 return params;
1490 }
1491 /**
1492 * @return {?}
1493 */
1494 parseFragment() {
1495 return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;
1496 }
1497 /**
1498 * @private
1499 * @return {?}
1500 */
1501 parseChildren() {
1502 if (this.remaining === '') {
1503 return {};
1504 }
1505 this.consumeOptional('/');
1506 /** @type {?} */
1507 const segments = [];
1508 if (!this.peekStartsWith('(')) {
1509 segments.push(this.parseSegment());
1510 }
1511 while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
1512 this.capture('/');
1513 segments.push(this.parseSegment());
1514 }
1515 /** @type {?} */
1516 let children = {};
1517 if (this.peekStartsWith('/(')) {
1518 this.capture('/');
1519 children = this.parseParens(true);
1520 }
1521 /** @type {?} */
1522 let res = {};
1523 if (this.peekStartsWith('(')) {
1524 res = this.parseParens(false);
1525 }
1526 if (segments.length > 0 || Object.keys(children).length > 0) {
1527 res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
1528 }
1529 return res;
1530 }
1531 // parse a segment with its matrix parameters
1532 // ie `name;k1=v1;k2`
1533 /**
1534 * @private
1535 * @return {?}
1536 */
1537 parseSegment() {
1538 /** @type {?} */
1539 const path = matchSegments(this.remaining);
1540 if (path === '' && this.peekStartsWith(';')) {
1541 throw new Error(`Empty path url segment cannot have parameters: '${this.remaining}'.`);
1542 }
1543 this.capture(path);
1544 return new UrlSegment(decode(path), this.parseMatrixParams());
1545 }
1546 /**
1547 * @private
1548 * @return {?}
1549 */
1550 parseMatrixParams() {
1551 /** @type {?} */
1552 const params = {};
1553 while (this.consumeOptional(';')) {
1554 this.parseParam(params);
1555 }
1556 return params;
1557 }
1558 /**
1559 * @private
1560 * @param {?} params
1561 * @return {?}
1562 */
1563 parseParam(params) {
1564 /** @type {?} */
1565 const key = matchSegments(this.remaining);
1566 if (!key) {
1567 return;
1568 }
1569 this.capture(key);
1570 /** @type {?} */
1571 let value = '';
1572 if (this.consumeOptional('=')) {
1573 /** @type {?} */
1574 const valueMatch = matchSegments(this.remaining);
1575 if (valueMatch) {
1576 value = valueMatch;
1577 this.capture(value);
1578 }
1579 }
1580 params[decode(key)] = decode(value);
1581 }
1582 // Parse a single query parameter `name[=value]`
1583 /**
1584 * @private
1585 * @param {?} params
1586 * @return {?}
1587 */
1588 parseQueryParam(params) {
1589 /** @type {?} */
1590 const key = matchQueryParams(this.remaining);
1591 if (!key) {
1592 return;
1593 }
1594 this.capture(key);
1595 /** @type {?} */
1596 let value = '';
1597 if (this.consumeOptional('=')) {
1598 /** @type {?} */
1599 const valueMatch = matchUrlQueryParamValue(this.remaining);
1600 if (valueMatch) {
1601 value = valueMatch;
1602 this.capture(value);
1603 }
1604 }
1605 /** @type {?} */
1606 const decodedKey = decodeQuery(key);
1607 /** @type {?} */
1608 const decodedVal = decodeQuery(value);
1609 if (params.hasOwnProperty(decodedKey)) {
1610 // Append to existing values
1611 /** @type {?} */
1612 let currentVal = params[decodedKey];
1613 if (!Array.isArray(currentVal)) {
1614 currentVal = [currentVal];
1615 params[decodedKey] = currentVal;
1616 }
1617 currentVal.push(decodedVal);
1618 }
1619 else {
1620 // Create a new value
1621 params[decodedKey] = decodedVal;
1622 }
1623 }
1624 // parse `(a/b//outlet_name:c/d)`
1625 /**
1626 * @private
1627 * @param {?} allowPrimary
1628 * @return {?}
1629 */
1630 parseParens(allowPrimary) {
1631 /** @type {?} */
1632 const segments = {};
1633 this.capture('(');
1634 while (!this.consumeOptional(')') && this.remaining.length > 0) {
1635 /** @type {?} */
1636 const path = matchSegments(this.remaining);
1637 /** @type {?} */
1638 const next = this.remaining[path.length];
1639 // if is is not one of these characters, then the segment was unescaped
1640 // or the group was not closed
1641 if (next !== '/' && next !== ')' && next !== ';') {
1642 throw new Error(`Cannot parse url '${this.url}'`);
1643 }
1644 /** @type {?} */
1645 let outletName = (/** @type {?} */ (undefined));
1646 if (path.indexOf(':') > -1) {
1647 outletName = path.substr(0, path.indexOf(':'));
1648 this.capture(outletName);
1649 this.capture(':');
1650 }
1651 else if (allowPrimary) {
1652 outletName = PRIMARY_OUTLET;
1653 }
1654 /** @type {?} */
1655 const children = this.parseChildren();
1656 segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] :
1657 new UrlSegmentGroup([], children);
1658 this.consumeOptional('//');
1659 }
1660 return segments;
1661 }
1662 /**
1663 * @private
1664 * @param {?} str
1665 * @return {?}
1666 */
1667 peekStartsWith(str) { return this.remaining.startsWith(str); }
1668 // Consumes the prefix when it is present and returns whether it has been consumed
1669 /**
1670 * @private
1671 * @param {?} str
1672 * @return {?}
1673 */
1674 consumeOptional(str) {
1675 if (this.peekStartsWith(str)) {
1676 this.remaining = this.remaining.substring(str.length);
1677 return true;
1678 }
1679 return false;
1680 }
1681 /**
1682 * @private
1683 * @param {?} str
1684 * @return {?}
1685 */
1686 capture(str) {
1687 if (!this.consumeOptional(str)) {
1688 throw new Error(`Expected "${str}".`);
1689 }
1690 }
1691}
1692
1693/**
1694 * @fileoverview added by tsickle
1695 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1696 */
1697/**
1698 * @license
1699 * Copyright Google Inc. All Rights Reserved.
1700 *
1701 * Use of this source code is governed by an MIT-style license that can be
1702 * found in the LICENSE file at https://angular.io/license
1703 */
1704/**
1705 * @template T
1706 */
1707class Tree {
1708 /**
1709 * @param {?} root
1710 */
1711 constructor(root) { this._root = root; }
1712 /**
1713 * @return {?}
1714 */
1715 get root() { return this._root.value; }
1716 /**
1717 * \@internal
1718 * @param {?} t
1719 * @return {?}
1720 */
1721 parent(t) {
1722 /** @type {?} */
1723 const p = this.pathFromRoot(t);
1724 return p.length > 1 ? p[p.length - 2] : null;
1725 }
1726 /**
1727 * \@internal
1728 * @param {?} t
1729 * @return {?}
1730 */
1731 children(t) {
1732 /** @type {?} */
1733 const n = findNode(t, this._root);
1734 return n ? n.children.map((/**
1735 * @param {?} t
1736 * @return {?}
1737 */
1738 t => t.value)) : [];
1739 }
1740 /**
1741 * \@internal
1742 * @param {?} t
1743 * @return {?}
1744 */
1745 firstChild(t) {
1746 /** @type {?} */
1747 const n = findNode(t, this._root);
1748 return n && n.children.length > 0 ? n.children[0].value : null;
1749 }
1750 /**
1751 * \@internal
1752 * @param {?} t
1753 * @return {?}
1754 */
1755 siblings(t) {
1756 /** @type {?} */
1757 const p = findPath(t, this._root);
1758 if (p.length < 2)
1759 return [];
1760 /** @type {?} */
1761 const c = p[p.length - 2].children.map((/**
1762 * @param {?} c
1763 * @return {?}
1764 */
1765 c => c.value));
1766 return c.filter((/**
1767 * @param {?} cc
1768 * @return {?}
1769 */
1770 cc => cc !== t));
1771 }
1772 /**
1773 * \@internal
1774 * @param {?} t
1775 * @return {?}
1776 */
1777 pathFromRoot(t) { return findPath(t, this._root).map((/**
1778 * @param {?} s
1779 * @return {?}
1780 */
1781 s => s.value)); }
1782}
1783// DFS for the node matching the value
1784/**
1785 * @template T
1786 * @param {?} value
1787 * @param {?} node
1788 * @return {?}
1789 */
1790function findNode(value, node) {
1791 if (value === node.value)
1792 return node;
1793 for (const child of node.children) {
1794 /** @type {?} */
1795 const node = findNode(value, child);
1796 if (node)
1797 return node;
1798 }
1799 return null;
1800}
1801// Return the path to the node with the given value using DFS
1802/**
1803 * @template T
1804 * @param {?} value
1805 * @param {?} node
1806 * @return {?}
1807 */
1808function findPath(value, node) {
1809 if (value === node.value)
1810 return [node];
1811 for (const child of node.children) {
1812 /** @type {?} */
1813 const path = findPath(value, child);
1814 if (path.length) {
1815 path.unshift(node);
1816 return path;
1817 }
1818 }
1819 return [];
1820}
1821/**
1822 * @template T
1823 */
1824class TreeNode {
1825 /**
1826 * @param {?} value
1827 * @param {?} children
1828 */
1829 constructor(value, children) {
1830 this.value = value;
1831 this.children = children;
1832 }
1833 /**
1834 * @return {?}
1835 */
1836 toString() { return `TreeNode(${this.value})`; }
1837}
1838// Return the list of T indexed by outlet name
1839/**
1840 * @template T
1841 * @param {?} node
1842 * @return {?}
1843 */
1844function nodeChildrenAsMap(node) {
1845 /** @type {?} */
1846 const map = {};
1847 if (node) {
1848 node.children.forEach((/**
1849 * @param {?} child
1850 * @return {?}
1851 */
1852 child => map[child.value.outlet] = child));
1853 }
1854 return map;
1855}
1856
1857/**
1858 * @fileoverview added by tsickle
1859 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1860 */
1861/**
1862 * Represents the state of the router as a tree of activated routes.
1863 *
1864 * \@usageNotes
1865 *
1866 * Every node in the route tree is an `ActivatedRoute` instance
1867 * that knows about the "consumed" URL segments, the extracted parameters,
1868 * and the resolved data.
1869 * Use the `ActivatedRoute` properties to traverse the tree from any node.
1870 *
1871 * ### Example
1872 *
1873 * ```
1874 * \@Component({templateUrl:'template.html'})
1875 * class MyComponent {
1876 * constructor(router: Router) {
1877 * const state: RouterState = router.routerState;
1878 * const root: ActivatedRoute = state.root;
1879 * const child = root.firstChild;
1880 * const id: Observable<string> = child.params.map(p => p.id);
1881 * //...
1882 * }
1883 * }
1884 * ```
1885 *
1886 * @see `ActivatedRoute`
1887 *
1888 * \@publicApi
1889 */
1890class RouterState extends Tree {
1891 /**
1892 * \@internal
1893 * @param {?} root
1894 * @param {?} snapshot
1895 */
1896 constructor(root, snapshot) {
1897 super(root);
1898 this.snapshot = snapshot;
1899 setRouterState((/** @type {?} */ (this)), root);
1900 }
1901 /**
1902 * @return {?}
1903 */
1904 toString() { return this.snapshot.toString(); }
1905}
1906/**
1907 * @param {?} urlTree
1908 * @param {?} rootComponent
1909 * @return {?}
1910 */
1911function createEmptyState(urlTree, rootComponent) {
1912 /** @type {?} */
1913 const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
1914 /** @type {?} */
1915 const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]);
1916 /** @type {?} */
1917 const emptyParams = new BehaviorSubject({});
1918 /** @type {?} */
1919 const emptyData = new BehaviorSubject({});
1920 /** @type {?} */
1921 const emptyQueryParams = new BehaviorSubject({});
1922 /** @type {?} */
1923 const fragment = new BehaviorSubject('');
1924 /** @type {?} */
1925 const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
1926 activated.snapshot = snapshot.root;
1927 return new RouterState(new TreeNode(activated, []), snapshot);
1928}
1929/**
1930 * @param {?} urlTree
1931 * @param {?} rootComponent
1932 * @return {?}
1933 */
1934function createEmptyStateSnapshot(urlTree, rootComponent) {
1935 /** @type {?} */
1936 const emptyParams = {};
1937 /** @type {?} */
1938 const emptyData = {};
1939 /** @type {?} */
1940 const emptyQueryParams = {};
1941 /** @type {?} */
1942 const fragment = '';
1943 /** @type {?} */
1944 const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {});
1945 return new RouterStateSnapshot('', new TreeNode(activated, []));
1946}
1947/**
1948 * Provides access to information about a route associated with a component
1949 * that is loaded in an outlet.
1950 * Use to traverse the `RouterState` tree and extract information from nodes.
1951 *
1952 * {\@example router/activated-route/module.ts region="activated-route"
1953 * header="activated-route.component.ts" linenums="false"}
1954 *
1955 * \@publicApi
1956 */
1957class ActivatedRoute {
1958 /**
1959 * \@internal
1960 * @param {?} url
1961 * @param {?} params
1962 * @param {?} queryParams
1963 * @param {?} fragment
1964 * @param {?} data
1965 * @param {?} outlet
1966 * @param {?} component
1967 * @param {?} futureSnapshot
1968 */
1969 constructor(url, params, queryParams, fragment, data, outlet, component, futureSnapshot) {
1970 this.url = url;
1971 this.params = params;
1972 this.queryParams = queryParams;
1973 this.fragment = fragment;
1974 this.data = data;
1975 this.outlet = outlet;
1976 this.component = component;
1977 this._futureSnapshot = futureSnapshot;
1978 }
1979 /**
1980 * The configuration used to match this route.
1981 * @return {?}
1982 */
1983 get routeConfig() { return this._futureSnapshot.routeConfig; }
1984 /**
1985 * The root of the router state.
1986 * @return {?}
1987 */
1988 get root() { return this._routerState.root; }
1989 /**
1990 * The parent of this route in the router state tree.
1991 * @return {?}
1992 */
1993 get parent() { return this._routerState.parent(this); }
1994 /**
1995 * The first child of this route in the router state tree.
1996 * @return {?}
1997 */
1998 get firstChild() { return this._routerState.firstChild(this); }
1999 /**
2000 * The children of this route in the router state tree.
2001 * @return {?}
2002 */
2003 get children() { return this._routerState.children(this); }
2004 /**
2005 * The path from the root of the router state tree to this route.
2006 * @return {?}
2007 */
2008 get pathFromRoot() { return this._routerState.pathFromRoot(this); }
2009 /**
2010 * An Observable that contains a map of the required and optional parameters
2011 * specific to the route.
2012 * The map supports retrieving single and multiple values from the same parameter.
2013 * @return {?}
2014 */
2015 get paramMap() {
2016 if (!this._paramMap) {
2017 this._paramMap = this.params.pipe(map((/**
2018 * @param {?} p
2019 * @return {?}
2020 */
2021 (p) => convertToParamMap(p))));
2022 }
2023 return this._paramMap;
2024 }
2025 /**
2026 * An Observable that contains a map of the query parameters available to all routes.
2027 * The map supports retrieving single and multiple values from the query parameter.
2028 * @return {?}
2029 */
2030 get queryParamMap() {
2031 if (!this._queryParamMap) {
2032 this._queryParamMap =
2033 this.queryParams.pipe(map((/**
2034 * @param {?} p
2035 * @return {?}
2036 */
2037 (p) => convertToParamMap(p))));
2038 }
2039 return this._queryParamMap;
2040 }
2041 /**
2042 * @return {?}
2043 */
2044 toString() {
2045 return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;
2046 }
2047}
2048/**
2049 * Returns the inherited params, data, and resolve for a given route.
2050 * By default, this only inherits values up to the nearest path-less or component-less route.
2051 * \@internal
2052 * @param {?} route
2053 * @param {?=} paramsInheritanceStrategy
2054 * @return {?}
2055 */
2056function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnly') {
2057 /** @type {?} */
2058 const pathFromRoot = route.pathFromRoot;
2059 /** @type {?} */
2060 let inheritingStartingFrom = 0;
2061 if (paramsInheritanceStrategy !== 'always') {
2062 inheritingStartingFrom = pathFromRoot.length - 1;
2063 while (inheritingStartingFrom >= 1) {
2064 /** @type {?} */
2065 const current = pathFromRoot[inheritingStartingFrom];
2066 /** @type {?} */
2067 const parent = pathFromRoot[inheritingStartingFrom - 1];
2068 // current route is an empty path => inherits its parent's params and data
2069 if (current.routeConfig && current.routeConfig.path === '') {
2070 inheritingStartingFrom--;
2071 // parent is componentless => current route should inherit its params and data
2072 }
2073 else if (!parent.component) {
2074 inheritingStartingFrom--;
2075 }
2076 else {
2077 break;
2078 }
2079 }
2080 }
2081 return flattenInherited(pathFromRoot.slice(inheritingStartingFrom));
2082}
2083/**
2084 * \@internal
2085 * @param {?} pathFromRoot
2086 * @return {?}
2087 */
2088function flattenInherited(pathFromRoot) {
2089 return pathFromRoot.reduce((/**
2090 * @param {?} res
2091 * @param {?} curr
2092 * @return {?}
2093 */
2094 (res, curr) => {
2095 /** @type {?} */
2096 const params = Object.assign({}, res.params, curr.params);
2097 /** @type {?} */
2098 const data = Object.assign({}, res.data, curr.data);
2099 /** @type {?} */
2100 const resolve = Object.assign({}, res.resolve, curr._resolvedData);
2101 return { params, data, resolve };
2102 }), (/** @type {?} */ ({ params: {}, data: {}, resolve: {} })));
2103}
2104/**
2105 * \@description
2106 *
2107 * Contains the information about a route associated with a component loaded in an
2108 * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to
2109 * traverse the router state tree.
2110 *
2111 * ```
2112 * \@Component({templateUrl:'./my-component.html'})
2113 * class MyComponent {
2114 * constructor(route: ActivatedRoute) {
2115 * const id: string = route.snapshot.params.id;
2116 * const url: string = route.snapshot.url.join('');
2117 * const user = route.snapshot.data.user;
2118 * }
2119 * }
2120 * ```
2121 *
2122 * \@publicApi
2123 */
2124class ActivatedRouteSnapshot {
2125 /**
2126 * \@internal
2127 * @param {?} url
2128 * @param {?} params
2129 * @param {?} queryParams
2130 * @param {?} fragment
2131 * @param {?} data
2132 * @param {?} outlet
2133 * @param {?} component
2134 * @param {?} routeConfig
2135 * @param {?} urlSegment
2136 * @param {?} lastPathIndex
2137 * @param {?} resolve
2138 */
2139 constructor(url, params, queryParams, fragment, data, outlet, component, routeConfig, urlSegment, lastPathIndex, resolve) {
2140 this.url = url;
2141 this.params = params;
2142 this.queryParams = queryParams;
2143 this.fragment = fragment;
2144 this.data = data;
2145 this.outlet = outlet;
2146 this.component = component;
2147 this.routeConfig = routeConfig;
2148 this._urlSegment = urlSegment;
2149 this._lastPathIndex = lastPathIndex;
2150 this._resolve = resolve;
2151 }
2152 /**
2153 * The root of the router state
2154 * @return {?}
2155 */
2156 get root() { return this._routerState.root; }
2157 /**
2158 * The parent of this route in the router state tree
2159 * @return {?}
2160 */
2161 get parent() { return this._routerState.parent(this); }
2162 /**
2163 * The first child of this route in the router state tree
2164 * @return {?}
2165 */
2166 get firstChild() { return this._routerState.firstChild(this); }
2167 /**
2168 * The children of this route in the router state tree
2169 * @return {?}
2170 */
2171 get children() { return this._routerState.children(this); }
2172 /**
2173 * The path from the root of the router state tree to this route
2174 * @return {?}
2175 */
2176 get pathFromRoot() { return this._routerState.pathFromRoot(this); }
2177 /**
2178 * @return {?}
2179 */
2180 get paramMap() {
2181 if (!this._paramMap) {
2182 this._paramMap = convertToParamMap(this.params);
2183 }
2184 return this._paramMap;
2185 }
2186 /**
2187 * @return {?}
2188 */
2189 get queryParamMap() {
2190 if (!this._queryParamMap) {
2191 this._queryParamMap = convertToParamMap(this.queryParams);
2192 }
2193 return this._queryParamMap;
2194 }
2195 /**
2196 * @return {?}
2197 */
2198 toString() {
2199 /** @type {?} */
2200 const url = this.url.map((/**
2201 * @param {?} segment
2202 * @return {?}
2203 */
2204 segment => segment.toString())).join('/');
2205 /** @type {?} */
2206 const matched = this.routeConfig ? this.routeConfig.path : '';
2207 return `Route(url:'${url}', path:'${matched}')`;
2208 }
2209}
2210/**
2211 * \@description
2212 *
2213 * Represents the state of the router at a moment in time.
2214 *
2215 * This is a tree of activated route snapshots. Every node in this tree knows about
2216 * the "consumed" URL segments, the extracted parameters, and the resolved data.
2217 *
2218 * \@usageNotes
2219 * ### Example
2220 *
2221 * ```
2222 * \@Component({templateUrl:'template.html'})
2223 * class MyComponent {
2224 * constructor(router: Router) {
2225 * const state: RouterState = router.routerState;
2226 * const snapshot: RouterStateSnapshot = state.snapshot;
2227 * const root: ActivatedRouteSnapshot = snapshot.root;
2228 * const child = root.firstChild;
2229 * const id: Observable<string> = child.params.map(p => p.id);
2230 * //...
2231 * }
2232 * }
2233 * ```
2234 *
2235 * \@publicApi
2236 */
2237class RouterStateSnapshot extends Tree {
2238 /**
2239 * \@internal
2240 * @param {?} url
2241 * @param {?} root
2242 */
2243 constructor(url, root) {
2244 super(root);
2245 this.url = url;
2246 setRouterState((/** @type {?} */ (this)), root);
2247 }
2248 /**
2249 * @return {?}
2250 */
2251 toString() { return serializeNode(this._root); }
2252}
2253/**
2254 * @template U, T
2255 * @param {?} state
2256 * @param {?} node
2257 * @return {?}
2258 */
2259function setRouterState(state, node) {
2260 node.value._routerState = state;
2261 node.children.forEach((/**
2262 * @param {?} c
2263 * @return {?}
2264 */
2265 c => setRouterState(state, c)));
2266}
2267/**
2268 * @param {?} node
2269 * @return {?}
2270 */
2271function serializeNode(node) {
2272 /** @type {?} */
2273 const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : '';
2274 return `${node.value}${c}`;
2275}
2276/**
2277 * The expectation is that the activate route is created with the right set of parameters.
2278 * So we push new values into the observables only when they are not the initial values.
2279 * And we detect that by checking if the snapshot field is set.
2280 * @param {?} route
2281 * @return {?}
2282 */
2283function advanceActivatedRoute(route) {
2284 if (route.snapshot) {
2285 /** @type {?} */
2286 const currentSnapshot = route.snapshot;
2287 /** @type {?} */
2288 const nextSnapshot = route._futureSnapshot;
2289 route.snapshot = nextSnapshot;
2290 if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
2291 ((/** @type {?} */ (route.queryParams))).next(nextSnapshot.queryParams);
2292 }
2293 if (currentSnapshot.fragment !== nextSnapshot.fragment) {
2294 ((/** @type {?} */ (route.fragment))).next(nextSnapshot.fragment);
2295 }
2296 if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
2297 ((/** @type {?} */ (route.params))).next(nextSnapshot.params);
2298 }
2299 if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
2300 ((/** @type {?} */ (route.url))).next(nextSnapshot.url);
2301 }
2302 if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
2303 ((/** @type {?} */ (route.data))).next(nextSnapshot.data);
2304 }
2305 }
2306 else {
2307 route.snapshot = route._futureSnapshot;
2308 // this is for resolved data
2309 ((/** @type {?} */ (route.data))).next(route._futureSnapshot.data);
2310 }
2311}
2312/**
2313 * @param {?} a
2314 * @param {?} b
2315 * @return {?}
2316 */
2317function equalParamsAndUrlSegments(a, b) {
2318 /** @type {?} */
2319 const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
2320 /** @type {?} */
2321 const parentsMismatch = !a.parent !== !b.parent;
2322 return equalUrlParams && !parentsMismatch &&
2323 (!a.parent || equalParamsAndUrlSegments(a.parent, (/** @type {?} */ (b.parent))));
2324}
2325
2326/**
2327 * @fileoverview added by tsickle
2328 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
2329 */
2330/**
2331 * @param {?} routeReuseStrategy
2332 * @param {?} curr
2333 * @param {?} prevState
2334 * @return {?}
2335 */
2336function createRouterState(routeReuseStrategy, curr, prevState) {
2337 /** @type {?} */
2338 const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
2339 return new RouterState(root, curr);
2340}
2341/**
2342 * @param {?} routeReuseStrategy
2343 * @param {?} curr
2344 * @param {?=} prevState
2345 * @return {?}
2346 */
2347function createNode(routeReuseStrategy, curr, prevState) {
2348 // reuse an activated route that is currently displayed on the screen
2349 if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
2350 /** @type {?} */
2351 const value = prevState.value;
2352 value._futureSnapshot = curr.value;
2353 /** @type {?} */
2354 const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
2355 return new TreeNode(value, children);
2356 // retrieve an activated route that is used to be displayed, but is not currently displayed
2357 }
2358 else {
2359 /** @type {?} */
2360 const detachedRouteHandle = (/** @type {?} */ (routeReuseStrategy.retrieve(curr.value)));
2361 if (detachedRouteHandle) {
2362 /** @type {?} */
2363 const tree = detachedRouteHandle.route;
2364 setFutureSnapshotsOfActivatedRoutes(curr, tree);
2365 return tree;
2366 }
2367 else {
2368 /** @type {?} */
2369 const value = createActivatedRoute(curr.value);
2370 /** @type {?} */
2371 const children = curr.children.map((/**
2372 * @param {?} c
2373 * @return {?}
2374 */
2375 c => createNode(routeReuseStrategy, c)));
2376 return new TreeNode(value, children);
2377 }
2378 }
2379}
2380/**
2381 * @param {?} curr
2382 * @param {?} result
2383 * @return {?}
2384 */
2385function setFutureSnapshotsOfActivatedRoutes(curr, result) {
2386 if (curr.value.routeConfig !== result.value.routeConfig) {
2387 throw new Error('Cannot reattach ActivatedRouteSnapshot created from a different route');
2388 }
2389 if (curr.children.length !== result.children.length) {
2390 throw new Error('Cannot reattach ActivatedRouteSnapshot with a different number of children');
2391 }
2392 result.value._futureSnapshot = curr.value;
2393 for (let i = 0; i < curr.children.length; ++i) {
2394 setFutureSnapshotsOfActivatedRoutes(curr.children[i], result.children[i]);
2395 }
2396}
2397/**
2398 * @param {?} routeReuseStrategy
2399 * @param {?} curr
2400 * @param {?} prevState
2401 * @return {?}
2402 */
2403function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
2404 return curr.children.map((/**
2405 * @param {?} child
2406 * @return {?}
2407 */
2408 child => {
2409 for (const p of prevState.children) {
2410 if (routeReuseStrategy.shouldReuseRoute(p.value.snapshot, child.value)) {
2411 return createNode(routeReuseStrategy, child, p);
2412 }
2413 }
2414 return createNode(routeReuseStrategy, child);
2415 }));
2416}
2417/**
2418 * @param {?} c
2419 * @return {?}
2420 */
2421function createActivatedRoute(c) {
2422 return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
2423}
2424
2425/**
2426 * @fileoverview added by tsickle
2427 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
2428 */
2429/**
2430 * @param {?} route
2431 * @param {?} urlTree
2432 * @param {?} commands
2433 * @param {?} queryParams
2434 * @param {?} fragment
2435 * @return {?}
2436 */
2437function createUrlTree(route, urlTree, commands, queryParams, fragment) {
2438 if (commands.length === 0) {
2439 return tree(urlTree.root, urlTree.root, urlTree, queryParams, fragment);
2440 }
2441 /** @type {?} */
2442 const nav = computeNavigation(commands);
2443 if (nav.toRoot()) {
2444 return tree(urlTree.root, new UrlSegmentGroup([], {}), urlTree, queryParams, fragment);
2445 }
2446 /** @type {?} */
2447 const startingPosition = findStartingPosition(nav, urlTree, route);
2448 /** @type {?} */
2449 const segmentGroup = startingPosition.processChildren ?
2450 updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) :
2451 updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);
2452 return tree(startingPosition.segmentGroup, segmentGroup, urlTree, queryParams, fragment);
2453}
2454/**
2455 * @param {?} command
2456 * @return {?}
2457 */
2458function isMatrixParams(command) {
2459 return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
2460}
2461/**
2462 * @param {?} oldSegmentGroup
2463 * @param {?} newSegmentGroup
2464 * @param {?} urlTree
2465 * @param {?} queryParams
2466 * @param {?} fragment
2467 * @return {?}
2468 */
2469function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) {
2470 /** @type {?} */
2471 let qp = {};
2472 if (queryParams) {
2473 forEach(queryParams, (/**
2474 * @param {?} value
2475 * @param {?} name
2476 * @return {?}
2477 */
2478 (value, name) => {
2479 qp[name] = Array.isArray(value) ? value.map((/**
2480 * @param {?} v
2481 * @return {?}
2482 */
2483 (v) => `${v}`)) : `${value}`;
2484 }));
2485 }
2486 if (urlTree.root === oldSegmentGroup) {
2487 return new UrlTree(newSegmentGroup, qp, fragment);
2488 }
2489 return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment);
2490}
2491/**
2492 * @param {?} current
2493 * @param {?} oldSegment
2494 * @param {?} newSegment
2495 * @return {?}
2496 */
2497function replaceSegment(current, oldSegment, newSegment) {
2498 /** @type {?} */
2499 const children = {};
2500 forEach(current.children, (/**
2501 * @param {?} c
2502 * @param {?} outletName
2503 * @return {?}
2504 */
2505 (c, outletName) => {
2506 if (c === oldSegment) {
2507 children[outletName] = newSegment;
2508 }
2509 else {
2510 children[outletName] = replaceSegment(c, oldSegment, newSegment);
2511 }
2512 }));
2513 return new UrlSegmentGroup(current.segments, children);
2514}
2515class Navigation {
2516 /**
2517 * @param {?} isAbsolute
2518 * @param {?} numberOfDoubleDots
2519 * @param {?} commands
2520 */
2521 constructor(isAbsolute, numberOfDoubleDots, commands) {
2522 this.isAbsolute = isAbsolute;
2523 this.numberOfDoubleDots = numberOfDoubleDots;
2524 this.commands = commands;
2525 if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
2526 throw new Error('Root segment cannot have matrix parameters');
2527 }
2528 /** @type {?} */
2529 const cmdWithOutlet = commands.find((/**
2530 * @param {?} c
2531 * @return {?}
2532 */
2533 c => typeof c === 'object' && c != null && c.outlets));
2534 if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
2535 throw new Error('{outlets:{}} has to be the last command');
2536 }
2537 }
2538 /**
2539 * @return {?}
2540 */
2541 toRoot() {
2542 return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
2543 }
2544}
2545/**
2546 * Transforms commands to a normalized `Navigation`
2547 * @param {?} commands
2548 * @return {?}
2549 */
2550function computeNavigation(commands) {
2551 if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') {
2552 return new Navigation(true, 0, commands);
2553 }
2554 /** @type {?} */
2555 let numberOfDoubleDots = 0;
2556 /** @type {?} */
2557 let isAbsolute = false;
2558 /** @type {?} */
2559 const res = commands.reduce((/**
2560 * @param {?} res
2561 * @param {?} cmd
2562 * @param {?} cmdIdx
2563 * @return {?}
2564 */
2565 (res, cmd, cmdIdx) => {
2566 if (typeof cmd === 'object' && cmd != null) {
2567 if (cmd.outlets) {
2568 /** @type {?} */
2569 const outlets = {};
2570 forEach(cmd.outlets, (/**
2571 * @param {?} commands
2572 * @param {?} name
2573 * @return {?}
2574 */
2575 (commands, name) => {
2576 outlets[name] = typeof commands === 'string' ? commands.split('/') : commands;
2577 }));
2578 return [...res, { outlets }];
2579 }
2580 if (cmd.segmentPath) {
2581 return [...res, cmd.segmentPath];
2582 }
2583 }
2584 if (!(typeof cmd === 'string')) {
2585 return [...res, cmd];
2586 }
2587 if (cmdIdx === 0) {
2588 cmd.split('/').forEach((/**
2589 * @param {?} urlPart
2590 * @param {?} partIndex
2591 * @return {?}
2592 */
2593 (urlPart, partIndex) => {
2594 if (partIndex == 0 && urlPart === '.') ;
2595 else if (partIndex == 0 && urlPart === '') { // '/a'
2596 isAbsolute = true;
2597 }
2598 else if (urlPart === '..') { // '../a'
2599 numberOfDoubleDots++;
2600 }
2601 else if (urlPart != '') {
2602 res.push(urlPart);
2603 }
2604 }));
2605 return res;
2606 }
2607 return [...res, cmd];
2608 }), []);
2609 return new Navigation(isAbsolute, numberOfDoubleDots, res);
2610}
2611class Position {
2612 /**
2613 * @param {?} segmentGroup
2614 * @param {?} processChildren
2615 * @param {?} index
2616 */
2617 constructor(segmentGroup, processChildren, index) {
2618 this.segmentGroup = segmentGroup;
2619 this.processChildren = processChildren;
2620 this.index = index;
2621 }
2622}
2623/**
2624 * @param {?} nav
2625 * @param {?} tree
2626 * @param {?} route
2627 * @return {?}
2628 */
2629function findStartingPosition(nav, tree, route) {
2630 if (nav.isAbsolute) {
2631 return new Position(tree.root, true, 0);
2632 }
2633 if (route.snapshot._lastPathIndex === -1) {
2634 return new Position(route.snapshot._urlSegment, true, 0);
2635 }
2636 /** @type {?} */
2637 const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
2638 /** @type {?} */
2639 const index = route.snapshot._lastPathIndex + modifier;
2640 return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots);
2641}
2642/**
2643 * @param {?} group
2644 * @param {?} index
2645 * @param {?} numberOfDoubleDots
2646 * @return {?}
2647 */
2648function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
2649 /** @type {?} */
2650 let g = group;
2651 /** @type {?} */
2652 let ci = index;
2653 /** @type {?} */
2654 let dd = numberOfDoubleDots;
2655 while (dd > ci) {
2656 dd -= ci;
2657 g = (/** @type {?} */ (g.parent));
2658 if (!g) {
2659 throw new Error('Invalid number of \'../\'');
2660 }
2661 ci = g.segments.length;
2662 }
2663 return new Position(g, false, ci - dd);
2664}
2665/**
2666 * @param {?} command
2667 * @return {?}
2668 */
2669function getPath(command) {
2670 if (typeof command === 'object' && command != null && command.outlets) {
2671 return command.outlets[PRIMARY_OUTLET];
2672 }
2673 return `${command}`;
2674}
2675/**
2676 * @param {?} commands
2677 * @return {?}
2678 */
2679function getOutlets(commands) {
2680 if (!(typeof commands[0] === 'object'))
2681 return { [PRIMARY_OUTLET]: commands };
2682 if (commands[0].outlets === undefined)
2683 return { [PRIMARY_OUTLET]: commands };
2684 return commands[0].outlets;
2685}
2686/**
2687 * @param {?} segmentGroup
2688 * @param {?} startIndex
2689 * @param {?} commands
2690 * @return {?}
2691 */
2692function updateSegmentGroup(segmentGroup, startIndex, commands) {
2693 if (!segmentGroup) {
2694 segmentGroup = new UrlSegmentGroup([], {});
2695 }
2696 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
2697 return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
2698 }
2699 /** @type {?} */
2700 const m = prefixedWith(segmentGroup, startIndex, commands);
2701 /** @type {?} */
2702 const slicedCommands = commands.slice(m.commandIndex);
2703 if (m.match && m.pathIndex < segmentGroup.segments.length) {
2704 /** @type {?} */
2705 const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
2706 g.children[PRIMARY_OUTLET] =
2707 new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
2708 return updateSegmentGroupChildren(g, 0, slicedCommands);
2709 }
2710 else if (m.match && slicedCommands.length === 0) {
2711 return new UrlSegmentGroup(segmentGroup.segments, {});
2712 }
2713 else if (m.match && !segmentGroup.hasChildren()) {
2714 return createNewSegmentGroup(segmentGroup, startIndex, commands);
2715 }
2716 else if (m.match) {
2717 return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
2718 }
2719 else {
2720 return createNewSegmentGroup(segmentGroup, startIndex, commands);
2721 }
2722}
2723/**
2724 * @param {?} segmentGroup
2725 * @param {?} startIndex
2726 * @param {?} commands
2727 * @return {?}
2728 */
2729function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
2730 if (commands.length === 0) {
2731 return new UrlSegmentGroup(segmentGroup.segments, {});
2732 }
2733 else {
2734 /** @type {?} */
2735 const outlets = getOutlets(commands);
2736 /** @type {?} */
2737 const children = {};
2738 forEach(outlets, (/**
2739 * @param {?} commands
2740 * @param {?} outlet
2741 * @return {?}
2742 */
2743 (commands, outlet) => {
2744 if (commands !== null) {
2745 children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
2746 }
2747 }));
2748 forEach(segmentGroup.children, (/**
2749 * @param {?} child
2750 * @param {?} childOutlet
2751 * @return {?}
2752 */
2753 (child, childOutlet) => {
2754 if (outlets[childOutlet] === undefined) {
2755 children[childOutlet] = child;
2756 }
2757 }));
2758 return new UrlSegmentGroup(segmentGroup.segments, children);
2759 }
2760}
2761/**
2762 * @param {?} segmentGroup
2763 * @param {?} startIndex
2764 * @param {?} commands
2765 * @return {?}
2766 */
2767function prefixedWith(segmentGroup, startIndex, commands) {
2768 /** @type {?} */
2769 let currentCommandIndex = 0;
2770 /** @type {?} */
2771 let currentPathIndex = startIndex;
2772 /** @type {?} */
2773 const noMatch = { match: false, pathIndex: 0, commandIndex: 0 };
2774 while (currentPathIndex < segmentGroup.segments.length) {
2775 if (currentCommandIndex >= commands.length)
2776 return noMatch;
2777 /** @type {?} */
2778 const path = segmentGroup.segments[currentPathIndex];
2779 /** @type {?} */
2780 const curr = getPath(commands[currentCommandIndex]);
2781 /** @type {?} */
2782 const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
2783 if (currentPathIndex > 0 && curr === undefined)
2784 break;
2785 if (curr && next && (typeof next === 'object') && next.outlets === undefined) {
2786 if (!compare(curr, next, path))
2787 return noMatch;
2788 currentCommandIndex += 2;
2789 }
2790 else {
2791 if (!compare(curr, {}, path))
2792 return noMatch;
2793 currentCommandIndex++;
2794 }
2795 currentPathIndex++;
2796 }
2797 return { match: true, pathIndex: currentPathIndex, commandIndex: currentCommandIndex };
2798}
2799/**
2800 * @param {?} segmentGroup
2801 * @param {?} startIndex
2802 * @param {?} commands
2803 * @return {?}
2804 */
2805function createNewSegmentGroup(segmentGroup, startIndex, commands) {
2806 /** @type {?} */
2807 const paths = segmentGroup.segments.slice(0, startIndex);
2808 /** @type {?} */
2809 let i = 0;
2810 while (i < commands.length) {
2811 if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) {
2812 /** @type {?} */
2813 const children = createNewSegmentChildren(commands[i].outlets);
2814 return new UrlSegmentGroup(paths, children);
2815 }
2816 // if we start with an object literal, we need to reuse the path part from the segment
2817 if (i === 0 && isMatrixParams(commands[0])) {
2818 /** @type {?} */
2819 const p = segmentGroup.segments[startIndex];
2820 paths.push(new UrlSegment(p.path, commands[0]));
2821 i++;
2822 continue;
2823 }
2824 /** @type {?} */
2825 const curr = getPath(commands[i]);
2826 /** @type {?} */
2827 const next = (i < commands.length - 1) ? commands[i + 1] : null;
2828 if (curr && next && isMatrixParams(next)) {
2829 paths.push(new UrlSegment(curr, stringify(next)));
2830 i += 2;
2831 }
2832 else {
2833 paths.push(new UrlSegment(curr, {}));
2834 i++;
2835 }
2836 }
2837 return new UrlSegmentGroup(paths, {});
2838}
2839/**
2840 * @param {?} outlets
2841 * @return {?}
2842 */
2843function createNewSegmentChildren(outlets) {
2844 /** @type {?} */
2845 const children = {};
2846 forEach(outlets, (/**
2847 * @param {?} commands
2848 * @param {?} outlet
2849 * @return {?}
2850 */
2851 (commands, outlet) => {
2852 if (commands !== null) {
2853 children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
2854 }
2855 }));
2856 return children;
2857}
2858/**
2859 * @param {?} params
2860 * @return {?}
2861 */
2862function stringify(params) {
2863 /** @type {?} */
2864 const res = {};
2865 forEach(params, (/**
2866 * @param {?} v
2867 * @param {?} k
2868 * @return {?}
2869 */
2870 (v, k) => res[k] = `${v}`));
2871 return res;
2872}
2873/**
2874 * @param {?} path
2875 * @param {?} params
2876 * @param {?} segment
2877 * @return {?}
2878 */
2879function compare(path, params, segment) {
2880 return path == segment.path && shallowEqual(params, segment.parameters);
2881}
2882
2883/**
2884 * @fileoverview added by tsickle
2885 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
2886 */
2887/** @type {?} */
2888const activateRoutes = (/**
2889 * @param {?} rootContexts
2890 * @param {?} routeReuseStrategy
2891 * @param {?} forwardEvent
2892 * @return {?}
2893 */
2894(rootContexts, routeReuseStrategy, forwardEvent) => map((/**
2895 * @param {?} t
2896 * @return {?}
2897 */
2898t => {
2899 new ActivateRoutes(routeReuseStrategy, (/** @type {?} */ (t.targetRouterState)), t.currentRouterState, forwardEvent)
2900 .activate(rootContexts);
2901 return t;
2902})));
2903class ActivateRoutes {
2904 /**
2905 * @param {?} routeReuseStrategy
2906 * @param {?} futureState
2907 * @param {?} currState
2908 * @param {?} forwardEvent
2909 */
2910 constructor(routeReuseStrategy, futureState, currState, forwardEvent) {
2911 this.routeReuseStrategy = routeReuseStrategy;
2912 this.futureState = futureState;
2913 this.currState = currState;
2914 this.forwardEvent = forwardEvent;
2915 }
2916 /**
2917 * @param {?} parentContexts
2918 * @return {?}
2919 */
2920 activate(parentContexts) {
2921 /** @type {?} */
2922 const futureRoot = this.futureState._root;
2923 /** @type {?} */
2924 const currRoot = this.currState ? this.currState._root : null;
2925 this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
2926 advanceActivatedRoute(this.futureState.root);
2927 this.activateChildRoutes(futureRoot, currRoot, parentContexts);
2928 }
2929 // De-activate the child route that are not re-used for the future state
2930 /**
2931 * @private
2932 * @param {?} futureNode
2933 * @param {?} currNode
2934 * @param {?} contexts
2935 * @return {?}
2936 */
2937 deactivateChildRoutes(futureNode, currNode, contexts) {
2938 /** @type {?} */
2939 const children = nodeChildrenAsMap(currNode);
2940 // Recurse on the routes active in the future state to de-activate deeper children
2941 futureNode.children.forEach((/**
2942 * @param {?} futureChild
2943 * @return {?}
2944 */
2945 futureChild => {
2946 /** @type {?} */
2947 const childOutletName = futureChild.value.outlet;
2948 this.deactivateRoutes(futureChild, children[childOutletName], contexts);
2949 delete children[childOutletName];
2950 }));
2951 // De-activate the routes that will not be re-used
2952 forEach(children, (/**
2953 * @param {?} v
2954 * @param {?} childName
2955 * @return {?}
2956 */
2957 (v, childName) => {
2958 this.deactivateRouteAndItsChildren(v, contexts);
2959 }));
2960 }
2961 /**
2962 * @private
2963 * @param {?} futureNode
2964 * @param {?} currNode
2965 * @param {?} parentContext
2966 * @return {?}
2967 */
2968 deactivateRoutes(futureNode, currNode, parentContext) {
2969 /** @type {?} */
2970 const future = futureNode.value;
2971 /** @type {?} */
2972 const curr = currNode ? currNode.value : null;
2973 if (future === curr) {
2974 // Reusing the node, check to see if the children need to be de-activated
2975 if (future.component) {
2976 // If we have a normal route, we need to go through an outlet.
2977 /** @type {?} */
2978 const context = parentContext.getContext(future.outlet);
2979 if (context) {
2980 this.deactivateChildRoutes(futureNode, currNode, context.children);
2981 }
2982 }
2983 else {
2984 // if we have a componentless route, we recurse but keep the same outlet map.
2985 this.deactivateChildRoutes(futureNode, currNode, parentContext);
2986 }
2987 }
2988 else {
2989 if (curr) {
2990 // Deactivate the current route which will not be re-used
2991 this.deactivateRouteAndItsChildren(currNode, parentContext);
2992 }
2993 }
2994 }
2995 /**
2996 * @private
2997 * @param {?} route
2998 * @param {?} parentContexts
2999 * @return {?}
3000 */
3001 deactivateRouteAndItsChildren(route, parentContexts) {
3002 if (this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
3003 this.detachAndStoreRouteSubtree(route, parentContexts);
3004 }
3005 else {
3006 this.deactivateRouteAndOutlet(route, parentContexts);
3007 }
3008 }
3009 /**
3010 * @private
3011 * @param {?} route
3012 * @param {?} parentContexts
3013 * @return {?}
3014 */
3015 detachAndStoreRouteSubtree(route, parentContexts) {
3016 /** @type {?} */
3017 const context = parentContexts.getContext(route.value.outlet);
3018 if (context && context.outlet) {
3019 /** @type {?} */
3020 const componentRef = context.outlet.detach();
3021 /** @type {?} */
3022 const contexts = context.children.onOutletDeactivated();
3023 this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts });
3024 }
3025 }
3026 /**
3027 * @private
3028 * @param {?} route
3029 * @param {?} parentContexts
3030 * @return {?}
3031 */
3032 deactivateRouteAndOutlet(route, parentContexts) {
3033 /** @type {?} */
3034 const context = parentContexts.getContext(route.value.outlet);
3035 if (context) {
3036 /** @type {?} */
3037 const children = nodeChildrenAsMap(route);
3038 /** @type {?} */
3039 const contexts = route.value.component ? context.children : parentContexts;
3040 forEach(children, (/**
3041 * @param {?} v
3042 * @param {?} k
3043 * @return {?}
3044 */
3045 (v, k) => this.deactivateRouteAndItsChildren(v, contexts)));
3046 if (context.outlet) {
3047 // Destroy the component
3048 context.outlet.deactivate();
3049 // Destroy the contexts for all the outlets that were in the component
3050 context.children.onOutletDeactivated();
3051 }
3052 }
3053 }
3054 /**
3055 * @private
3056 * @param {?} futureNode
3057 * @param {?} currNode
3058 * @param {?} contexts
3059 * @return {?}
3060 */
3061 activateChildRoutes(futureNode, currNode, contexts) {
3062 /** @type {?} */
3063 const children = nodeChildrenAsMap(currNode);
3064 futureNode.children.forEach((/**
3065 * @param {?} c
3066 * @return {?}
3067 */
3068 c => {
3069 this.activateRoutes(c, children[c.value.outlet], contexts);
3070 this.forwardEvent(new ActivationEnd(c.value.snapshot));
3071 }));
3072 if (futureNode.children.length) {
3073 this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
3074 }
3075 }
3076 /**
3077 * @private
3078 * @param {?} futureNode
3079 * @param {?} currNode
3080 * @param {?} parentContexts
3081 * @return {?}
3082 */
3083 activateRoutes(futureNode, currNode, parentContexts) {
3084 /** @type {?} */
3085 const future = futureNode.value;
3086 /** @type {?} */
3087 const curr = currNode ? currNode.value : null;
3088 advanceActivatedRoute(future);
3089 // reusing the node
3090 if (future === curr) {
3091 if (future.component) {
3092 // If we have a normal route, we need to go through an outlet.
3093 /** @type {?} */
3094 const context = parentContexts.getOrCreateContext(future.outlet);
3095 this.activateChildRoutes(futureNode, currNode, context.children);
3096 }
3097 else {
3098 // if we have a componentless route, we recurse but keep the same outlet map.
3099 this.activateChildRoutes(futureNode, currNode, parentContexts);
3100 }
3101 }
3102 else {
3103 if (future.component) {
3104 // if we have a normal route, we need to place the component into the outlet and recurse.
3105 /** @type {?} */
3106 const context = parentContexts.getOrCreateContext(future.outlet);
3107 if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
3108 /** @type {?} */
3109 const stored = ((/** @type {?} */ (this.routeReuseStrategy.retrieve(future.snapshot))));
3110 this.routeReuseStrategy.store(future.snapshot, null);
3111 context.children.onOutletReAttached(stored.contexts);
3112 context.attachRef = stored.componentRef;
3113 context.route = stored.route.value;
3114 if (context.outlet) {
3115 // Attach right away when the outlet has already been instantiated
3116 // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
3117 context.outlet.attach(stored.componentRef, stored.route.value);
3118 }
3119 advanceActivatedRouteNodeAndItsChildren(stored.route);
3120 }
3121 else {
3122 /** @type {?} */
3123 const config = parentLoadedConfig(future.snapshot);
3124 /** @type {?} */
3125 const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
3126 context.attachRef = null;
3127 context.route = future;
3128 context.resolver = cmpFactoryResolver;
3129 if (context.outlet) {
3130 // Activate the outlet when it has already been instantiated
3131 // Otherwise it will get activated from its `ngOnInit` when instantiated
3132 context.outlet.activateWith(future, cmpFactoryResolver);
3133 }
3134 this.activateChildRoutes(futureNode, null, context.children);
3135 }
3136 }
3137 else {
3138 // if we have a componentless route, we recurse but keep the same outlet map.
3139 this.activateChildRoutes(futureNode, null, parentContexts);
3140 }
3141 }
3142 }
3143}
3144/**
3145 * @param {?} node
3146 * @return {?}
3147 */
3148function advanceActivatedRouteNodeAndItsChildren(node) {
3149 advanceActivatedRoute(node.value);
3150 node.children.forEach(advanceActivatedRouteNodeAndItsChildren);
3151}
3152/**
3153 * @param {?} snapshot
3154 * @return {?}
3155 */
3156function parentLoadedConfig(snapshot) {
3157 for (let s = snapshot.parent; s; s = s.parent) {
3158 /** @type {?} */
3159 const route = s.routeConfig;
3160 if (route && route._loadedConfig)
3161 return route._loadedConfig;
3162 if (route && route.component)
3163 return null;
3164 }
3165 return null;
3166}
3167
3168/**
3169 * @fileoverview added by tsickle
3170 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3171 */
3172/**
3173 * Simple function check, but generic so type inference will flow. Example:
3174 *
3175 * function product(a: number, b: number) {
3176 * return a * b;
3177 * }
3178 *
3179 * if (isFunction<product>(fn)) {
3180 * return fn(1, 2);
3181 * } else {
3182 * throw "Must provide the `product` function";
3183 * }
3184 * @template T
3185 * @param {?} v
3186 * @return {?}
3187 */
3188function isFunction(v) {
3189 return typeof v === 'function';
3190}
3191/**
3192 * @param {?} v
3193 * @return {?}
3194 */
3195function isBoolean(v) {
3196 return typeof v === 'boolean';
3197}
3198/**
3199 * @param {?} v
3200 * @return {?}
3201 */
3202function isUrlTree(v) {
3203 return v instanceof UrlTree;
3204}
3205/**
3206 * @param {?} guard
3207 * @return {?}
3208 */
3209function isCanLoad(guard) {
3210 return guard && isFunction(guard.canLoad);
3211}
3212/**
3213 * @param {?} guard
3214 * @return {?}
3215 */
3216function isCanActivate(guard) {
3217 return guard && isFunction(guard.canActivate);
3218}
3219/**
3220 * @param {?} guard
3221 * @return {?}
3222 */
3223function isCanActivateChild(guard) {
3224 return guard && isFunction(guard.canActivateChild);
3225}
3226/**
3227 * @template T
3228 * @param {?} guard
3229 * @return {?}
3230 */
3231function isCanDeactivate(guard) {
3232 return guard && isFunction(guard.canDeactivate);
3233}
3234
3235/**
3236 * @fileoverview added by tsickle
3237 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
3238 */
3239class NoMatch {
3240 /**
3241 * @param {?=} segmentGroup
3242 */
3243 constructor(segmentGroup) { this.segmentGroup = segmentGroup || null; }
3244}
3245class AbsoluteRedirect {
3246 /**
3247 * @param {?} urlTree
3248 */
3249 constructor(urlTree) {
3250 this.urlTree = urlTree;
3251 }
3252}
3253/**
3254 * @param {?} segmentGroup
3255 * @return {?}
3256 */
3257function noMatch(segmentGroup) {
3258 return new Observable((/**
3259 * @param {?} obs
3260 * @return {?}
3261 */
3262 (obs) => obs.error(new NoMatch(segmentGroup))));
3263}
3264/**
3265 * @param {?} newTree
3266 * @return {?}
3267 */
3268function absoluteRedirect(newTree) {
3269 return new Observable((/**
3270 * @param {?} obs
3271 * @return {?}
3272 */
3273 (obs) => obs.error(new AbsoluteRedirect(newTree))));
3274}
3275/**
3276 * @param {?} redirectTo
3277 * @return {?}
3278 */
3279function namedOutletsRedirect(redirectTo) {
3280 return new Observable((/**
3281 * @param {?} obs
3282 * @return {?}
3283 */
3284 (obs) => obs.error(new Error(`Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`))));
3285}
3286/**
3287 * @param {?} route
3288 * @return {?}
3289 */
3290function canLoadFails(route) {
3291 return new Observable((/**
3292 * @param {?} obs
3293 * @return {?}
3294 */
3295 (obs) => obs.error(navigationCancelingError(`Cannot load children because the guard of the route "path: '${route.path}'" returned false`))));
3296}
3297/**
3298 * Returns the `UrlTree` with the redirection applied.
3299 *
3300 * Lazy modules are loaded along the way.
3301 * @param {?} moduleInjector
3302 * @param {?} configLoader
3303 * @param {?} urlSerializer
3304 * @param {?} urlTree
3305 * @param {?} config
3306 * @return {?}
3307 */
3308function applyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config) {
3309 return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply();
3310}
3311class ApplyRedirects {
3312 /**
3313 * @param {?} moduleInjector
3314 * @param {?} configLoader
3315 * @param {?} urlSerializer
3316 * @param {?} urlTree
3317 * @param {?} config
3318 */
3319 constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) {
3320 this.configLoader = configLoader;
3321 this.urlSerializer = urlSerializer;
3322 this.urlTree = urlTree;
3323 this.config = config;
3324 this.allowRedirects = true;
3325 this.ngModule = moduleInjector.get(NgModuleRef);
3326 }
3327 /**
3328 * @return {?}
3329 */
3330 apply() {
3331 /** @type {?} */
3332 const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET);
3333 /** @type {?} */
3334 const urlTrees$ = expanded$.pipe(map((/**
3335 * @param {?} rootSegmentGroup
3336 * @return {?}
3337 */
3338 (rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, this.urlTree.queryParams, (/** @type {?} */ (this.urlTree.fragment))))));
3339 return urlTrees$.pipe(catchError((/**
3340 * @param {?} e
3341 * @return {?}
3342 */
3343 (e) => {
3344 if (e instanceof AbsoluteRedirect) {
3345 // after an absolute redirect we do not apply any more redirects!
3346 this.allowRedirects = false;
3347 // we need to run matching, so we can fetch all lazy-loaded modules
3348 return this.match(e.urlTree);
3349 }
3350 if (e instanceof NoMatch) {
3351 throw this.noMatchError(e);
3352 }
3353 throw e;
3354 })));
3355 }
3356 /**
3357 * @private
3358 * @param {?} tree
3359 * @return {?}
3360 */
3361 match(tree) {
3362 /** @type {?} */
3363 const expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
3364 /** @type {?} */
3365 const mapped$ = expanded$.pipe(map((/**
3366 * @param {?} rootSegmentGroup
3367 * @return {?}
3368 */
3369 (rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, tree.queryParams, (/** @type {?} */ (tree.fragment))))));
3370 return mapped$.pipe(catchError((/**
3371 * @param {?} e
3372 * @return {?}
3373 */
3374 (e) => {
3375 if (e instanceof NoMatch) {
3376 throw this.noMatchError(e);
3377 }
3378 throw e;
3379 })));
3380 }
3381 /**
3382 * @private
3383 * @param {?} e
3384 * @return {?}
3385 */
3386 noMatchError(e) {
3387 return new Error(`Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
3388 }
3389 /**
3390 * @private
3391 * @param {?} rootCandidate
3392 * @param {?} queryParams
3393 * @param {?} fragment
3394 * @return {?}
3395 */
3396 createUrlTree(rootCandidate, queryParams, fragment) {
3397 /** @type {?} */
3398 const root = rootCandidate.segments.length > 0 ?
3399 new UrlSegmentGroup([], { [PRIMARY_OUTLET]: rootCandidate }) :
3400 rootCandidate;
3401 return new UrlTree(root, queryParams, fragment);
3402 }
3403 /**
3404 * @private
3405 * @param {?} ngModule
3406 * @param {?} routes
3407 * @param {?} segmentGroup
3408 * @param {?} outlet
3409 * @return {?}
3410 */
3411 expandSegmentGroup(ngModule, routes, segmentGroup, outlet) {
3412 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
3413 return this.expandChildren(ngModule, routes, segmentGroup)
3414 .pipe(map((/**
3415 * @param {?} children
3416 * @return {?}
3417 */
3418 (children) => new UrlSegmentGroup([], children))));
3419 }
3420 return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true);
3421 }
3422 // Recursively expand segment groups for all the child outlets
3423 /**
3424 * @private
3425 * @param {?} ngModule
3426 * @param {?} routes
3427 * @param {?} segmentGroup
3428 * @return {?}
3429 */
3430 expandChildren(ngModule, routes, segmentGroup) {
3431 return waitForMap(segmentGroup.children, (/**
3432 * @param {?} childOutlet
3433 * @param {?} child
3434 * @return {?}
3435 */
3436 (childOutlet, child) => this.expandSegmentGroup(ngModule, routes, child, childOutlet)));
3437 }
3438 /**
3439 * @private
3440 * @param {?} ngModule
3441 * @param {?} segmentGroup
3442 * @param {?} routes
3443 * @param {?} segments
3444 * @param {?} outlet
3445 * @param {?} allowRedirects
3446 * @return {?}
3447 */
3448 expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) {
3449 return of(...routes).pipe(map((/**
3450 * @param {?} r
3451 * @return {?}
3452 */
3453 (r) => {
3454 /** @type {?} */
3455 const expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects);
3456 return expanded$.pipe(catchError((/**
3457 * @param {?} e
3458 * @return {?}
3459 */
3460 (e) => {
3461 if (e instanceof NoMatch) {
3462 // TODO(i): this return type doesn't match the declared Observable<UrlSegmentGroup> -
3463 // talk to Jason
3464 return (/** @type {?} */ (of(null)));
3465 }
3466 throw e;
3467 })));
3468 })), concatAll(), first((/**
3469 * @param {?} s
3470 * @return {?}
3471 */
3472 (s) => !!s)), catchError((/**
3473 * @param {?} e
3474 * @param {?} _
3475 * @return {?}
3476 */
3477 (e, _) => {
3478 if (e instanceof EmptyError || e.name === 'EmptyError') {
3479 if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
3480 return of(new UrlSegmentGroup([], {}));
3481 }
3482 throw new NoMatch(segmentGroup);
3483 }
3484 throw e;
3485 })));
3486 }
3487 /**
3488 * @private
3489 * @param {?} segmentGroup
3490 * @param {?} segments
3491 * @param {?} outlet
3492 * @return {?}
3493 */
3494 noLeftoversInUrl(segmentGroup, segments, outlet) {
3495 return segments.length === 0 && !segmentGroup.children[outlet];
3496 }
3497 /**
3498 * @private
3499 * @param {?} ngModule
3500 * @param {?} segmentGroup
3501 * @param {?} routes
3502 * @param {?} route
3503 * @param {?} paths
3504 * @param {?} outlet
3505 * @param {?} allowRedirects
3506 * @return {?}
3507 */
3508 expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) {
3509 if (getOutlet(route) !== outlet) {
3510 return noMatch(segmentGroup);
3511 }
3512 if (route.redirectTo === undefined) {
3513 return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths);
3514 }
3515 if (allowRedirects && this.allowRedirects) {
3516 return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet);
3517 }
3518 return noMatch(segmentGroup);
3519 }
3520 /**
3521 * @private
3522 * @param {?} ngModule
3523 * @param {?} segmentGroup
3524 * @param {?} routes
3525 * @param {?} route
3526 * @param {?} segments
3527 * @param {?} outlet
3528 * @return {?}
3529 */
3530 expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3531 if (route.path === '**') {
3532 return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet);
3533 }
3534 return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet);
3535 }
3536 /**
3537 * @private
3538 * @param {?} ngModule
3539 * @param {?} routes
3540 * @param {?} route
3541 * @param {?} outlet
3542 * @return {?}
3543 */
3544 expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) {
3545 /** @type {?} */
3546 const newTree = this.applyRedirectCommands([], (/** @type {?} */ (route.redirectTo)), {});
3547 if ((/** @type {?} */ (route.redirectTo)).startsWith('/')) {
3548 return absoluteRedirect(newTree);
3549 }
3550 return this.lineralizeSegments(route, newTree).pipe(mergeMap((/**
3551 * @param {?} newSegments
3552 * @return {?}
3553 */
3554 (newSegments) => {
3555 /** @type {?} */
3556 const group = new UrlSegmentGroup(newSegments, {});
3557 return this.expandSegment(ngModule, group, routes, newSegments, outlet, false);
3558 })));
3559 }
3560 /**
3561 * @private
3562 * @param {?} ngModule
3563 * @param {?} segmentGroup
3564 * @param {?} routes
3565 * @param {?} route
3566 * @param {?} segments
3567 * @param {?} outlet
3568 * @return {?}
3569 */
3570 expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) {
3571 const { matched, consumedSegments, lastChild, positionalParamSegments } = match(segmentGroup, route, segments);
3572 if (!matched)
3573 return noMatch(segmentGroup);
3574 /** @type {?} */
3575 const newTree = this.applyRedirectCommands(consumedSegments, (/** @type {?} */ (route.redirectTo)), (/** @type {?} */ (positionalParamSegments)));
3576 if ((/** @type {?} */ (route.redirectTo)).startsWith('/')) {
3577 return absoluteRedirect(newTree);
3578 }
3579 return this.lineralizeSegments(route, newTree).pipe(mergeMap((/**
3580 * @param {?} newSegments
3581 * @return {?}
3582 */
3583 (newSegments) => {
3584 return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(segments.slice(lastChild)), outlet, false);
3585 })));
3586 }
3587 /**
3588 * @private
3589 * @param {?} ngModule
3590 * @param {?} rawSegmentGroup
3591 * @param {?} route
3592 * @param {?} segments
3593 * @return {?}
3594 */
3595 matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments) {
3596 if (route.path === '**') {
3597 if (route.loadChildren) {
3598 return this.configLoader.load(ngModule.injector, route)
3599 .pipe(map((/**
3600 * @param {?} cfg
3601 * @return {?}
3602 */
3603 (cfg) => {
3604 route._loadedConfig = cfg;
3605 return new UrlSegmentGroup(segments, {});
3606 })));
3607 }
3608 return of(new UrlSegmentGroup(segments, {}));
3609 }
3610 const { matched, consumedSegments, lastChild } = match(rawSegmentGroup, route, segments);
3611 if (!matched)
3612 return noMatch(rawSegmentGroup);
3613 /** @type {?} */
3614 const rawSlicedSegments = segments.slice(lastChild);
3615 /** @type {?} */
3616 const childConfig$ = this.getChildConfig(ngModule, route, segments);
3617 return childConfig$.pipe(mergeMap((/**
3618 * @param {?} routerConfig
3619 * @return {?}
3620 */
3621 (routerConfig) => {
3622 /** @type {?} */
3623 const childModule = routerConfig.module;
3624 /** @type {?} */
3625 const childConfig = routerConfig.routes;
3626 const { segmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, rawSlicedSegments, childConfig);
3627 if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3628 /** @type {?} */
3629 const expanded$ = this.expandChildren(childModule, childConfig, segmentGroup);
3630 return expanded$.pipe(map((/**
3631 * @param {?} children
3632 * @return {?}
3633 */
3634 (children) => new UrlSegmentGroup(consumedSegments, children))));
3635 }
3636 if (childConfig.length === 0 && slicedSegments.length === 0) {
3637 return of(new UrlSegmentGroup(consumedSegments, {}));
3638 }
3639 /** @type {?} */
3640 const expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, PRIMARY_OUTLET, true);
3641 return expanded$.pipe(map((/**
3642 * @param {?} cs
3643 * @return {?}
3644 */
3645 (cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children))));
3646 })));
3647 }
3648 /**
3649 * @private
3650 * @param {?} ngModule
3651 * @param {?} route
3652 * @param {?} segments
3653 * @return {?}
3654 */
3655 getChildConfig(ngModule, route, segments) {
3656 if (route.children) {
3657 // The children belong to the same module
3658 return of(new LoadedRouterConfig(route.children, ngModule));
3659 }
3660 if (route.loadChildren) {
3661 // lazy children belong to the loaded module
3662 if (route._loadedConfig !== undefined) {
3663 return of(route._loadedConfig);
3664 }
3665 return runCanLoadGuard(ngModule.injector, route, segments)
3666 .pipe(mergeMap((/**
3667 * @param {?} shouldLoad
3668 * @return {?}
3669 */
3670 (shouldLoad) => {
3671 if (shouldLoad) {
3672 return this.configLoader.load(ngModule.injector, route)
3673 .pipe(map((/**
3674 * @param {?} cfg
3675 * @return {?}
3676 */
3677 (cfg) => {
3678 route._loadedConfig = cfg;
3679 return cfg;
3680 })));
3681 }
3682 return canLoadFails(route);
3683 })));
3684 }
3685 return of(new LoadedRouterConfig([], ngModule));
3686 }
3687 /**
3688 * @private
3689 * @param {?} route
3690 * @param {?} urlTree
3691 * @return {?}
3692 */
3693 lineralizeSegments(route, urlTree) {
3694 /** @type {?} */
3695 let res = [];
3696 /** @type {?} */
3697 let c = urlTree.root;
3698 while (true) {
3699 res = res.concat(c.segments);
3700 if (c.numberOfChildren === 0) {
3701 return of(res);
3702 }
3703 if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
3704 return namedOutletsRedirect((/** @type {?} */ (route.redirectTo)));
3705 }
3706 c = c.children[PRIMARY_OUTLET];
3707 }
3708 }
3709 /**
3710 * @private
3711 * @param {?} segments
3712 * @param {?} redirectTo
3713 * @param {?} posParams
3714 * @return {?}
3715 */
3716 applyRedirectCommands(segments, redirectTo, posParams) {
3717 return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3718 }
3719 /**
3720 * @private
3721 * @param {?} redirectTo
3722 * @param {?} urlTree
3723 * @param {?} segments
3724 * @param {?} posParams
3725 * @return {?}
3726 */
3727 applyRedirectCreatreUrlTree(redirectTo, urlTree, segments, posParams) {
3728 /** @type {?} */
3729 const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
3730 return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
3731 }
3732 /**
3733 * @private
3734 * @param {?} redirectToParams
3735 * @param {?} actualParams
3736 * @return {?}
3737 */
3738 createQueryParams(redirectToParams, actualParams) {
3739 /** @type {?} */
3740 const res = {};
3741 forEach(redirectToParams, (/**
3742 * @param {?} v
3743 * @param {?} k
3744 * @return {?}
3745 */
3746 (v, k) => {
3747 /** @type {?} */
3748 const copySourceValue = typeof v === 'string' && v.startsWith(':');
3749 if (copySourceValue) {
3750 /** @type {?} */
3751 const sourceName = v.substring(1);
3752 res[k] = actualParams[sourceName];
3753 }
3754 else {
3755 res[k] = v;
3756 }
3757 }));
3758 return res;
3759 }
3760 /**
3761 * @private
3762 * @param {?} redirectTo
3763 * @param {?} group
3764 * @param {?} segments
3765 * @param {?} posParams
3766 * @return {?}
3767 */
3768 createSegmentGroup(redirectTo, group, segments, posParams) {
3769 /** @type {?} */
3770 const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
3771 /** @type {?} */
3772 let children = {};
3773 forEach(group.children, (/**
3774 * @param {?} child
3775 * @param {?} name
3776 * @return {?}
3777 */
3778 (child, name) => {
3779 children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
3780 }));
3781 return new UrlSegmentGroup(updatedSegments, children);
3782 }
3783 /**
3784 * @private
3785 * @param {?} redirectTo
3786 * @param {?} redirectToSegments
3787 * @param {?} actualSegments
3788 * @param {?} posParams
3789 * @return {?}
3790 */
3791 createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
3792 return redirectToSegments.map((/**
3793 * @param {?} s
3794 * @return {?}
3795 */
3796 s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) :
3797 this.findOrReturn(s, actualSegments)));
3798 }
3799 /**
3800 * @private
3801 * @param {?} redirectTo
3802 * @param {?} redirectToUrlSegment
3803 * @param {?} posParams
3804 * @return {?}
3805 */
3806 findPosParam(redirectTo, redirectToUrlSegment, posParams) {
3807 /** @type {?} */
3808 const pos = posParams[redirectToUrlSegment.path.substring(1)];
3809 if (!pos)
3810 throw new Error(`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
3811 return pos;
3812 }
3813 /**
3814 * @private
3815 * @param {?} redirectToUrlSegment
3816 * @param {?} actualSegments
3817 * @return {?}
3818 */
3819 findOrReturn(redirectToUrlSegment, actualSegments) {
3820 /** @type {?} */
3821 let idx = 0;
3822 for (const s of actualSegments) {
3823 if (s.path === redirectToUrlSegment.path) {
3824 actualSegments.splice(idx);
3825 return s;
3826 }
3827 idx++;
3828 }
3829 return redirectToUrlSegment;
3830 }
3831}
3832/**
3833 * @param {?} moduleInjector
3834 * @param {?} route
3835 * @param {?} segments
3836 * @return {?}
3837 */
3838function runCanLoadGuard(moduleInjector, route, segments) {
3839 /** @type {?} */
3840 const canLoad = route.canLoad;
3841 if (!canLoad || canLoad.length === 0)
3842 return of(true);
3843 /** @type {?} */
3844 const obs = from(canLoad).pipe(map((/**
3845 * @param {?} injectionToken
3846 * @return {?}
3847 */
3848 (injectionToken) => {
3849 /** @type {?} */
3850 const guard = moduleInjector.get(injectionToken);
3851 /** @type {?} */
3852 let guardVal;
3853 if (isCanLoad(guard)) {
3854 guardVal = guard.canLoad(route, segments);
3855 }
3856 else if (isFunction(guard)) {
3857 guardVal = guard(route, segments);
3858 }
3859 else {
3860 throw new Error('Invalid CanLoad guard');
3861 }
3862 return wrapIntoObservable(guardVal);
3863 })));
3864 return obs.pipe(concatAll(), every((/**
3865 * @param {?} result
3866 * @return {?}
3867 */
3868 result => result === true)));
3869}
3870/**
3871 * @param {?} segmentGroup
3872 * @param {?} route
3873 * @param {?} segments
3874 * @return {?}
3875 */
3876function match(segmentGroup, route, segments) {
3877 if (route.path === '') {
3878 if ((route.pathMatch === 'full') && (segmentGroup.hasChildren() || segments.length > 0)) {
3879 return { matched: false, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
3880 }
3881 return { matched: true, consumedSegments: [], lastChild: 0, positionalParamSegments: {} };
3882 }
3883 /** @type {?} */
3884 const matcher = route.matcher || defaultUrlMatcher;
3885 /** @type {?} */
3886 const res = matcher(segments, segmentGroup, route);
3887 if (!res) {
3888 return {
3889 matched: false,
3890 consumedSegments: (/** @type {?} */ ([])),
3891 lastChild: 0,
3892 positionalParamSegments: {},
3893 };
3894 }
3895 return {
3896 matched: true,
3897 consumedSegments: (/** @type {?} */ (res.consumed)),
3898 lastChild: (/** @type {?} */ (res.consumed.length)),
3899 positionalParamSegments: (/** @type {?} */ (res.posParams)),
3900 };
3901}
3902/**
3903 * @param {?} segmentGroup
3904 * @param {?} consumedSegments
3905 * @param {?} slicedSegments
3906 * @param {?} config
3907 * @return {?}
3908 */
3909function split(segmentGroup, consumedSegments, slicedSegments, config) {
3910 if (slicedSegments.length > 0 &&
3911 containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, slicedSegments, config)) {
3912 /** @type {?} */
3913 const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptySegments(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
3914 return { segmentGroup: mergeTrivialChildren(s), slicedSegments: [] };
3915 }
3916 if (slicedSegments.length === 0 &&
3917 containsEmptyPathRedirects(segmentGroup, slicedSegments, config)) {
3918 /** @type {?} */
3919 const s = new UrlSegmentGroup(segmentGroup.segments, addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children));
3920 return { segmentGroup: mergeTrivialChildren(s), slicedSegments };
3921 }
3922 return { segmentGroup, slicedSegments };
3923}
3924/**
3925 * @param {?} s
3926 * @return {?}
3927 */
3928function mergeTrivialChildren(s) {
3929 if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
3930 /** @type {?} */
3931 const c = s.children[PRIMARY_OUTLET];
3932 return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
3933 }
3934 return s;
3935}
3936/**
3937 * @param {?} segmentGroup
3938 * @param {?} slicedSegments
3939 * @param {?} routes
3940 * @param {?} children
3941 * @return {?}
3942 */
3943function addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) {
3944 /** @type {?} */
3945 const res = {};
3946 for (const r of routes) {
3947 if (isEmptyPathRedirect(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
3948 res[getOutlet(r)] = new UrlSegmentGroup([], {});
3949 }
3950 }
3951 return Object.assign({}, children, res);
3952}
3953/**
3954 * @param {?} routes
3955 * @param {?} primarySegmentGroup
3956 * @return {?}
3957 */
3958function createChildrenForEmptySegments(routes, primarySegmentGroup) {
3959 /** @type {?} */
3960 const res = {};
3961 res[PRIMARY_OUTLET] = primarySegmentGroup;
3962 for (const r of routes) {
3963 if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
3964 res[getOutlet(r)] = new UrlSegmentGroup([], {});
3965 }
3966 }
3967 return res;
3968}
3969/**
3970 * @param {?} segmentGroup
3971 * @param {?} segments
3972 * @param {?} routes
3973 * @return {?}
3974 */
3975function containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, segments, routes) {
3976 return routes.some((/**
3977 * @param {?} r
3978 * @return {?}
3979 */
3980 r => isEmptyPathRedirect(segmentGroup, segments, r) && getOutlet(r) !== PRIMARY_OUTLET));
3981}
3982/**
3983 * @param {?} segmentGroup
3984 * @param {?} segments
3985 * @param {?} routes
3986 * @return {?}
3987 */
3988function containsEmptyPathRedirects(segmentGroup, segments, routes) {
3989 return routes.some((/**
3990 * @param {?} r
3991 * @return {?}
3992 */
3993 r => isEmptyPathRedirect(segmentGroup, segments, r)));
3994}
3995/**
3996 * @param {?} segmentGroup
3997 * @param {?} segments
3998 * @param {?} r
3999 * @return {?}
4000 */
4001function isEmptyPathRedirect(segmentGroup, segments, r) {
4002 if ((segmentGroup.hasChildren() || segments.length > 0) && r.pathMatch === 'full') {
4003 return false;
4004 }
4005 return r.path === '' && r.redirectTo !== undefined;
4006}
4007/**
4008 * @param {?} route
4009 * @return {?}
4010 */
4011function getOutlet(route) {
4012 return route.outlet || PRIMARY_OUTLET;
4013}
4014
4015/**
4016 * @fileoverview added by tsickle
4017 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4018 */
4019/**
4020 * @param {?} moduleInjector
4021 * @param {?} configLoader
4022 * @param {?} urlSerializer
4023 * @param {?} config
4024 * @return {?}
4025 */
4026function applyRedirects$1(moduleInjector, configLoader, urlSerializer, config) {
4027 return (/**
4028 * @param {?} source
4029 * @return {?}
4030 */
4031 function (source) {
4032 return source.pipe(switchMap((/**
4033 * @param {?} t
4034 * @return {?}
4035 */
4036 t => applyRedirects(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
4037 .pipe(map((/**
4038 * @param {?} urlAfterRedirects
4039 * @return {?}
4040 */
4041 urlAfterRedirects => (Object.assign({}, t, { urlAfterRedirects }))))))));
4042 });
4043}
4044
4045/**
4046 * @fileoverview added by tsickle
4047 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4048 */
4049class CanActivate {
4050 /**
4051 * @param {?} path
4052 */
4053 constructor(path) {
4054 this.path = path;
4055 this.route = this.path[this.path.length - 1];
4056 }
4057}
4058class CanDeactivate {
4059 /**
4060 * @param {?} component
4061 * @param {?} route
4062 */
4063 constructor(component, route) {
4064 this.component = component;
4065 this.route = route;
4066 }
4067}
4068/**
4069 * @param {?} future
4070 * @param {?} curr
4071 * @param {?} parentContexts
4072 * @return {?}
4073 */
4074function getAllRouteGuards(future, curr, parentContexts) {
4075 /** @type {?} */
4076 const futureRoot = future._root;
4077 /** @type {?} */
4078 const currRoot = curr ? curr._root : null;
4079 return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
4080}
4081/**
4082 * @param {?} p
4083 * @return {?}
4084 */
4085function getCanActivateChild(p) {
4086 /** @type {?} */
4087 const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
4088 if (!canActivateChild || canActivateChild.length === 0)
4089 return null;
4090 return { node: p, guards: canActivateChild };
4091}
4092/**
4093 * @param {?} token
4094 * @param {?} snapshot
4095 * @param {?} moduleInjector
4096 * @return {?}
4097 */
4098function getToken(token, snapshot, moduleInjector) {
4099 /** @type {?} */
4100 const config = getClosestLoadedConfig(snapshot);
4101 /** @type {?} */
4102 const injector = config ? config.module.injector : moduleInjector;
4103 return injector.get(token);
4104}
4105/**
4106 * @param {?} snapshot
4107 * @return {?}
4108 */
4109function getClosestLoadedConfig(snapshot) {
4110 if (!snapshot)
4111 return null;
4112 for (let s = snapshot.parent; s; s = s.parent) {
4113 /** @type {?} */
4114 const route = s.routeConfig;
4115 if (route && route._loadedConfig)
4116 return route._loadedConfig;
4117 }
4118 return null;
4119}
4120/**
4121 * @param {?} futureNode
4122 * @param {?} currNode
4123 * @param {?} contexts
4124 * @param {?} futurePath
4125 * @param {?=} checks
4126 * @return {?}
4127 */
4128function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
4129 canDeactivateChecks: [],
4130 canActivateChecks: []
4131}) {
4132 /** @type {?} */
4133 const prevChildren = nodeChildrenAsMap(currNode);
4134 // Process the children of the future route
4135 futureNode.children.forEach((/**
4136 * @param {?} c
4137 * @return {?}
4138 */
4139 c => {
4140 getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
4141 delete prevChildren[c.value.outlet];
4142 }));
4143 // Process any children left from the current route (not active for the future route)
4144 forEach(prevChildren, (/**
4145 * @param {?} v
4146 * @param {?} k
4147 * @return {?}
4148 */
4149 (v, k) => deactivateRouteAndItsChildren(v, (/** @type {?} */ (contexts)).getContext(k), checks)));
4150 return checks;
4151}
4152/**
4153 * @param {?} futureNode
4154 * @param {?} currNode
4155 * @param {?} parentContexts
4156 * @param {?} futurePath
4157 * @param {?=} checks
4158 * @return {?}
4159 */
4160function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
4161 canDeactivateChecks: [],
4162 canActivateChecks: []
4163}) {
4164 /** @type {?} */
4165 const future = futureNode.value;
4166 /** @type {?} */
4167 const curr = currNode ? currNode.value : null;
4168 /** @type {?} */
4169 const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
4170 // reusing the node
4171 if (curr && future.routeConfig === curr.routeConfig) {
4172 /** @type {?} */
4173 const shouldRun = shouldRunGuardsAndResolvers(curr, future, (/** @type {?} */ (future.routeConfig)).runGuardsAndResolvers);
4174 if (shouldRun) {
4175 checks.canActivateChecks.push(new CanActivate(futurePath));
4176 }
4177 else {
4178 // we need to set the data
4179 future.data = curr.data;
4180 future._resolvedData = curr._resolvedData;
4181 }
4182 // If we have a component, we need to go through an outlet.
4183 if (future.component) {
4184 getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
4185 // if we have a componentless route, we recurse but keep the same outlet map.
4186 }
4187 else {
4188 getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
4189 }
4190 if (shouldRun) {
4191 /** @type {?} */
4192 const component = context && context.outlet && context.outlet.component || null;
4193 checks.canDeactivateChecks.push(new CanDeactivate(component, curr));
4194 }
4195 }
4196 else {
4197 if (curr) {
4198 deactivateRouteAndItsChildren(currNode, context, checks);
4199 }
4200 checks.canActivateChecks.push(new CanActivate(futurePath));
4201 // If we have a component, we need to go through an outlet.
4202 if (future.component) {
4203 getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
4204 // if we have a componentless route, we recurse but keep the same outlet map.
4205 }
4206 else {
4207 getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
4208 }
4209 }
4210 return checks;
4211}
4212/**
4213 * @param {?} curr
4214 * @param {?} future
4215 * @param {?} mode
4216 * @return {?}
4217 */
4218function shouldRunGuardsAndResolvers(curr, future, mode) {
4219 if (typeof mode === 'function') {
4220 return mode(curr, future);
4221 }
4222 switch (mode) {
4223 case 'pathParamsChange':
4224 return !equalPath(curr.url, future.url);
4225 case 'pathParamsOrQueryParamsChange':
4226 return !equalPath(curr.url, future.url) ||
4227 !shallowEqual(curr.queryParams, future.queryParams);
4228 case 'always':
4229 return true;
4230 case 'paramsOrQueryParamsChange':
4231 return !equalParamsAndUrlSegments(curr, future) ||
4232 !shallowEqual(curr.queryParams, future.queryParams);
4233 case 'paramsChange':
4234 default:
4235 return !equalParamsAndUrlSegments(curr, future);
4236 }
4237}
4238/**
4239 * @param {?} route
4240 * @param {?} context
4241 * @param {?} checks
4242 * @return {?}
4243 */
4244function deactivateRouteAndItsChildren(route, context, checks) {
4245 /** @type {?} */
4246 const children = nodeChildrenAsMap(route);
4247 /** @type {?} */
4248 const r = route.value;
4249 forEach(children, (/**
4250 * @param {?} node
4251 * @param {?} childName
4252 * @return {?}
4253 */
4254 (node, childName) => {
4255 if (!r.component) {
4256 deactivateRouteAndItsChildren(node, context, checks);
4257 }
4258 else if (context) {
4259 deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
4260 }
4261 else {
4262 deactivateRouteAndItsChildren(node, null, checks);
4263 }
4264 }));
4265 if (!r.component) {
4266 checks.canDeactivateChecks.push(new CanDeactivate(null, r));
4267 }
4268 else if (context && context.outlet && context.outlet.isActivated) {
4269 checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
4270 }
4271 else {
4272 checks.canDeactivateChecks.push(new CanDeactivate(null, r));
4273 }
4274}
4275
4276/**
4277 * @fileoverview added by tsickle
4278 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4279 */
4280/** @type {?} */
4281const INITIAL_VALUE = Symbol('INITIAL_VALUE');
4282/**
4283 * @return {?}
4284 */
4285function prioritizedGuardValue() {
4286 return switchMap((/**
4287 * @param {?} obs
4288 * @return {?}
4289 */
4290 obs => {
4291 return (/** @type {?} */ (combineLatest(...obs.map((/**
4292 * @param {?} o
4293 * @return {?}
4294 */
4295 o => o.pipe(take(1), startWith((/** @type {?} */ (INITIAL_VALUE)))))))
4296 .pipe(scan((/**
4297 * @param {?} acc
4298 * @param {?} list
4299 * @return {?}
4300 */
4301 (acc, list) => {
4302 /** @type {?} */
4303 let isPending = false;
4304 return list.reduce((/**
4305 * @param {?} innerAcc
4306 * @param {?} val
4307 * @param {?} i
4308 * @return {?}
4309 */
4310 (innerAcc, val, i) => {
4311 if (innerAcc !== INITIAL_VALUE)
4312 return innerAcc;
4313 // Toggle pending flag if any values haven't been set yet
4314 if (val === INITIAL_VALUE)
4315 isPending = true;
4316 // Any other return values are only valid if we haven't yet hit a pending call.
4317 // This guarantees that in the case of a guard at the bottom of the tree that
4318 // returns a redirect, we will wait for the higher priority guard at the top to
4319 // finish before performing the redirect.
4320 if (!isPending) {
4321 // Early return when we hit a `false` value as that should always cancel
4322 // navigation
4323 if (val === false)
4324 return val;
4325 if (i === list.length - 1 || isUrlTree(val)) {
4326 return val;
4327 }
4328 }
4329 return innerAcc;
4330 }), acc);
4331 }), INITIAL_VALUE), filter((/**
4332 * @param {?} item
4333 * @return {?}
4334 */
4335 item => item !== INITIAL_VALUE)), map((/**
4336 * @param {?} item
4337 * @return {?}
4338 */
4339 item => isUrlTree(item) ? item : item === true)), //
4340 take(1))));
4341 }));
4342}
4343
4344/**
4345 * @fileoverview added by tsickle
4346 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4347 */
4348/**
4349 * @param {?} moduleInjector
4350 * @param {?=} forwardEvent
4351 * @return {?}
4352 */
4353function checkGuards(moduleInjector, forwardEvent) {
4354 return (/**
4355 * @param {?} source
4356 * @return {?}
4357 */
4358 function (source) {
4359 return source.pipe(mergeMap((/**
4360 * @param {?} t
4361 * @return {?}
4362 */
4363 t => {
4364 const { targetSnapshot, currentSnapshot, guards: { canActivateChecks, canDeactivateChecks } } = t;
4365 if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
4366 return of(Object.assign({}, t, { guardsResult: true }));
4367 }
4368 return runCanDeactivateChecks(canDeactivateChecks, (/** @type {?} */ (targetSnapshot)), currentSnapshot, moduleInjector)
4369 .pipe(mergeMap((/**
4370 * @param {?} canDeactivate
4371 * @return {?}
4372 */
4373 canDeactivate => {
4374 return canDeactivate && isBoolean(canDeactivate) ?
4375 runCanActivateChecks((/** @type {?} */ (targetSnapshot)), canActivateChecks, moduleInjector, forwardEvent) :
4376 of(canDeactivate);
4377 })), map((/**
4378 * @param {?} guardsResult
4379 * @return {?}
4380 */
4381 guardsResult => (Object.assign({}, t, { guardsResult })))));
4382 })));
4383 });
4384}
4385/**
4386 * @param {?} checks
4387 * @param {?} futureRSS
4388 * @param {?} currRSS
4389 * @param {?} moduleInjector
4390 * @return {?}
4391 */
4392function runCanDeactivateChecks(checks, futureRSS, currRSS, moduleInjector) {
4393 return from(checks).pipe(mergeMap((/**
4394 * @param {?} check
4395 * @return {?}
4396 */
4397 check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, moduleInjector))), first((/**
4398 * @param {?} result
4399 * @return {?}
4400 */
4401 result => { return result !== true; }), (/** @type {?} */ (true))));
4402}
4403/**
4404 * @param {?} futureSnapshot
4405 * @param {?} checks
4406 * @param {?} moduleInjector
4407 * @param {?=} forwardEvent
4408 * @return {?}
4409 */
4410function runCanActivateChecks(futureSnapshot, checks, moduleInjector, forwardEvent) {
4411 return from(checks).pipe(concatMap((/**
4412 * @param {?} check
4413 * @return {?}
4414 */
4415 (check) => {
4416 return from([
4417 fireChildActivationStart(check.route.parent, forwardEvent),
4418 fireActivationStart(check.route, forwardEvent),
4419 runCanActivateChild(futureSnapshot, check.path, moduleInjector),
4420 runCanActivate(futureSnapshot, check.route, moduleInjector)
4421 ])
4422 .pipe(concatAll(), first((/**
4423 * @param {?} result
4424 * @return {?}
4425 */
4426 result => {
4427 return result !== true;
4428 }), (/** @type {?} */ (true))));
4429 })), first((/**
4430 * @param {?} result
4431 * @return {?}
4432 */
4433 result => { return result !== true; }), (/** @type {?} */ (true))));
4434}
4435/**
4436 * This should fire off `ActivationStart` events for each route being activated at this
4437 * level.
4438 * In other words, if you're activating `a` and `b` below, `path` will contain the
4439 * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always
4440 * return
4441 * `true` so checks continue to run.
4442 * @param {?} snapshot
4443 * @param {?=} forwardEvent
4444 * @return {?}
4445 */
4446function fireActivationStart(snapshot, forwardEvent) {
4447 if (snapshot !== null && forwardEvent) {
4448 forwardEvent(new ActivationStart(snapshot));
4449 }
4450 return of(true);
4451}
4452/**
4453 * This should fire off `ChildActivationStart` events for each route being activated at this
4454 * level.
4455 * In other words, if you're activating `a` and `b` below, `path` will contain the
4456 * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always
4457 * return
4458 * `true` so checks continue to run.
4459 * @param {?} snapshot
4460 * @param {?=} forwardEvent
4461 * @return {?}
4462 */
4463function fireChildActivationStart(snapshot, forwardEvent) {
4464 if (snapshot !== null && forwardEvent) {
4465 forwardEvent(new ChildActivationStart(snapshot));
4466 }
4467 return of(true);
4468}
4469/**
4470 * @param {?} futureRSS
4471 * @param {?} futureARS
4472 * @param {?} moduleInjector
4473 * @return {?}
4474 */
4475function runCanActivate(futureRSS, futureARS, moduleInjector) {
4476 /** @type {?} */
4477 const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
4478 if (!canActivate || canActivate.length === 0)
4479 return of(true);
4480 /** @type {?} */
4481 const canActivateObservables = canActivate.map((/**
4482 * @param {?} c
4483 * @return {?}
4484 */
4485 (c) => {
4486 return defer((/**
4487 * @return {?}
4488 */
4489 () => {
4490 /** @type {?} */
4491 const guard = getToken(c, futureARS, moduleInjector);
4492 /** @type {?} */
4493 let observable;
4494 if (isCanActivate(guard)) {
4495 observable = wrapIntoObservable(guard.canActivate(futureARS, futureRSS));
4496 }
4497 else if (isFunction(guard)) {
4498 observable = wrapIntoObservable(guard(futureARS, futureRSS));
4499 }
4500 else {
4501 throw new Error('Invalid CanActivate guard');
4502 }
4503 return observable.pipe(first());
4504 }));
4505 }));
4506 return of(canActivateObservables).pipe(prioritizedGuardValue());
4507}
4508/**
4509 * @param {?} futureRSS
4510 * @param {?} path
4511 * @param {?} moduleInjector
4512 * @return {?}
4513 */
4514function runCanActivateChild(futureRSS, path, moduleInjector) {
4515 /** @type {?} */
4516 const futureARS = path[path.length - 1];
4517 /** @type {?} */
4518 const canActivateChildGuards = path.slice(0, path.length - 1)
4519 .reverse()
4520 .map((/**
4521 * @param {?} p
4522 * @return {?}
4523 */
4524 p => getCanActivateChild(p)))
4525 .filter((/**
4526 * @param {?} _
4527 * @return {?}
4528 */
4529 _ => _ !== null));
4530 /** @type {?} */
4531 const canActivateChildGuardsMapped = canActivateChildGuards.map((/**
4532 * @param {?} d
4533 * @return {?}
4534 */
4535 (d) => {
4536 return defer((/**
4537 * @return {?}
4538 */
4539 () => {
4540 /** @type {?} */
4541 const guardsMapped = d.guards.map((/**
4542 * @param {?} c
4543 * @return {?}
4544 */
4545 (c) => {
4546 /** @type {?} */
4547 const guard = getToken(c, d.node, moduleInjector);
4548 /** @type {?} */
4549 let observable;
4550 if (isCanActivateChild(guard)) {
4551 observable = wrapIntoObservable(guard.canActivateChild(futureARS, futureRSS));
4552 }
4553 else if (isFunction(guard)) {
4554 observable = wrapIntoObservable(guard(futureARS, futureRSS));
4555 }
4556 else {
4557 throw new Error('Invalid CanActivateChild guard');
4558 }
4559 return observable.pipe(first());
4560 }));
4561 return of(guardsMapped).pipe(prioritizedGuardValue());
4562 }));
4563 }));
4564 return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
4565}
4566/**
4567 * @param {?} component
4568 * @param {?} currARS
4569 * @param {?} currRSS
4570 * @param {?} futureRSS
4571 * @param {?} moduleInjector
4572 * @return {?}
4573 */
4574function runCanDeactivate(component, currARS, currRSS, futureRSS, moduleInjector) {
4575 /** @type {?} */
4576 const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
4577 if (!canDeactivate || canDeactivate.length === 0)
4578 return of(true);
4579 /** @type {?} */
4580 const canDeactivateObservables = canDeactivate.map((/**
4581 * @param {?} c
4582 * @return {?}
4583 */
4584 (c) => {
4585 /** @type {?} */
4586 const guard = getToken(c, currARS, moduleInjector);
4587 /** @type {?} */
4588 let observable;
4589 if (isCanDeactivate(guard)) {
4590 observable =
4591 wrapIntoObservable(guard.canDeactivate((/** @type {?} */ (component)), currARS, currRSS, futureRSS));
4592 }
4593 else if (isFunction(guard)) {
4594 observable = wrapIntoObservable(guard(component, currARS, currRSS, futureRSS));
4595 }
4596 else {
4597 throw new Error('Invalid CanDeactivate guard');
4598 }
4599 return observable.pipe(first());
4600 }));
4601 return of(canDeactivateObservables).pipe(prioritizedGuardValue());
4602}
4603
4604/**
4605 * @fileoverview added by tsickle
4606 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
4607 */
4608class NoMatch$1 {
4609}
4610/**
4611 * @param {?} rootComponentType
4612 * @param {?} config
4613 * @param {?} urlTree
4614 * @param {?} url
4615 * @param {?=} paramsInheritanceStrategy
4616 * @param {?=} relativeLinkResolution
4617 * @return {?}
4618 */
4619function recognize(rootComponentType, config, urlTree, url, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') {
4620 return new Recognizer(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution)
4621 .recognize();
4622}
4623class Recognizer {
4624 /**
4625 * @param {?} rootComponentType
4626 * @param {?} config
4627 * @param {?} urlTree
4628 * @param {?} url
4629 * @param {?} paramsInheritanceStrategy
4630 * @param {?} relativeLinkResolution
4631 */
4632 constructor(rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution) {
4633 this.rootComponentType = rootComponentType;
4634 this.config = config;
4635 this.urlTree = urlTree;
4636 this.url = url;
4637 this.paramsInheritanceStrategy = paramsInheritanceStrategy;
4638 this.relativeLinkResolution = relativeLinkResolution;
4639 }
4640 /**
4641 * @return {?}
4642 */
4643 recognize() {
4644 try {
4645 /** @type {?} */
4646 const rootSegmentGroup = split$1(this.urlTree.root, [], [], this.config, this.relativeLinkResolution).segmentGroup;
4647 /** @type {?} */
4648 const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
4649 /** @type {?} */
4650 const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(Object.assign({}, this.urlTree.queryParams)), (/** @type {?} */ (this.urlTree.fragment)), {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
4651 /** @type {?} */
4652 const rootNode = new TreeNode(root, children);
4653 /** @type {?} */
4654 const routeState = new RouterStateSnapshot(this.url, rootNode);
4655 this.inheritParamsAndData(routeState._root);
4656 return of(routeState);
4657 }
4658 catch (e) {
4659 return new Observable((/**
4660 * @param {?} obs
4661 * @return {?}
4662 */
4663 (obs) => obs.error(e)));
4664 }
4665 }
4666 /**
4667 * @param {?} routeNode
4668 * @return {?}
4669 */
4670 inheritParamsAndData(routeNode) {
4671 /** @type {?} */
4672 const route = routeNode.value;
4673 /** @type {?} */
4674 const i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy);
4675 route.params = Object.freeze(i.params);
4676 route.data = Object.freeze(i.data);
4677 routeNode.children.forEach((/**
4678 * @param {?} n
4679 * @return {?}
4680 */
4681 n => this.inheritParamsAndData(n)));
4682 }
4683 /**
4684 * @param {?} config
4685 * @param {?} segmentGroup
4686 * @param {?} outlet
4687 * @return {?}
4688 */
4689 processSegmentGroup(config, segmentGroup, outlet) {
4690 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
4691 return this.processChildren(config, segmentGroup);
4692 }
4693 return this.processSegment(config, segmentGroup, segmentGroup.segments, outlet);
4694 }
4695 /**
4696 * @param {?} config
4697 * @param {?} segmentGroup
4698 * @return {?}
4699 */
4700 processChildren(config, segmentGroup) {
4701 /** @type {?} */
4702 const children = mapChildrenIntoArray(segmentGroup, (/**
4703 * @param {?} child
4704 * @param {?} childOutlet
4705 * @return {?}
4706 */
4707 (child, childOutlet) => this.processSegmentGroup(config, child, childOutlet)));
4708 checkOutletNameUniqueness(children);
4709 sortActivatedRouteSnapshots(children);
4710 return children;
4711 }
4712 /**
4713 * @param {?} config
4714 * @param {?} segmentGroup
4715 * @param {?} segments
4716 * @param {?} outlet
4717 * @return {?}
4718 */
4719 processSegment(config, segmentGroup, segments, outlet) {
4720 for (const r of config) {
4721 try {
4722 return this.processSegmentAgainstRoute(r, segmentGroup, segments, outlet);
4723 }
4724 catch (e) {
4725 if (!(e instanceof NoMatch$1))
4726 throw e;
4727 }
4728 }
4729 if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) {
4730 return [];
4731 }
4732 throw new NoMatch$1();
4733 }
4734 /**
4735 * @private
4736 * @param {?} segmentGroup
4737 * @param {?} segments
4738 * @param {?} outlet
4739 * @return {?}
4740 */
4741 noLeftoversInUrl(segmentGroup, segments, outlet) {
4742 return segments.length === 0 && !segmentGroup.children[outlet];
4743 }
4744 /**
4745 * @param {?} route
4746 * @param {?} rawSegment
4747 * @param {?} segments
4748 * @param {?} outlet
4749 * @return {?}
4750 */
4751 processSegmentAgainstRoute(route, rawSegment, segments, outlet) {
4752 if (route.redirectTo)
4753 throw new NoMatch$1();
4754 if ((route.outlet || PRIMARY_OUTLET) !== outlet)
4755 throw new NoMatch$1();
4756 /** @type {?} */
4757 let snapshot;
4758 /** @type {?} */
4759 let consumedSegments = [];
4760 /** @type {?} */
4761 let rawSlicedSegments = [];
4762 if (route.path === '**') {
4763 /** @type {?} */
4764 const params = segments.length > 0 ? (/** @type {?} */ (last(segments))).parameters : {};
4765 snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), (/** @type {?} */ (this.urlTree.fragment)), getData(route), outlet, (/** @type {?} */ (route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route));
4766 }
4767 else {
4768 /** @type {?} */
4769 const result = match$1(rawSegment, route, segments);
4770 consumedSegments = result.consumedSegments;
4771 rawSlicedSegments = segments.slice(result.lastChild);
4772 snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), (/** @type {?} */ (this.urlTree.fragment)), getData(route), outlet, (/** @type {?} */ (route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route));
4773 }
4774 /** @type {?} */
4775 const childConfig = getChildConfig(route);
4776 const { segmentGroup, slicedSegments } = split$1(rawSegment, consumedSegments, rawSlicedSegments, childConfig, this.relativeLinkResolution);
4777 if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
4778 /** @type {?} */
4779 const children = this.processChildren(childConfig, segmentGroup);
4780 return [new TreeNode(snapshot, children)];
4781 }
4782 if (childConfig.length === 0 && slicedSegments.length === 0) {
4783 return [new TreeNode(snapshot, [])];
4784 }
4785 /** @type {?} */
4786 const children = this.processSegment(childConfig, segmentGroup, slicedSegments, PRIMARY_OUTLET);
4787 return [new TreeNode(snapshot, children)];
4788 }
4789}
4790/**
4791 * @param {?} nodes
4792 * @return {?}
4793 */
4794function sortActivatedRouteSnapshots(nodes) {
4795 nodes.sort((/**
4796 * @param {?} a
4797 * @param {?} b
4798 * @return {?}
4799 */
4800 (a, b) => {
4801 if (a.value.outlet === PRIMARY_OUTLET)
4802 return -1;
4803 if (b.value.outlet === PRIMARY_OUTLET)
4804 return 1;
4805 return a.value.outlet.localeCompare(b.value.outlet);
4806 }));
4807}
4808/**
4809 * @param {?} route
4810 * @return {?}
4811 */
4812function getChildConfig(route) {
4813 if (route.children) {
4814 return route.children;
4815 }
4816 if (route.loadChildren) {
4817 return (/** @type {?} */ (route._loadedConfig)).routes;
4818 }
4819 return [];
4820}
4821/**
4822 * @param {?} segmentGroup
4823 * @param {?} route
4824 * @param {?} segments
4825 * @return {?}
4826 */
4827function match$1(segmentGroup, route, segments) {
4828 if (route.path === '') {
4829 if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
4830 throw new NoMatch$1();
4831 }
4832 return { consumedSegments: [], lastChild: 0, parameters: {} };
4833 }
4834 /** @type {?} */
4835 const matcher = route.matcher || defaultUrlMatcher;
4836 /** @type {?} */
4837 const res = matcher(segments, segmentGroup, route);
4838 if (!res)
4839 throw new NoMatch$1();
4840 /** @type {?} */
4841 const posParams = {};
4842 forEach((/** @type {?} */ (res.posParams)), (/**
4843 * @param {?} v
4844 * @param {?} k
4845 * @return {?}
4846 */
4847 (v, k) => { posParams[k] = v.path; }));
4848 /** @type {?} */
4849 const parameters = res.consumed.length > 0 ? Object.assign({}, posParams, res.consumed[res.consumed.length - 1].parameters) :
4850 posParams;
4851 return { consumedSegments: res.consumed, lastChild: res.consumed.length, parameters };
4852}
4853/**
4854 * @param {?} nodes
4855 * @return {?}
4856 */
4857function checkOutletNameUniqueness(nodes) {
4858 /** @type {?} */
4859 const names = {};
4860 nodes.forEach((/**
4861 * @param {?} n
4862 * @return {?}
4863 */
4864 n => {
4865 /** @type {?} */
4866 const routeWithSameOutletName = names[n.value.outlet];
4867 if (routeWithSameOutletName) {
4868 /** @type {?} */
4869 const p = routeWithSameOutletName.url.map((/**
4870 * @param {?} s
4871 * @return {?}
4872 */
4873 s => s.toString())).join('/');
4874 /** @type {?} */
4875 const c = n.value.url.map((/**
4876 * @param {?} s
4877 * @return {?}
4878 */
4879 s => s.toString())).join('/');
4880 throw new Error(`Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
4881 }
4882 names[n.value.outlet] = n.value;
4883 }));
4884}
4885/**
4886 * @param {?} segmentGroup
4887 * @return {?}
4888 */
4889function getSourceSegmentGroup(segmentGroup) {
4890 /** @type {?} */
4891 let s = segmentGroup;
4892 while (s._sourceSegment) {
4893 s = s._sourceSegment;
4894 }
4895 return s;
4896}
4897/**
4898 * @param {?} segmentGroup
4899 * @return {?}
4900 */
4901function getPathIndexShift(segmentGroup) {
4902 /** @type {?} */
4903 let s = segmentGroup;
4904 /** @type {?} */
4905 let res = (s._segmentIndexShift ? s._segmentIndexShift : 0);
4906 while (s._sourceSegment) {
4907 s = s._sourceSegment;
4908 res += (s._segmentIndexShift ? s._segmentIndexShift : 0);
4909 }
4910 return res - 1;
4911}
4912/**
4913 * @param {?} segmentGroup
4914 * @param {?} consumedSegments
4915 * @param {?} slicedSegments
4916 * @param {?} config
4917 * @param {?} relativeLinkResolution
4918 * @return {?}
4919 */
4920function split$1(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution) {
4921 if (slicedSegments.length > 0 &&
4922 containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
4923 /** @type {?} */
4924 const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
4925 s._sourceSegment = segmentGroup;
4926 s._segmentIndexShift = consumedSegments.length;
4927 return { segmentGroup: s, slicedSegments: [] };
4928 }
4929 if (slicedSegments.length === 0 &&
4930 containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
4931 /** @type {?} */
4932 const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution));
4933 s._sourceSegment = segmentGroup;
4934 s._segmentIndexShift = consumedSegments.length;
4935 return { segmentGroup: s, slicedSegments };
4936 }
4937 /** @type {?} */
4938 const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
4939 s._sourceSegment = segmentGroup;
4940 s._segmentIndexShift = consumedSegments.length;
4941 return { segmentGroup: s, slicedSegments };
4942}
4943/**
4944 * @param {?} segmentGroup
4945 * @param {?} consumedSegments
4946 * @param {?} slicedSegments
4947 * @param {?} routes
4948 * @param {?} children
4949 * @param {?} relativeLinkResolution
4950 * @return {?}
4951 */
4952function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) {
4953 /** @type {?} */
4954 const res = {};
4955 for (const r of routes) {
4956 if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet$1(r)]) {
4957 /** @type {?} */
4958 const s = new UrlSegmentGroup([], {});
4959 s._sourceSegment = segmentGroup;
4960 if (relativeLinkResolution === 'legacy') {
4961 s._segmentIndexShift = segmentGroup.segments.length;
4962 }
4963 else {
4964 s._segmentIndexShift = consumedSegments.length;
4965 }
4966 res[getOutlet$1(r)] = s;
4967 }
4968 }
4969 return Object.assign({}, children, res);
4970}
4971/**
4972 * @param {?} segmentGroup
4973 * @param {?} consumedSegments
4974 * @param {?} routes
4975 * @param {?} primarySegment
4976 * @return {?}
4977 */
4978function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) {
4979 /** @type {?} */
4980 const res = {};
4981 res[PRIMARY_OUTLET] = primarySegment;
4982 primarySegment._sourceSegment = segmentGroup;
4983 primarySegment._segmentIndexShift = consumedSegments.length;
4984 for (const r of routes) {
4985 if (r.path === '' && getOutlet$1(r) !== PRIMARY_OUTLET) {
4986 /** @type {?} */
4987 const s = new UrlSegmentGroup([], {});
4988 s._sourceSegment = segmentGroup;
4989 s._segmentIndexShift = consumedSegments.length;
4990 res[getOutlet$1(r)] = s;
4991 }
4992 }
4993 return res;
4994}
4995/**
4996 * @param {?} segmentGroup
4997 * @param {?} slicedSegments
4998 * @param {?} routes
4999 * @return {?}
5000 */
5001function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
5002 return routes.some((/**
5003 * @param {?} r
5004 * @return {?}
5005 */
5006 r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet$1(r) !== PRIMARY_OUTLET));
5007}
5008/**
5009 * @param {?} segmentGroup
5010 * @param {?} slicedSegments
5011 * @param {?} routes
5012 * @return {?}
5013 */
5014function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
5015 return routes.some((/**
5016 * @param {?} r
5017 * @return {?}
5018 */
5019 r => emptyPathMatch(segmentGroup, slicedSegments, r)));
5020}
5021/**
5022 * @param {?} segmentGroup
5023 * @param {?} slicedSegments
5024 * @param {?} r
5025 * @return {?}
5026 */
5027function emptyPathMatch(segmentGroup, slicedSegments, r) {
5028 if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
5029 return false;
5030 }
5031 return r.path === '' && r.redirectTo === undefined;
5032}
5033/**
5034 * @param {?} route
5035 * @return {?}
5036 */
5037function getOutlet$1(route) {
5038 return route.outlet || PRIMARY_OUTLET;
5039}
5040/**
5041 * @param {?} route
5042 * @return {?}
5043 */
5044function getData(route) {
5045 return route.data || {};
5046}
5047/**
5048 * @param {?} route
5049 * @return {?}
5050 */
5051function getResolve(route) {
5052 return route.resolve || {};
5053}
5054
5055/**
5056 * @fileoverview added by tsickle
5057 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5058 */
5059/**
5060 * @param {?} rootComponentType
5061 * @param {?} config
5062 * @param {?} serializer
5063 * @param {?} paramsInheritanceStrategy
5064 * @param {?} relativeLinkResolution
5065 * @return {?}
5066 */
5067function recognize$1(rootComponentType, config, serializer, paramsInheritanceStrategy, relativeLinkResolution) {
5068 return (/**
5069 * @param {?} source
5070 * @return {?}
5071 */
5072 function (source) {
5073 return source.pipe(mergeMap((/**
5074 * @param {?} t
5075 * @return {?}
5076 */
5077 t => recognize(rootComponentType, config, t.urlAfterRedirects, serializer(t.urlAfterRedirects), paramsInheritanceStrategy, relativeLinkResolution)
5078 .pipe(map((/**
5079 * @param {?} targetSnapshot
5080 * @return {?}
5081 */
5082 targetSnapshot => (Object.assign({}, t, { targetSnapshot }))))))));
5083 });
5084}
5085
5086/**
5087 * @fileoverview added by tsickle
5088 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5089 */
5090/**
5091 * @param {?} paramsInheritanceStrategy
5092 * @param {?} moduleInjector
5093 * @return {?}
5094 */
5095function resolveData(paramsInheritanceStrategy, moduleInjector) {
5096 return (/**
5097 * @param {?} source
5098 * @return {?}
5099 */
5100 function (source) {
5101 return source.pipe(mergeMap((/**
5102 * @param {?} t
5103 * @return {?}
5104 */
5105 t => {
5106 const { targetSnapshot, guards: { canActivateChecks } } = t;
5107 if (!canActivateChecks.length) {
5108 return of(t);
5109 }
5110 return from(canActivateChecks)
5111 .pipe(concatMap((/**
5112 * @param {?} check
5113 * @return {?}
5114 */
5115 check => runResolve(check.route, (/** @type {?} */ (targetSnapshot)), paramsInheritanceStrategy, moduleInjector))), reduce((/**
5116 * @param {?} _
5117 * @param {?} __
5118 * @return {?}
5119 */
5120 (_, __) => _)), map((/**
5121 * @param {?} _
5122 * @return {?}
5123 */
5124 _ => t)));
5125 })));
5126 });
5127}
5128/**
5129 * @param {?} futureARS
5130 * @param {?} futureRSS
5131 * @param {?} paramsInheritanceStrategy
5132 * @param {?} moduleInjector
5133 * @return {?}
5134 */
5135function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, moduleInjector) {
5136 /** @type {?} */
5137 const resolve = futureARS._resolve;
5138 return resolveNode(resolve, futureARS, futureRSS, moduleInjector)
5139 .pipe(map((/**
5140 * @param {?} resolvedData
5141 * @return {?}
5142 */
5143 (resolvedData) => {
5144 futureARS._resolvedData = resolvedData;
5145 futureARS.data = Object.assign({}, futureARS.data, inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve);
5146 return null;
5147 })));
5148}
5149/**
5150 * @param {?} resolve
5151 * @param {?} futureARS
5152 * @param {?} futureRSS
5153 * @param {?} moduleInjector
5154 * @return {?}
5155 */
5156function resolveNode(resolve, futureARS, futureRSS, moduleInjector) {
5157 /** @type {?} */
5158 const keys = Object.keys(resolve);
5159 if (keys.length === 0) {
5160 return of({});
5161 }
5162 if (keys.length === 1) {
5163 /** @type {?} */
5164 const key = keys[0];
5165 return getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
5166 .pipe(map((/**
5167 * @param {?} value
5168 * @return {?}
5169 */
5170 (value) => { return { [key]: value }; })));
5171 }
5172 /** @type {?} */
5173 const data = {};
5174 /** @type {?} */
5175 const runningResolvers$ = from(keys).pipe(mergeMap((/**
5176 * @param {?} key
5177 * @return {?}
5178 */
5179 (key) => {
5180 return getResolver(resolve[key], futureARS, futureRSS, moduleInjector)
5181 .pipe(map((/**
5182 * @param {?} value
5183 * @return {?}
5184 */
5185 (value) => {
5186 data[key] = value;
5187 return value;
5188 })));
5189 })));
5190 return runningResolvers$.pipe(last$1(), map((/**
5191 * @return {?}
5192 */
5193 () => data)));
5194}
5195/**
5196 * @param {?} injectionToken
5197 * @param {?} futureARS
5198 * @param {?} futureRSS
5199 * @param {?} moduleInjector
5200 * @return {?}
5201 */
5202function getResolver(injectionToken, futureARS, futureRSS, moduleInjector) {
5203 /** @type {?} */
5204 const resolver = getToken(injectionToken, futureARS, moduleInjector);
5205 return resolver.resolve ? wrapIntoObservable(resolver.resolve(futureARS, futureRSS)) :
5206 wrapIntoObservable(resolver(futureARS, futureRSS));
5207}
5208
5209/**
5210 * @fileoverview added by tsickle
5211 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5212 */
5213/**
5214 * Perform a side effect through a switchMap for every emission on the source Observable,
5215 * but return an Observable that is identical to the source. It's essentially the same as
5216 * the `tap` operator, but if the side effectful `next` function returns an ObservableInput,
5217 * it will wait before continuing with the original value.
5218 * @template T
5219 * @param {?} next
5220 * @return {?}
5221 */
5222function switchTap(next) {
5223 return (/**
5224 * @param {?} source
5225 * @return {?}
5226 */
5227 function (source) {
5228 return source.pipe(switchMap((/**
5229 * @param {?} v
5230 * @return {?}
5231 */
5232 v => {
5233 /** @type {?} */
5234 const nextResult = next(v);
5235 if (nextResult) {
5236 return from(nextResult).pipe(map((/**
5237 * @return {?}
5238 */
5239 () => v)));
5240 }
5241 return from([v]);
5242 })));
5243 });
5244}
5245
5246/**
5247 * @fileoverview added by tsickle
5248 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5249 */
5250/**
5251 * @license
5252 * Copyright Google Inc. All Rights Reserved.
5253 *
5254 * Use of this source code is governed by an MIT-style license that can be
5255 * found in the LICENSE file at https://angular.io/license
5256 */
5257/**
5258 * \@description
5259 *
5260 * Provides a way to customize when activated routes get reused.
5261 *
5262 * \@publicApi
5263 * @abstract
5264 */
5265class RouteReuseStrategy {
5266}
5267/**
5268 * Does not detach any subtrees. Reuses routes as long as their route config is the same.
5269 */
5270class DefaultRouteReuseStrategy {
5271 /**
5272 * @param {?} route
5273 * @return {?}
5274 */
5275 shouldDetach(route) { return false; }
5276 /**
5277 * @param {?} route
5278 * @param {?} detachedTree
5279 * @return {?}
5280 */
5281 store(route, detachedTree) { }
5282 /**
5283 * @param {?} route
5284 * @return {?}
5285 */
5286 shouldAttach(route) { return false; }
5287 /**
5288 * @param {?} route
5289 * @return {?}
5290 */
5291 retrieve(route) { return null; }
5292 /**
5293 * @param {?} future
5294 * @param {?} curr
5295 * @return {?}
5296 */
5297 shouldReuseRoute(future, curr) {
5298 return future.routeConfig === curr.routeConfig;
5299 }
5300}
5301
5302/**
5303 * @fileoverview added by tsickle
5304 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5305 */
5306/**
5307 * The [DI token](guide/glossary/#di-token) for a router configuration.
5308 * @see `ROUTES`
5309 * \@publicApi
5310 * @type {?}
5311 */
5312const ROUTES = new InjectionToken('ROUTES');
5313class RouterConfigLoader {
5314 /**
5315 * @param {?} loader
5316 * @param {?} compiler
5317 * @param {?=} onLoadStartListener
5318 * @param {?=} onLoadEndListener
5319 */
5320 constructor(loader, compiler, onLoadStartListener, onLoadEndListener) {
5321 this.loader = loader;
5322 this.compiler = compiler;
5323 this.onLoadStartListener = onLoadStartListener;
5324 this.onLoadEndListener = onLoadEndListener;
5325 }
5326 /**
5327 * @param {?} parentInjector
5328 * @param {?} route
5329 * @return {?}
5330 */
5331 load(parentInjector, route) {
5332 if (this.onLoadStartListener) {
5333 this.onLoadStartListener(route);
5334 }
5335 /** @type {?} */
5336 const moduleFactory$ = this.loadModuleFactory((/** @type {?} */ (route.loadChildren)));
5337 return moduleFactory$.pipe(map((/**
5338 * @param {?} factory
5339 * @return {?}
5340 */
5341 (factory) => {
5342 if (this.onLoadEndListener) {
5343 this.onLoadEndListener(route);
5344 }
5345 /** @type {?} */
5346 const module = factory.create(parentInjector);
5347 return new LoadedRouterConfig(flatten(module.injector.get(ROUTES)).map(standardizeConfig), module);
5348 })));
5349 }
5350 /**
5351 * @private
5352 * @param {?} loadChildren
5353 * @return {?}
5354 */
5355 loadModuleFactory(loadChildren) {
5356 if (typeof loadChildren === 'string') {
5357 return from(this.loader.load(loadChildren));
5358 }
5359 else {
5360 return wrapIntoObservable(loadChildren()).pipe(mergeMap((/**
5361 * @param {?} t
5362 * @return {?}
5363 */
5364 (t) => {
5365 if (t instanceof NgModuleFactory) {
5366 return of(t);
5367 }
5368 else {
5369 return from(this.compiler.compileModuleAsync(t));
5370 }
5371 })));
5372 }
5373 }
5374}
5375
5376/**
5377 * @fileoverview added by tsickle
5378 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5379 */
5380/**
5381 * @license
5382 * Copyright Google Inc. All Rights Reserved.
5383 *
5384 * Use of this source code is governed by an MIT-style license that can be
5385 * found in the LICENSE file at https://angular.io/license
5386 */
5387/**
5388 * \@description
5389 *
5390 * Provides a way to migrate AngularJS applications to Angular.
5391 *
5392 * \@publicApi
5393 * @abstract
5394 */
5395class UrlHandlingStrategy {
5396}
5397/**
5398 * \@publicApi
5399 */
5400class DefaultUrlHandlingStrategy {
5401 /**
5402 * @param {?} url
5403 * @return {?}
5404 */
5405 shouldProcessUrl(url) { return true; }
5406 /**
5407 * @param {?} url
5408 * @return {?}
5409 */
5410 extract(url) { return url; }
5411 /**
5412 * @param {?} newUrlPart
5413 * @param {?} wholeUrl
5414 * @return {?}
5415 */
5416 merge(newUrlPart, wholeUrl) { return newUrlPart; }
5417}
5418
5419/**
5420 * @fileoverview added by tsickle
5421 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5422 */
5423/**
5424 * @param {?} error
5425 * @return {?}
5426 */
5427function defaultErrorHandler(error) {
5428 throw error;
5429}
5430/**
5431 * @param {?} error
5432 * @param {?} urlSerializer
5433 * @param {?} url
5434 * @return {?}
5435 */
5436function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
5437 return urlSerializer.parse('/');
5438}
5439/**
5440 * \@internal
5441 * @param {?} snapshot
5442 * @param {?} runExtras
5443 * @return {?}
5444 */
5445function defaultRouterHook(snapshot, runExtras) {
5446 return (/** @type {?} */ (of(null)));
5447}
5448/**
5449 * \@description
5450 *
5451 * An NgModule that provides navigation and URL manipulation capabilities.
5452 *
5453 * @see `Route`.
5454 * @see [Routing and Navigation Guide](guide/router).
5455 *
5456 * \@ngModule RouterModule
5457 *
5458 * \@publicApi
5459 */
5460class Router {
5461 /**
5462 * Creates the router service.
5463 * @param {?} rootComponentType
5464 * @param {?} urlSerializer
5465 * @param {?} rootContexts
5466 * @param {?} location
5467 * @param {?} injector
5468 * @param {?} loader
5469 * @param {?} compiler
5470 * @param {?} config
5471 */
5472 // TODO: vsavkin make internal after the final is out.
5473 constructor(rootComponentType, urlSerializer, rootContexts, location, injector, loader, compiler, config) {
5474 this.rootComponentType = rootComponentType;
5475 this.urlSerializer = urlSerializer;
5476 this.rootContexts = rootContexts;
5477 this.location = location;
5478 this.config = config;
5479 this.lastSuccessfulNavigation = null;
5480 this.currentNavigation = null;
5481 this.navigationId = 0;
5482 this.isNgZoneEnabled = false;
5483 /**
5484 * An event stream for routing events in this NgModule.
5485 */
5486 this.events = new Subject();
5487 /**
5488 * A handler for navigation errors in this NgModule.
5489 */
5490 this.errorHandler = defaultErrorHandler;
5491 /**
5492 * A handler for errors thrown by `Router.parseUrl(url)`
5493 * when `url` contains an invalid character.
5494 * The most common case is a `%` sign
5495 * that's not encoded and is not part of a percent encoded sequence.
5496 */
5497 this.malformedUriErrorHandler = defaultMalformedUriErrorHandler;
5498 /**
5499 * True if at least one navigation event has occurred,
5500 * false otherwise.
5501 */
5502 this.navigated = false;
5503 this.lastSuccessfulId = -1;
5504 /**
5505 * Hooks that enable you to pause navigation,
5506 * either before or after the preactivation phase.
5507 * Used by `RouterModule`.
5508 *
5509 * \@internal
5510 */
5511 this.hooks = {
5512 beforePreactivation: defaultRouterHook,
5513 afterPreactivation: defaultRouterHook
5514 };
5515 /**
5516 * A strategy for extracting and merging URLs.
5517 * Used for AngularJS to Angular migrations.
5518 */
5519 this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
5520 /**
5521 * A strategy for re-using routes.
5522 */
5523 this.routeReuseStrategy = new DefaultRouteReuseStrategy();
5524 /**
5525 * How to handle a navigation request to the current URL. One of:
5526 * - `'ignore'` : The router ignores the request.
5527 * - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature.
5528 */
5529 this.onSameUrlNavigation = 'ignore';
5530 /**
5531 * How to merge parameters, data, and resolved data from parent to child
5532 * routes. One of:
5533 *
5534 * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
5535 * for path-less or component-less routes.
5536 * - `'always'` : Inherit parent parameters, data, and resolved data
5537 * for all child routes.
5538 */
5539 this.paramsInheritanceStrategy = 'emptyOnly';
5540 /**
5541 * Determines when the router updates the browser URL.
5542 * By default (`"deferred"`), udates the browser URL after navigation has finished.
5543 * Set to `'eager'` to update the browser URL at the beginning of navigation.
5544 * You can choose to update early so that, if navigation fails,
5545 * you can show an error message with the URL that failed.
5546 */
5547 this.urlUpdateStrategy = 'deferred';
5548 /**
5549 * Enables a bug fix that corrects relative link resolution in components with empty paths.
5550 * @see `RouterModule`
5551 */
5552 this.relativeLinkResolution = 'legacy';
5553 /** @type {?} */
5554 const onLoadStart = (/**
5555 * @param {?} r
5556 * @return {?}
5557 */
5558 (r) => this.triggerEvent(new RouteConfigLoadStart(r)));
5559 /** @type {?} */
5560 const onLoadEnd = (/**
5561 * @param {?} r
5562 * @return {?}
5563 */
5564 (r) => this.triggerEvent(new RouteConfigLoadEnd(r)));
5565 this.ngModule = injector.get(NgModuleRef);
5566 this.console = injector.get(ɵConsole);
5567 /** @type {?} */
5568 const ngZone = injector.get(NgZone);
5569 this.isNgZoneEnabled = ngZone instanceof NgZone;
5570 this.resetConfig(config);
5571 this.currentUrlTree = createEmptyUrlTree();
5572 this.rawUrlTree = this.currentUrlTree;
5573 this.browserUrlTree = this.currentUrlTree;
5574 this.configLoader = new RouterConfigLoader(loader, compiler, onLoadStart, onLoadEnd);
5575 this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
5576 this.transitions = new BehaviorSubject({
5577 id: 0,
5578 currentUrlTree: this.currentUrlTree,
5579 currentRawUrl: this.currentUrlTree,
5580 extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
5581 urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
5582 rawUrl: this.currentUrlTree,
5583 extras: {},
5584 resolve: null,
5585 reject: null,
5586 promise: Promise.resolve(true),
5587 source: 'imperative',
5588 restoredState: null,
5589 currentSnapshot: this.routerState.snapshot,
5590 targetSnapshot: null,
5591 currentRouterState: this.routerState,
5592 targetRouterState: null,
5593 guards: { canActivateChecks: [], canDeactivateChecks: [] },
5594 guardsResult: null,
5595 });
5596 this.navigations = this.setupNavigations(this.transitions);
5597 this.processNavigations();
5598 }
5599 /**
5600 * @private
5601 * @param {?} transitions
5602 * @return {?}
5603 */
5604 setupNavigations(transitions) {
5605 /** @type {?} */
5606 const eventsSubject = ((/** @type {?} */ (this.events)));
5607 return (/** @type {?} */ ((/** @type {?} */ (transitions.pipe(filter((/**
5608 * @param {?} t
5609 * @return {?}
5610 */
5611 t => t.id !== 0)),
5612 // Extract URL
5613 map((/**
5614 * @param {?} t
5615 * @return {?}
5616 */
5617 t => ((/** @type {?} */ (Object.assign({}, t, { extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })))))),
5618 // Using switchMap so we cancel executing navigations when a new one comes in
5619 switchMap((/**
5620 * @param {?} t
5621 * @return {?}
5622 */
5623 t => {
5624 /** @type {?} */
5625 let completed = false;
5626 /** @type {?} */
5627 let errored = false;
5628 return of(t).pipe(
5629 // Store the Navigation object
5630 tap((/**
5631 * @param {?} t
5632 * @return {?}
5633 */
5634 t => {
5635 this.currentNavigation = {
5636 id: t.id,
5637 initialUrl: t.currentRawUrl,
5638 extractedUrl: t.extractedUrl,
5639 trigger: t.source,
5640 extras: t.extras,
5641 previousNavigation: this.lastSuccessfulNavigation ? Object.assign({}, this.lastSuccessfulNavigation, { previousNavigation: null }) :
5642 null
5643 };
5644 })), switchMap((/**
5645 * @param {?} t
5646 * @return {?}
5647 */
5648 t => {
5649 /** @type {?} */
5650 const urlTransition = !this.navigated || t.extractedUrl.toString() !== this.browserUrlTree.toString();
5651 /** @type {?} */
5652 const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
5653 this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
5654 if (processCurrentUrl) {
5655 return of(t).pipe(
5656 // Fire NavigationStart event
5657 switchMap((/**
5658 * @param {?} t
5659 * @return {?}
5660 */
5661 t => {
5662 /** @type {?} */
5663 const transition = this.transitions.getValue();
5664 eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState));
5665 if (transition !== this.transitions.getValue()) {
5666 return EMPTY;
5667 }
5668 return [t];
5669 })),
5670 // This delay is required to match old behavior that forced navigation to
5671 // always be async
5672 switchMap((/**
5673 * @param {?} t
5674 * @return {?}
5675 */
5676 t => Promise.resolve(t))),
5677 // ApplyRedirects
5678 applyRedirects$1(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config),
5679 // Update the currentNavigation
5680 tap((/**
5681 * @param {?} t
5682 * @return {?}
5683 */
5684 t => {
5685 this.currentNavigation = Object.assign({}, (/** @type {?} */ (this.currentNavigation)), { finalUrl: t.urlAfterRedirects });
5686 })),
5687 // Recognize
5688 recognize$1(this.rootComponentType, this.config, (/**
5689 * @param {?} url
5690 * @return {?}
5691 */
5692 (url) => this.serializeUrl(url)), this.paramsInheritanceStrategy, this.relativeLinkResolution),
5693 // Update URL if in `eager` update mode
5694 tap((/**
5695 * @param {?} t
5696 * @return {?}
5697 */
5698 t => {
5699 if (this.urlUpdateStrategy === 'eager') {
5700 if (!t.extras.skipLocationChange) {
5701 this.setBrowserUrl(t.urlAfterRedirects, !!t.extras.replaceUrl, t.id, t.extras.state);
5702 }
5703 this.browserUrlTree = t.urlAfterRedirects;
5704 }
5705 })),
5706 // Fire RoutesRecognized
5707 tap((/**
5708 * @param {?} t
5709 * @return {?}
5710 */
5711 t => {
5712 /** @type {?} */
5713 const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), (/** @type {?} */ (t.targetSnapshot)));
5714 eventsSubject.next(routesRecognized);
5715 })));
5716 }
5717 else {
5718 /** @type {?} */
5719 const processPreviousUrl = urlTransition && this.rawUrlTree &&
5720 this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
5721 /* When the current URL shouldn't be processed, but the previous one was, we
5722 * handle this "error condition" by navigating to the previously successful URL,
5723 * but leaving the URL intact.*/
5724 if (processPreviousUrl) {
5725 const { id, extractedUrl, source, restoredState, extras } = t;
5726 /** @type {?} */
5727 const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState);
5728 eventsSubject.next(navStart);
5729 /** @type {?} */
5730 const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
5731 return of(Object.assign({}, t, { targetSnapshot, urlAfterRedirects: extractedUrl, extras: Object.assign({}, extras, { skipLocationChange: false, replaceUrl: false }) }));
5732 }
5733 else {
5734 /* When neither the current or previous URL can be processed, do nothing other
5735 * than update router's internal reference to the current "settled" URL. This
5736 * way the next navigation will be coming from the current URL in the browser.
5737 */
5738 this.rawUrlTree = t.rawUrl;
5739 this.browserUrlTree = t.urlAfterRedirects;
5740 t.resolve(null);
5741 return EMPTY;
5742 }
5743 }
5744 })),
5745 // Before Preactivation
5746 switchTap((/**
5747 * @param {?} t
5748 * @return {?}
5749 */
5750 t => {
5751 const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
5752 return this.hooks.beforePreactivation((/** @type {?} */ (targetSnapshot)), {
5753 navigationId,
5754 appliedUrlTree,
5755 rawUrlTree,
5756 skipLocationChange: !!skipLocationChange,
5757 replaceUrl: !!replaceUrl,
5758 });
5759 })),
5760 // --- GUARDS ---
5761 tap((/**
5762 * @param {?} t
5763 * @return {?}
5764 */
5765 t => {
5766 /** @type {?} */
5767 const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), (/** @type {?} */ (t.targetSnapshot)));
5768 this.triggerEvent(guardsStart);
5769 })), map((/**
5770 * @param {?} t
5771 * @return {?}
5772 */
5773 t => (Object.assign({}, t, { guards: getAllRouteGuards((/** @type {?} */ (t.targetSnapshot)), t.currentSnapshot, this.rootContexts) })))), checkGuards(this.ngModule.injector, (/**
5774 * @param {?} evt
5775 * @return {?}
5776 */
5777 (evt) => this.triggerEvent(evt))), tap((/**
5778 * @param {?} t
5779 * @return {?}
5780 */
5781 t => {
5782 if (isUrlTree(t.guardsResult)) {
5783 /** @type {?} */
5784 const error = navigationCancelingError(`Redirecting to "${this.serializeUrl(t.guardsResult)}"`);
5785 error.url = t.guardsResult;
5786 throw error;
5787 }
5788 })), tap((/**
5789 * @param {?} t
5790 * @return {?}
5791 */
5792 t => {
5793 /** @type {?} */
5794 const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), (/** @type {?} */ (t.targetSnapshot)), !!t.guardsResult);
5795 this.triggerEvent(guardsEnd);
5796 })), filter((/**
5797 * @param {?} t
5798 * @return {?}
5799 */
5800 t => {
5801 if (!t.guardsResult) {
5802 this.resetUrlToCurrentUrlTree();
5803 /** @type {?} */
5804 const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), '');
5805 eventsSubject.next(navCancel);
5806 t.resolve(false);
5807 return false;
5808 }
5809 return true;
5810 })),
5811 // --- RESOLVE ---
5812 switchTap((/**
5813 * @param {?} t
5814 * @return {?}
5815 */
5816 t => {
5817 if (t.guards.canActivateChecks.length) {
5818 return of(t).pipe(tap((/**
5819 * @param {?} t
5820 * @return {?}
5821 */
5822 t => {
5823 /** @type {?} */
5824 const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), (/** @type {?} */ (t.targetSnapshot)));
5825 this.triggerEvent(resolveStart);
5826 })), resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), //
5827 tap((/**
5828 * @param {?} t
5829 * @return {?}
5830 */
5831 t => {
5832 /** @type {?} */
5833 const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), (/** @type {?} */ (t.targetSnapshot)));
5834 this.triggerEvent(resolveEnd);
5835 })));
5836 }
5837 return undefined;
5838 })),
5839 // --- AFTER PREACTIVATION ---
5840 switchTap((/**
5841 * @param {?} t
5842 * @return {?}
5843 */
5844 (t) => {
5845 const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
5846 return this.hooks.afterPreactivation((/** @type {?} */ (targetSnapshot)), {
5847 navigationId,
5848 appliedUrlTree,
5849 rawUrlTree,
5850 skipLocationChange: !!skipLocationChange,
5851 replaceUrl: !!replaceUrl,
5852 });
5853 })), map((/**
5854 * @param {?} t
5855 * @return {?}
5856 */
5857 (t) => {
5858 /** @type {?} */
5859 const targetRouterState = createRouterState(this.routeReuseStrategy, (/** @type {?} */ (t.targetSnapshot)), t.currentRouterState);
5860 return (Object.assign({}, t, { targetRouterState }));
5861 })),
5862 /* Once here, we are about to activate syncronously. The assumption is this will
5863 succeed, and user code may read from the Router service. Therefore before
5864 activation, we need to update router properties storing the current URL and the
5865 RouterState, as well as updated the browser URL. All this should happen *before*
5866 activating. */
5867 tap((/**
5868 * @param {?} t
5869 * @return {?}
5870 */
5871 (t) => {
5872 this.currentUrlTree = t.urlAfterRedirects;
5873 this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
5874 ((/** @type {?} */ (this))).routerState = (/** @type {?} */ (t.targetRouterState));
5875 if (this.urlUpdateStrategy === 'deferred') {
5876 if (!t.extras.skipLocationChange) {
5877 this.setBrowserUrl(this.rawUrlTree, !!t.extras.replaceUrl, t.id, t.extras.state);
5878 }
5879 this.browserUrlTree = t.urlAfterRedirects;
5880 }
5881 })), activateRoutes(this.rootContexts, this.routeReuseStrategy, (/**
5882 * @param {?} evt
5883 * @return {?}
5884 */
5885 (evt) => this.triggerEvent(evt))), tap({ /**
5886 * @return {?}
5887 */
5888 next() { completed = true; }, /**
5889 * @return {?}
5890 */
5891 complete() { completed = true; } }), finalize((/**
5892 * @return {?}
5893 */
5894 () => {
5895 /* When the navigation stream finishes either through error or success, we set the
5896 * `completed` or `errored` flag. However, there are some situations where we could
5897 * get here without either of those being set. For instance, a redirect during
5898 * NavigationStart. Therefore, this is a catch-all to make sure the NavigationCancel
5899 * event is fired when a navigation gets cancelled but not caught by other means. */
5900 if (!completed && !errored) {
5901 // Must reset to current URL tree here to ensure history.state is set. On a fresh
5902 // page load, if a new navigation comes in before a successful navigation
5903 // completes, there will be nothing in history.state.navigationId. This can cause
5904 // sync problems with AngularJS sync code which looks for a value here in order
5905 // to determine whether or not to handle a given popstate event or to leave it
5906 // to the Angualr router.
5907 this.resetUrlToCurrentUrlTree();
5908 /** @type {?} */
5909 const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`);
5910 eventsSubject.next(navCancel);
5911 t.resolve(false);
5912 }
5913 // currentNavigation should always be reset to null here. If navigation was
5914 // successful, lastSuccessfulTransition will have already been set. Therefore we
5915 // can safely set currentNavigation to null here.
5916 this.currentNavigation = null;
5917 })), catchError((/**
5918 * @param {?} e
5919 * @return {?}
5920 */
5921 (e) => {
5922 errored = true;
5923 /* This error type is issued during Redirect, and is handled as a cancellation
5924 * rather than an error. */
5925 if (isNavigationCancelingError(e)) {
5926 /** @type {?} */
5927 const redirecting = isUrlTree(e.url);
5928 if (!redirecting) {
5929 // Set property only if we're not redirecting. If we landed on a page and
5930 // redirect to `/` route, the new navigation is going to see the `/` isn't
5931 // a change from the default currentUrlTree and won't navigate. This is
5932 // only applicable with initial navigation, so setting `navigated` only when
5933 // not redirecting resolves this scenario.
5934 this.navigated = true;
5935 this.resetStateAndUrl(t.currentRouterState, t.currentUrlTree, t.rawUrl);
5936 }
5937 /** @type {?} */
5938 const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), e.message);
5939 eventsSubject.next(navCancel);
5940 t.resolve(false);
5941 if (redirecting) {
5942 this.navigateByUrl(e.url);
5943 }
5944 /* All other errors should reset to the router's internal URL reference to the
5945 * pre-error state. */
5946 }
5947 else {
5948 this.resetStateAndUrl(t.currentRouterState, t.currentUrlTree, t.rawUrl);
5949 /** @type {?} */
5950 const navError = new NavigationError(t.id, this.serializeUrl(t.extractedUrl), e);
5951 eventsSubject.next(navError);
5952 try {
5953 t.resolve(this.errorHandler(e));
5954 }
5955 catch (ee) {
5956 t.reject(ee);
5957 }
5958 }
5959 return EMPTY;
5960 })));
5961 // TODO(jasonaden): remove cast once g3 is on updated TypeScript
5962 })))))));
5963 }
5964 /**
5965 * \@internal
5966 * TODO: this should be removed once the constructor of the router made internal
5967 * @param {?} rootComponentType
5968 * @return {?}
5969 */
5970 resetRootComponentType(rootComponentType) {
5971 this.rootComponentType = rootComponentType;
5972 // TODO: vsavkin router 4.0 should make the root component set to null
5973 // this will simplify the lifecycle of the router.
5974 this.routerState.root.component = this.rootComponentType;
5975 }
5976 /**
5977 * @private
5978 * @return {?}
5979 */
5980 getTransition() {
5981 /** @type {?} */
5982 const transition = this.transitions.value;
5983 // This value needs to be set. Other values such as extractedUrl are set on initial navigation
5984 // but the urlAfterRedirects may not get set if we aren't processing the new URL *and* not
5985 // processing the previous URL.
5986 transition.urlAfterRedirects = this.browserUrlTree;
5987 return transition;
5988 }
5989 /**
5990 * @private
5991 * @param {?} t
5992 * @return {?}
5993 */
5994 setTransition(t) {
5995 this.transitions.next(Object.assign({}, this.getTransition(), t));
5996 }
5997 /**
5998 * Sets up the location change listener and performs the initial navigation.
5999 * @return {?}
6000 */
6001 initialNavigation() {
6002 this.setUpLocationChangeListener();
6003 if (this.navigationId === 0) {
6004 this.navigateByUrl(this.location.path(true), { replaceUrl: true });
6005 }
6006 }
6007 /**
6008 * Sets up the location change listener.
6009 * @return {?}
6010 */
6011 setUpLocationChangeListener() {
6012 // Don't need to use Zone.wrap any more, because zone.js
6013 // already patch onPopState, so location change callback will
6014 // run into ngZone
6015 if (!this.locationSubscription) {
6016 this.locationSubscription = (/** @type {?} */ (this.location.subscribe((/**
6017 * @param {?} change
6018 * @return {?}
6019 */
6020 (change) => {
6021 /** @type {?} */
6022 let rawUrlTree = this.parseUrl(change['url']);
6023 /** @type {?} */
6024 const source = change['type'] === 'popstate' ? 'popstate' : 'hashchange';
6025 // Navigations coming from Angular router have a navigationId state property. When this
6026 // exists, restore the state.
6027 /** @type {?} */
6028 const state = change.state && change.state.navigationId ? change.state : null;
6029 setTimeout((/**
6030 * @return {?}
6031 */
6032 () => { this.scheduleNavigation(rawUrlTree, source, state, { replaceUrl: true }); }), 0);
6033 }))));
6034 }
6035 }
6036 /**
6037 * The current URL.
6038 * @return {?}
6039 */
6040 get url() { return this.serializeUrl(this.currentUrlTree); }
6041 /**
6042 * The current Navigation object if one exists
6043 * @return {?}
6044 */
6045 getCurrentNavigation() { return this.currentNavigation; }
6046 /**
6047 * \@internal
6048 * @param {?} event
6049 * @return {?}
6050 */
6051 triggerEvent(event) { ((/** @type {?} */ (this.events))).next(event); }
6052 /**
6053 * Resets the configuration used for navigation and generating links.
6054 *
6055 * \@usageNotes
6056 *
6057 * ```
6058 * router.resetConfig([
6059 * { path: 'team/:id', component: TeamCmp, children: [
6060 * { path: 'simple', component: SimpleCmp },
6061 * { path: 'user/:name', component: UserCmp }
6062 * ]}
6063 * ]);
6064 * ```
6065 * @param {?} config The route array for the new configuration.
6066 *
6067 * @return {?}
6068 */
6069 resetConfig(config) {
6070 validateConfig(config);
6071 this.config = config.map(standardizeConfig);
6072 this.navigated = false;
6073 this.lastSuccessfulId = -1;
6074 }
6075 /**
6076 * \@docsNotRequired
6077 * @return {?}
6078 */
6079 ngOnDestroy() { this.dispose(); }
6080 /**
6081 * Disposes of the router.
6082 * @return {?}
6083 */
6084 dispose() {
6085 if (this.locationSubscription) {
6086 this.locationSubscription.unsubscribe();
6087 this.locationSubscription = (/** @type {?} */ (null));
6088 }
6089 }
6090 /**
6091 * Applies an array of commands to the current URL tree and creates a new URL tree.
6092 *
6093 * When given an activate route, applies the given commands starting from the route.
6094 * Otherwise, applies the given command starting from the root.
6095 *
6096 * \@usageNotes
6097 *
6098 * ```
6099 * // create /team/33/user/11
6100 * router.createUrlTree(['/team', 33, 'user', 11]);
6101 *
6102 * // create /team/33;expand=true/user/11
6103 * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
6104 *
6105 * // you can collapse static segments like this (this works only with the first passed-in value):
6106 * router.createUrlTree(['/team/33/user', userId]);
6107 *
6108 * // If the first segment can contain slashes, and you do not want the router to split it,
6109 * // you can do the following:
6110 * router.createUrlTree([{segmentPath: '/one/two'}]);
6111 *
6112 * // create /team/33/(user/11//right:chat)
6113 * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
6114 *
6115 * // remove the right secondary node
6116 * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
6117 *
6118 * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
6119 *
6120 * // navigate to /team/33/user/11/details
6121 * router.createUrlTree(['details'], {relativeTo: route});
6122 *
6123 * // navigate to /team/33/user/22
6124 * router.createUrlTree(['../22'], {relativeTo: route});
6125 *
6126 * // navigate to /team/44/user/22
6127 * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
6128 * ```
6129 * @param {?} commands An array of commands to apply.
6130 * @param {?=} navigationExtras Options that control the navigation strategy.
6131 * @return {?} The new URL tree.
6132 *
6133 */
6134 createUrlTree(commands, navigationExtras = {}) {
6135 const { relativeTo, queryParams, fragment, preserveQueryParams, queryParamsHandling, preserveFragment } = navigationExtras;
6136 if (isDevMode() && preserveQueryParams && (/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) {
6137 console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
6138 }
6139 /** @type {?} */
6140 const a = relativeTo || this.routerState.root;
6141 /** @type {?} */
6142 const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
6143 /** @type {?} */
6144 let q = null;
6145 if (queryParamsHandling) {
6146 switch (queryParamsHandling) {
6147 case 'merge':
6148 q = Object.assign({}, this.currentUrlTree.queryParams, queryParams);
6149 break;
6150 case 'preserve':
6151 q = this.currentUrlTree.queryParams;
6152 break;
6153 default:
6154 q = queryParams || null;
6155 }
6156 }
6157 else {
6158 q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
6159 }
6160 if (q !== null) {
6161 q = this.removeEmptyProps(q);
6162 }
6163 return createUrlTree(a, this.currentUrlTree, commands, (/** @type {?} */ (q)), (/** @type {?} */ (f)));
6164 }
6165 /**
6166 * Navigate based on the provided URL, which must be absolute.
6167 *
6168 * \@usageNotes
6169 *
6170 * ```
6171 * router.navigateByUrl("/team/33/user/11");
6172 *
6173 * // Navigate without updating the URL
6174 * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
6175 * ```
6176 *
6177 * @param {?} url An absolute URL. The function does not apply any delta to the current URL.
6178 * @param {?=} extras An object containing properties that modify the navigation strategy.
6179 * The function ignores any properties in the `NavigationExtras` that would change the
6180 * provided URL.
6181 *
6182 * @return {?} A Promise that resolves to 'true' when navigation succeeds,
6183 * to 'false' when navigation fails, or is rejected on error.
6184 *
6185 */
6186 navigateByUrl(url, extras = { skipLocationChange: false }) {
6187 if (isDevMode() && this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
6188 this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
6189 }
6190 /** @type {?} */
6191 const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
6192 /** @type {?} */
6193 const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
6194 return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
6195 }
6196 /**
6197 * Navigate based on the provided array of commands and a starting point.
6198 * If no starting route is provided, the navigation is absolute.
6199 *
6200 * Returns a promise that:
6201 * - resolves to 'true' when navigation succeeds,
6202 * - resolves to 'false' when navigation fails,
6203 * - is rejected when an error happens.
6204 *
6205 * \@usageNotes
6206 *
6207 * ```
6208 * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
6209 *
6210 * // Navigate without updating the URL
6211 * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
6212 * ```
6213 *
6214 * The first parameter of `navigate()` is a delta to be applied to the current URL
6215 * or the one provided in the `relativeTo` property of the second parameter (the
6216 * `NavigationExtras`).
6217 *
6218 * In order to affect this browser's `history.state` entry, the `state`
6219 * parameter can be passed. This must be an object because the router
6220 * will add the `navigationId` property to this object before creating
6221 * the new history item.
6222 * @param {?} commands
6223 * @param {?=} extras
6224 * @return {?}
6225 */
6226 navigate(commands, extras = { skipLocationChange: false }) {
6227 validateCommands(commands);
6228 return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
6229 }
6230 /**
6231 * Serializes a `UrlTree` into a string
6232 * @param {?} url
6233 * @return {?}
6234 */
6235 serializeUrl(url) { return this.urlSerializer.serialize(url); }
6236 /**
6237 * Parses a string into a `UrlTree`
6238 * @param {?} url
6239 * @return {?}
6240 */
6241 parseUrl(url) {
6242 /** @type {?} */
6243 let urlTree;
6244 try {
6245 urlTree = this.urlSerializer.parse(url);
6246 }
6247 catch (e) {
6248 urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
6249 }
6250 return urlTree;
6251 }
6252 /**
6253 * Returns whether the url is activated
6254 * @param {?} url
6255 * @param {?} exact
6256 * @return {?}
6257 */
6258 isActive(url, exact) {
6259 if (isUrlTree(url)) {
6260 return containsTree(this.currentUrlTree, url, exact);
6261 }
6262 /** @type {?} */
6263 const urlTree = this.parseUrl(url);
6264 return containsTree(this.currentUrlTree, urlTree, exact);
6265 }
6266 /**
6267 * @private
6268 * @param {?} params
6269 * @return {?}
6270 */
6271 removeEmptyProps(params) {
6272 return Object.keys(params).reduce((/**
6273 * @param {?} result
6274 * @param {?} key
6275 * @return {?}
6276 */
6277 (result, key) => {
6278 /** @type {?} */
6279 const value = params[key];
6280 if (value !== null && value !== undefined) {
6281 result[key] = value;
6282 }
6283 return result;
6284 }), {});
6285 }
6286 /**
6287 * @private
6288 * @return {?}
6289 */
6290 processNavigations() {
6291 this.navigations.subscribe((/**
6292 * @param {?} t
6293 * @return {?}
6294 */
6295 t => {
6296 this.navigated = true;
6297 this.lastSuccessfulId = t.id;
6298 ((/** @type {?} */ (this.events)))
6299 .next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
6300 this.lastSuccessfulNavigation = this.currentNavigation;
6301 this.currentNavigation = null;
6302 t.resolve(true);
6303 }), (/**
6304 * @param {?} e
6305 * @return {?}
6306 */
6307 e => { this.console.warn(`Unhandled Navigation Error: `); }));
6308 }
6309 /**
6310 * @private
6311 * @param {?} rawUrl
6312 * @param {?} source
6313 * @param {?} restoredState
6314 * @param {?} extras
6315 * @return {?}
6316 */
6317 scheduleNavigation(rawUrl, source, restoredState, extras) {
6318 /** @type {?} */
6319 const lastNavigation = this.getTransition();
6320 // If the user triggers a navigation imperatively (e.g., by using navigateByUrl),
6321 // and that navigation results in 'replaceState' that leads to the same URL,
6322 // we should skip those.
6323 if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' &&
6324 lastNavigation.rawUrl.toString() === rawUrl.toString()) {
6325 return Promise.resolve(true); // return value is not used
6326 }
6327 // Because of a bug in IE and Edge, the location class fires two events (popstate and
6328 // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
6329 // flicker. Handles the case when a popstate was emitted first.
6330 if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' &&
6331 lastNavigation.rawUrl.toString() === rawUrl.toString()) {
6332 return Promise.resolve(true); // return value is not used
6333 }
6334 // Because of a bug in IE and Edge, the location class fires two events (popstate and
6335 // hashchange) every single time. The second one should be ignored. Otherwise, the URL will
6336 // flicker. Handles the case when a hashchange was emitted first.
6337 if (lastNavigation && source == 'popstate' && lastNavigation.source === 'hashchange' &&
6338 lastNavigation.rawUrl.toString() === rawUrl.toString()) {
6339 return Promise.resolve(true); // return value is not used
6340 }
6341 /** @type {?} */
6342 let resolve = null;
6343 /** @type {?} */
6344 let reject = null;
6345 /** @type {?} */
6346 const promise = new Promise((/**
6347 * @param {?} res
6348 * @param {?} rej
6349 * @return {?}
6350 */
6351 (res, rej) => {
6352 resolve = res;
6353 reject = rej;
6354 }));
6355 /** @type {?} */
6356 const id = ++this.navigationId;
6357 this.setTransition({
6358 id,
6359 source,
6360 restoredState,
6361 currentUrlTree: this.currentUrlTree,
6362 currentRawUrl: this.rawUrlTree, rawUrl, extras, resolve, reject, promise,
6363 currentSnapshot: this.routerState.snapshot,
6364 currentRouterState: this.routerState
6365 });
6366 // Make sure that the error is propagated even though `processNavigations` catch
6367 // handler does not rethrow
6368 return promise.catch((/**
6369 * @param {?} e
6370 * @return {?}
6371 */
6372 (e) => { return Promise.reject(e); }));
6373 }
6374 /**
6375 * @private
6376 * @param {?} url
6377 * @param {?} replaceUrl
6378 * @param {?} id
6379 * @param {?=} state
6380 * @return {?}
6381 */
6382 setBrowserUrl(url, replaceUrl, id, state) {
6383 /** @type {?} */
6384 const path = this.urlSerializer.serialize(url);
6385 state = state || {};
6386 if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
6387 // TODO(jasonaden): Remove first `navigationId` and rely on `ng` namespace.
6388 this.location.replaceState(path, '', Object.assign({}, state, { navigationId: id }));
6389 }
6390 else {
6391 this.location.go(path, '', Object.assign({}, state, { navigationId: id }));
6392 }
6393 }
6394 /**
6395 * @private
6396 * @param {?} storedState
6397 * @param {?} storedUrl
6398 * @param {?} rawUrl
6399 * @return {?}
6400 */
6401 resetStateAndUrl(storedState, storedUrl, rawUrl) {
6402 ((/** @type {?} */ (this))).routerState = storedState;
6403 this.currentUrlTree = storedUrl;
6404 this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, rawUrl);
6405 this.resetUrlToCurrentUrlTree();
6406 }
6407 /**
6408 * @private
6409 * @return {?}
6410 */
6411 resetUrlToCurrentUrlTree() {
6412 this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', { navigationId: this.lastSuccessfulId });
6413 }
6414}
6415/**
6416 * @param {?} commands
6417 * @return {?}
6418 */
6419function validateCommands(commands) {
6420 for (let i = 0; i < commands.length; i++) {
6421 /** @type {?} */
6422 const cmd = commands[i];
6423 if (cmd == null) {
6424 throw new Error(`The requested path contains ${cmd} segment at index ${i}`);
6425 }
6426 }
6427}
6428
6429/**
6430 * @fileoverview added by tsickle
6431 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
6432 */
6433/**
6434 * \@description
6435 *
6436 * Lets you link to specific routes in your app.
6437 *
6438 * Consider the following route configuration:
6439 * `[{ path: 'user/:name', component: UserCmp }]`.
6440 * When linking to this `user/:name` route, you use the `RouterLink` directive.
6441 *
6442 * If the link is static, you can use the directive as follows:
6443 * `<a routerLink="/user/bob">link to user component</a>`
6444 *
6445 * If you use dynamic values to generate the link, you can pass an array of path
6446 * segments, followed by the params for each segment.
6447 *
6448 * For instance `['/team', teamId, 'user', userName, {details: true}]`
6449 * means that we want to generate a link to `/team/11/user/bob;details=true`.
6450 *
6451 * Multiple static segments can be merged into one
6452 * (e.g., `['/team/11/user', userName, {details: true}]`).
6453 *
6454 * The first segment name can be prepended with `/`, `./`, or `../`:
6455 * * If the first segment begins with `/`, the router will look up the route from the root of the
6456 * app.
6457 * * If the first segment begins with `./`, or doesn't begin with a slash, the router will
6458 * instead look in the children of the current activated route.
6459 * * And if the first segment begins with `../`, the router will go up one level.
6460 *
6461 * You can set query params and fragment as follows:
6462 *
6463 * ```
6464 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
6465 * link to user component
6466 * </a>
6467 * ```
6468 * RouterLink will use these to generate this link: `/user/bob#education?debug=true`.
6469 *
6470 * (Deprecated in v4.0.0 use `queryParamsHandling` instead) You can also tell the
6471 * directive to preserve the current query params and fragment:
6472 *
6473 * ```
6474 * <a [routerLink]="['/user/bob']" preserveQueryParams preserveFragment>
6475 * link to user component
6476 * </a>
6477 * ```
6478 *
6479 * You can tell the directive how to handle queryParams. Available options are:
6480 * - `'merge'`: merge the queryParams into the current queryParams
6481 * - `'preserve'`: preserve the current queryParams
6482 * - default/`''`: use the queryParams only
6483 *
6484 * Same options for {\@link NavigationExtras#queryParamsHandling
6485 * NavigationExtras#queryParamsHandling}.
6486 *
6487 * ```
6488 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
6489 * link to user component
6490 * </a>
6491 * ```
6492 *
6493 * You can provide a `state` value to be persisted to the browser's History.state
6494 * property (See https://developer.mozilla.org/en-US/docs/Web/API/History#Properties). It's
6495 * used as follows:
6496 *
6497 * ```
6498 * <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}">
6499 * link to user component
6500 * </a>
6501 * ```
6502 *
6503 * And later the value can be read from the router through `router.getCurrentNavigation`.
6504 * For example, to capture the `tracingId` above during the `NavigationStart` event:
6505 *
6506 * ```
6507 * // Get NavigationStart events
6508 * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {
6509 * const navigation = router.getCurrentNavigation();
6510 * tracingService.trace({id: navigation.extras.state.tracingId});
6511 * });
6512 * ```
6513 *
6514 * The router link directive always treats the provided input as a delta to the current url.
6515 *
6516 * For instance, if the current url is `/user/(box//aux:team)`.
6517 *
6518 * Then the following link `<a [routerLink]="['/user/jim']">Jim</a>` will generate the link
6519 * `/user/(jim//aux:team)`.
6520 *
6521 * See {\@link Router#createUrlTree createUrlTree} for more information.
6522 *
6523 * \@ngModule RouterModule
6524 *
6525 * \@publicApi
6526 */
6527class RouterLink {
6528 /**
6529 * @param {?} router
6530 * @param {?} route
6531 * @param {?} tabIndex
6532 * @param {?} renderer
6533 * @param {?} el
6534 */
6535 constructor(router, route, tabIndex, renderer, el) {
6536 this.router = router;
6537 this.route = route;
6538 this.commands = [];
6539 if (tabIndex == null) {
6540 renderer.setAttribute(el.nativeElement, 'tabindex', '0');
6541 }
6542 }
6543 /**
6544 * @param {?} commands
6545 * @return {?}
6546 */
6547 set routerLink(commands) {
6548 if (commands != null) {
6549 this.commands = Array.isArray(commands) ? commands : [commands];
6550 }
6551 else {
6552 this.commands = [];
6553 }
6554 }
6555 /**
6556 * @deprecated 4.0.0 use `queryParamsHandling` instead.
6557 * @param {?} value
6558 * @return {?}
6559 */
6560 set preserveQueryParams(value) {
6561 if (isDevMode() && (/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) {
6562 console.warn('preserveQueryParams is deprecated!, use queryParamsHandling instead.');
6563 }
6564 this.preserve = value;
6565 }
6566 /**
6567 * @return {?}
6568 */
6569 onClick() {
6570 /** @type {?} */
6571 const extras = {
6572 skipLocationChange: attrBoolValue(this.skipLocationChange),
6573 replaceUrl: attrBoolValue(this.replaceUrl),
6574 };
6575 this.router.navigateByUrl(this.urlTree, extras);
6576 return true;
6577 }
6578 /**
6579 * @return {?}
6580 */
6581 get urlTree() {
6582 return this.router.createUrlTree(this.commands, {
6583 relativeTo: this.route,
6584 queryParams: this.queryParams,
6585 fragment: this.fragment,
6586 preserveQueryParams: attrBoolValue(this.preserve),
6587 queryParamsHandling: this.queryParamsHandling,
6588 preserveFragment: attrBoolValue(this.preserveFragment),
6589 });
6590 }
6591}
6592RouterLink.decorators = [
6593 { type: Directive, args: [{ selector: ':not(a):not(area)[routerLink]' },] }
6594];
6595/** @nocollapse */
6596RouterLink.ctorParameters = () => [
6597 { type: Router },
6598 { type: ActivatedRoute },
6599 { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] },
6600 { type: Renderer2 },
6601 { type: ElementRef }
6602];
6603RouterLink.propDecorators = {
6604 queryParams: [{ type: Input }],
6605 fragment: [{ type: Input }],
6606 queryParamsHandling: [{ type: Input }],
6607 preserveFragment: [{ type: Input }],
6608 skipLocationChange: [{ type: Input }],
6609 replaceUrl: [{ type: Input }],
6610 state: [{ type: Input }],
6611 routerLink: [{ type: Input }],
6612 preserveQueryParams: [{ type: Input }],
6613 onClick: [{ type: HostListener, args: ['click',] }]
6614};
6615/**
6616 * \@description
6617 *
6618 * Lets you link to specific routes in your app.
6619 *
6620 * See `RouterLink` for more information.
6621 *
6622 * \@ngModule RouterModule
6623 *
6624 * \@publicApi
6625 */
6626class RouterLinkWithHref {
6627 /**
6628 * @param {?} router
6629 * @param {?} route
6630 * @param {?} locationStrategy
6631 */
6632 constructor(router, route, locationStrategy) {
6633 this.router = router;
6634 this.route = route;
6635 this.locationStrategy = locationStrategy;
6636 this.commands = [];
6637 this.subscription = router.events.subscribe((/**
6638 * @param {?} s
6639 * @return {?}
6640 */
6641 (s) => {
6642 if (s instanceof NavigationEnd) {
6643 this.updateTargetUrlAndHref();
6644 }
6645 }));
6646 }
6647 /**
6648 * @param {?} commands
6649 * @return {?}
6650 */
6651 set routerLink(commands) {
6652 if (commands != null) {
6653 this.commands = Array.isArray(commands) ? commands : [commands];
6654 }
6655 else {
6656 this.commands = [];
6657 }
6658 }
6659 /**
6660 * @param {?} value
6661 * @return {?}
6662 */
6663 set preserveQueryParams(value) {
6664 if (isDevMode() && (/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) {
6665 console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.');
6666 }
6667 this.preserve = value;
6668 }
6669 /**
6670 * @param {?} changes
6671 * @return {?}
6672 */
6673 ngOnChanges(changes) { this.updateTargetUrlAndHref(); }
6674 /**
6675 * @return {?}
6676 */
6677 ngOnDestroy() { this.subscription.unsubscribe(); }
6678 /**
6679 * @param {?} button
6680 * @param {?} ctrlKey
6681 * @param {?} metaKey
6682 * @param {?} shiftKey
6683 * @return {?}
6684 */
6685 onClick(button, ctrlKey, metaKey, shiftKey) {
6686 if (button !== 0 || ctrlKey || metaKey || shiftKey) {
6687 return true;
6688 }
6689 if (typeof this.target === 'string' && this.target != '_self') {
6690 return true;
6691 }
6692 /** @type {?} */
6693 const extras = {
6694 skipLocationChange: attrBoolValue(this.skipLocationChange),
6695 replaceUrl: attrBoolValue(this.replaceUrl),
6696 state: this.state
6697 };
6698 this.router.navigateByUrl(this.urlTree, extras);
6699 return false;
6700 }
6701 /**
6702 * @private
6703 * @return {?}
6704 */
6705 updateTargetUrlAndHref() {
6706 this.href = this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree));
6707 }
6708 /**
6709 * @return {?}
6710 */
6711 get urlTree() {
6712 return this.router.createUrlTree(this.commands, {
6713 relativeTo: this.route,
6714 queryParams: this.queryParams,
6715 fragment: this.fragment,
6716 preserveQueryParams: attrBoolValue(this.preserve),
6717 queryParamsHandling: this.queryParamsHandling,
6718 preserveFragment: attrBoolValue(this.preserveFragment),
6719 });
6720 }
6721}
6722RouterLinkWithHref.decorators = [
6723 { type: Directive, args: [{ selector: 'a[routerLink],area[routerLink]' },] }
6724];
6725/** @nocollapse */
6726RouterLinkWithHref.ctorParameters = () => [
6727 { type: Router },
6728 { type: ActivatedRoute },
6729 { type: LocationStrategy }
6730];
6731RouterLinkWithHref.propDecorators = {
6732 target: [{ type: HostBinding, args: ['attr.target',] }, { type: Input }],
6733 queryParams: [{ type: Input }],
6734 fragment: [{ type: Input }],
6735 queryParamsHandling: [{ type: Input }],
6736 preserveFragment: [{ type: Input }],
6737 skipLocationChange: [{ type: Input }],
6738 replaceUrl: [{ type: Input }],
6739 state: [{ type: Input }],
6740 href: [{ type: HostBinding }],
6741 routerLink: [{ type: Input }],
6742 preserveQueryParams: [{ type: Input }],
6743 onClick: [{ type: HostListener, args: ['click', ['$event.button', '$event.ctrlKey', '$event.metaKey', '$event.shiftKey'],] }]
6744};
6745/**
6746 * @param {?} s
6747 * @return {?}
6748 */
6749function attrBoolValue(s) {
6750 return s === '' || !!s;
6751}
6752
6753/**
6754 * @fileoverview added by tsickle
6755 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
6756 */
6757/**
6758 *
6759 * \@description
6760 *
6761 * Lets you add a CSS class to an element when the link's route becomes active.
6762 *
6763 * This directive lets you add a CSS class to an element when the link's route
6764 * becomes active.
6765 *
6766 * Consider the following example:
6767 *
6768 * ```
6769 * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
6770 * ```
6771 *
6772 * When the url is either '/user' or '/user/bob', the active-link class will
6773 * be added to the `a` tag. If the url changes, the class will be removed.
6774 *
6775 * You can set more than one class, as follows:
6776 *
6777 * ```
6778 * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
6779 * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
6780 * ```
6781 *
6782 * You can configure RouterLinkActive by passing `exact: true`. This will add the classes
6783 * only when the url matches the link exactly.
6784 *
6785 * ```
6786 * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
6787 * true}">Bob</a>
6788 * ```
6789 *
6790 * You can assign the RouterLinkActive instance to a template variable and directly check
6791 * the `isActive` status.
6792 * ```
6793 * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
6794 * Bob {{ rla.isActive ? '(already open)' : ''}}
6795 * </a>
6796 * ```
6797 *
6798 * Finally, you can apply the RouterLinkActive directive to an ancestor of a RouterLink.
6799 *
6800 * ```
6801 * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
6802 * <a routerLink="/user/jim">Jim</a>
6803 * <a routerLink="/user/bob">Bob</a>
6804 * </div>
6805 * ```
6806 *
6807 * This will set the active-link class on the div tag if the url is either '/user/jim' or
6808 * '/user/bob'.
6809 *
6810 * \@ngModule RouterModule
6811 *
6812 * \@publicApi
6813 */
6814class RouterLinkActive {
6815 /**
6816 * @param {?} router
6817 * @param {?} element
6818 * @param {?} renderer
6819 * @param {?=} link
6820 * @param {?=} linkWithHref
6821 */
6822 constructor(router, element, renderer, link, linkWithHref) {
6823 this.router = router;
6824 this.element = element;
6825 this.renderer = renderer;
6826 this.link = link;
6827 this.linkWithHref = linkWithHref;
6828 this.classes = [];
6829 this.isActive = false;
6830 this.routerLinkActiveOptions = { exact: false };
6831 this.subscription = router.events.subscribe((/**
6832 * @param {?} s
6833 * @return {?}
6834 */
6835 (s) => {
6836 if (s instanceof NavigationEnd) {
6837 this.update();
6838 }
6839 }));
6840 }
6841 /**
6842 * @return {?}
6843 */
6844 ngAfterContentInit() {
6845 this.links.changes.subscribe((/**
6846 * @param {?} _
6847 * @return {?}
6848 */
6849 _ => this.update()));
6850 this.linksWithHrefs.changes.subscribe((/**
6851 * @param {?} _
6852 * @return {?}
6853 */
6854 _ => this.update()));
6855 this.update();
6856 }
6857 /**
6858 * @param {?} data
6859 * @return {?}
6860 */
6861 set routerLinkActive(data) {
6862 /** @type {?} */
6863 const classes = Array.isArray(data) ? data : data.split(' ');
6864 this.classes = classes.filter((/**
6865 * @param {?} c
6866 * @return {?}
6867 */
6868 c => !!c));
6869 }
6870 /**
6871 * @param {?} changes
6872 * @return {?}
6873 */
6874 ngOnChanges(changes) { this.update(); }
6875 /**
6876 * @return {?}
6877 */
6878 ngOnDestroy() { this.subscription.unsubscribe(); }
6879 /**
6880 * @private
6881 * @return {?}
6882 */
6883 update() {
6884 if (!this.links || !this.linksWithHrefs || !this.router.navigated)
6885 return;
6886 Promise.resolve().then((/**
6887 * @return {?}
6888 */
6889 () => {
6890 /** @type {?} */
6891 const hasActiveLinks = this.hasActiveLinks();
6892 if (this.isActive !== hasActiveLinks) {
6893 ((/** @type {?} */ (this))).isActive = hasActiveLinks;
6894 this.classes.forEach((/**
6895 * @param {?} c
6896 * @return {?}
6897 */
6898 (c) => {
6899 if (hasActiveLinks) {
6900 this.renderer.addClass(this.element.nativeElement, c);
6901 }
6902 else {
6903 this.renderer.removeClass(this.element.nativeElement, c);
6904 }
6905 }));
6906 }
6907 }));
6908 }
6909 /**
6910 * @private
6911 * @param {?} router
6912 * @return {?}
6913 */
6914 isLinkActive(router) {
6915 return (/**
6916 * @param {?} link
6917 * @return {?}
6918 */
6919 (link) => router.isActive(link.urlTree, this.routerLinkActiveOptions.exact));
6920 }
6921 /**
6922 * @private
6923 * @return {?}
6924 */
6925 hasActiveLinks() {
6926 /** @type {?} */
6927 const isActiveCheckFn = this.isLinkActive(this.router);
6928 return this.link && isActiveCheckFn(this.link) ||
6929 this.linkWithHref && isActiveCheckFn(this.linkWithHref) ||
6930 this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
6931 }
6932}
6933RouterLinkActive.decorators = [
6934 { type: Directive, args: [{
6935 selector: '[routerLinkActive]',
6936 exportAs: 'routerLinkActive',
6937 },] }
6938];
6939/** @nocollapse */
6940RouterLinkActive.ctorParameters = () => [
6941 { type: Router },
6942 { type: ElementRef },
6943 { type: Renderer2 },
6944 { type: RouterLink, decorators: [{ type: Optional }] },
6945 { type: RouterLinkWithHref, decorators: [{ type: Optional }] }
6946];
6947RouterLinkActive.propDecorators = {
6948 links: [{ type: ContentChildren, args: [RouterLink, { descendants: true },] }],
6949 linksWithHrefs: [{ type: ContentChildren, args: [RouterLinkWithHref, { descendants: true },] }],
6950 routerLinkActiveOptions: [{ type: Input }],
6951 routerLinkActive: [{ type: Input }]
6952};
6953
6954/**
6955 * @fileoverview added by tsickle
6956 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
6957 */
6958/**
6959 * @license
6960 * Copyright Google Inc. All Rights Reserved.
6961 *
6962 * Use of this source code is governed by an MIT-style license that can be
6963 * found in the LICENSE file at https://angular.io/license
6964 */
6965/**
6966 * Store contextual information about a `RouterOutlet`
6967 *
6968 * \@publicApi
6969 */
6970class OutletContext {
6971 constructor() {
6972 this.outlet = null;
6973 this.route = null;
6974 this.resolver = null;
6975 this.children = new ChildrenOutletContexts();
6976 this.attachRef = null;
6977 }
6978}
6979/**
6980 * Store contextual information about the children (= nested) `RouterOutlet`
6981 *
6982 * \@publicApi
6983 */
6984class ChildrenOutletContexts {
6985 constructor() {
6986 // contexts for child outlets, by name.
6987 this.contexts = new Map();
6988 }
6989 /**
6990 * Called when a `RouterOutlet` directive is instantiated
6991 * @param {?} childName
6992 * @param {?} outlet
6993 * @return {?}
6994 */
6995 onChildOutletCreated(childName, outlet) {
6996 /** @type {?} */
6997 const context = this.getOrCreateContext(childName);
6998 context.outlet = outlet;
6999 this.contexts.set(childName, context);
7000 }
7001 /**
7002 * Called when a `RouterOutlet` directive is destroyed.
7003 * We need to keep the context as the outlet could be destroyed inside a NgIf and might be
7004 * re-created later.
7005 * @param {?} childName
7006 * @return {?}
7007 */
7008 onChildOutletDestroyed(childName) {
7009 /** @type {?} */
7010 const context = this.getContext(childName);
7011 if (context) {
7012 context.outlet = null;
7013 }
7014 }
7015 /**
7016 * Called when the corresponding route is deactivated during navigation.
7017 * Because the component get destroyed, all children outlet are destroyed.
7018 * @return {?}
7019 */
7020 onOutletDeactivated() {
7021 /** @type {?} */
7022 const contexts = this.contexts;
7023 this.contexts = new Map();
7024 return contexts;
7025 }
7026 /**
7027 * @param {?} contexts
7028 * @return {?}
7029 */
7030 onOutletReAttached(contexts) { this.contexts = contexts; }
7031 /**
7032 * @param {?} childName
7033 * @return {?}
7034 */
7035 getOrCreateContext(childName) {
7036 /** @type {?} */
7037 let context = this.getContext(childName);
7038 if (!context) {
7039 context = new OutletContext();
7040 this.contexts.set(childName, context);
7041 }
7042 return context;
7043 }
7044 /**
7045 * @param {?} childName
7046 * @return {?}
7047 */
7048 getContext(childName) { return this.contexts.get(childName) || null; }
7049}
7050
7051/**
7052 * @fileoverview added by tsickle
7053 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7054 */
7055/**
7056 * \@description
7057 *
7058 * Acts as a placeholder that Angular dynamically fills based on the current router state.
7059 *
7060 * ```
7061 * <router-outlet></router-outlet>
7062 * <router-outlet name='left'></router-outlet>
7063 * <router-outlet name='right'></router-outlet>
7064 * ```
7065 *
7066 * A router outlet will emit an activate event any time a new component is being instantiated,
7067 * and a deactivate event when it is being destroyed.
7068 *
7069 * ```
7070 * <router-outlet
7071 * (activate)='onActivate($event)'
7072 * (deactivate)='onDeactivate($event)'></router-outlet>
7073 * ```
7074 * \@ngModule RouterModule
7075 *
7076 * \@publicApi
7077 */
7078class RouterOutlet {
7079 /**
7080 * @param {?} parentContexts
7081 * @param {?} location
7082 * @param {?} resolver
7083 * @param {?} name
7084 * @param {?} changeDetector
7085 */
7086 constructor(parentContexts, location, resolver, name, changeDetector) {
7087 this.parentContexts = parentContexts;
7088 this.location = location;
7089 this.resolver = resolver;
7090 this.changeDetector = changeDetector;
7091 this.activated = null;
7092 this._activatedRoute = null;
7093 this.activateEvents = new EventEmitter();
7094 this.deactivateEvents = new EventEmitter();
7095 this.name = name || PRIMARY_OUTLET;
7096 parentContexts.onChildOutletCreated(this.name, this);
7097 }
7098 /**
7099 * @return {?}
7100 */
7101 ngOnDestroy() { this.parentContexts.onChildOutletDestroyed(this.name); }
7102 /**
7103 * @return {?}
7104 */
7105 ngOnInit() {
7106 if (!this.activated) {
7107 // If the outlet was not instantiated at the time the route got activated we need to populate
7108 // the outlet when it is initialized (ie inside a NgIf)
7109 /** @type {?} */
7110 const context = this.parentContexts.getContext(this.name);
7111 if (context && context.route) {
7112 if (context.attachRef) {
7113 // `attachRef` is populated when there is an existing component to mount
7114 this.attach(context.attachRef, context.route);
7115 }
7116 else {
7117 // otherwise the component defined in the configuration is created
7118 this.activateWith(context.route, context.resolver || null);
7119 }
7120 }
7121 }
7122 }
7123 /**
7124 * @return {?}
7125 */
7126 get isActivated() { return !!this.activated; }
7127 /**
7128 * @return {?}
7129 */
7130 get component() {
7131 if (!this.activated)
7132 throw new Error('Outlet is not activated');
7133 return this.activated.instance;
7134 }
7135 /**
7136 * @return {?}
7137 */
7138 get activatedRoute() {
7139 if (!this.activated)
7140 throw new Error('Outlet is not activated');
7141 return (/** @type {?} */ (this._activatedRoute));
7142 }
7143 /**
7144 * @return {?}
7145 */
7146 get activatedRouteData() {
7147 if (this._activatedRoute) {
7148 return this._activatedRoute.snapshot.data;
7149 }
7150 return {};
7151 }
7152 /**
7153 * Called when the `RouteReuseStrategy` instructs to detach the subtree
7154 * @return {?}
7155 */
7156 detach() {
7157 if (!this.activated)
7158 throw new Error('Outlet is not activated');
7159 this.location.detach();
7160 /** @type {?} */
7161 const cmp = this.activated;
7162 this.activated = null;
7163 this._activatedRoute = null;
7164 return cmp;
7165 }
7166 /**
7167 * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
7168 * @param {?} ref
7169 * @param {?} activatedRoute
7170 * @return {?}
7171 */
7172 attach(ref, activatedRoute) {
7173 this.activated = ref;
7174 this._activatedRoute = activatedRoute;
7175 this.location.insert(ref.hostView);
7176 }
7177 /**
7178 * @return {?}
7179 */
7180 deactivate() {
7181 if (this.activated) {
7182 /** @type {?} */
7183 const c = this.component;
7184 this.activated.destroy();
7185 this.activated = null;
7186 this._activatedRoute = null;
7187 this.deactivateEvents.emit(c);
7188 }
7189 }
7190 /**
7191 * @param {?} activatedRoute
7192 * @param {?} resolver
7193 * @return {?}
7194 */
7195 activateWith(activatedRoute, resolver) {
7196 if (this.isActivated) {
7197 throw new Error('Cannot activate an already activated outlet');
7198 }
7199 this._activatedRoute = activatedRoute;
7200 /** @type {?} */
7201 const snapshot = activatedRoute._futureSnapshot;
7202 /** @type {?} */
7203 const component = (/** @type {?} */ ((/** @type {?} */ (snapshot.routeConfig)).component));
7204 resolver = resolver || this.resolver;
7205 /** @type {?} */
7206 const factory = resolver.resolveComponentFactory(component);
7207 /** @type {?} */
7208 const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
7209 /** @type {?} */
7210 const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
7211 this.activated = this.location.createComponent(factory, this.location.length, injector);
7212 // Calling `markForCheck` to make sure we will run the change detection when the
7213 // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
7214 this.changeDetector.markForCheck();
7215 this.activateEvents.emit(this.activated.instance);
7216 }
7217}
7218RouterOutlet.decorators = [
7219 { type: Directive, args: [{ selector: 'router-outlet', exportAs: 'outlet' },] }
7220];
7221/** @nocollapse */
7222RouterOutlet.ctorParameters = () => [
7223 { type: ChildrenOutletContexts },
7224 { type: ViewContainerRef },
7225 { type: ComponentFactoryResolver },
7226 { type: String, decorators: [{ type: Attribute, args: ['name',] }] },
7227 { type: ChangeDetectorRef }
7228];
7229RouterOutlet.propDecorators = {
7230 activateEvents: [{ type: Output, args: ['activate',] }],
7231 deactivateEvents: [{ type: Output, args: ['deactivate',] }]
7232};
7233class OutletInjector {
7234 /**
7235 * @param {?} route
7236 * @param {?} childContexts
7237 * @param {?} parent
7238 */
7239 constructor(route, childContexts, parent) {
7240 this.route = route;
7241 this.childContexts = childContexts;
7242 this.parent = parent;
7243 }
7244 /**
7245 * @param {?} token
7246 * @param {?=} notFoundValue
7247 * @return {?}
7248 */
7249 get(token, notFoundValue) {
7250 if (token === ActivatedRoute) {
7251 return this.route;
7252 }
7253 if (token === ChildrenOutletContexts) {
7254 return this.childContexts;
7255 }
7256 return this.parent.get(token, notFoundValue);
7257 }
7258}
7259
7260/**
7261 * @fileoverview added by tsickle
7262 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7263 */
7264/**
7265 * \@description
7266 *
7267 * Provides a preloading strategy.
7268 *
7269 * \@publicApi
7270 * @abstract
7271 */
7272class PreloadingStrategy {
7273}
7274/**
7275 * \@description
7276 *
7277 * Provides a preloading strategy that preloads all modules as quickly as possible.
7278 *
7279 * ```
7280 * RouteModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
7281 * ```
7282 *
7283 * \@publicApi
7284 */
7285class PreloadAllModules {
7286 /**
7287 * @param {?} route
7288 * @param {?} fn
7289 * @return {?}
7290 */
7291 preload(route, fn) {
7292 return fn().pipe(catchError((/**
7293 * @return {?}
7294 */
7295 () => of(null))));
7296 }
7297}
7298/**
7299 * \@description
7300 *
7301 * Provides a preloading strategy that does not preload any modules.
7302 *
7303 * This strategy is enabled by default.
7304 *
7305 * \@publicApi
7306 */
7307class NoPreloading {
7308 /**
7309 * @param {?} route
7310 * @param {?} fn
7311 * @return {?}
7312 */
7313 preload(route, fn) { return of(null); }
7314}
7315/**
7316 * The preloader optimistically loads all router configurations to
7317 * make navigations into lazily-loaded sections of the application faster.
7318 *
7319 * The preloader runs in the background. When the router bootstraps, the preloader
7320 * starts listening to all navigation events. After every such event, the preloader
7321 * will check if any configurations can be loaded lazily.
7322 *
7323 * If a route is protected by `canLoad` guards, the preloaded will not load it.
7324 *
7325 * \@publicApi
7326 */
7327class RouterPreloader {
7328 /**
7329 * @param {?} router
7330 * @param {?} moduleLoader
7331 * @param {?} compiler
7332 * @param {?} injector
7333 * @param {?} preloadingStrategy
7334 */
7335 constructor(router, moduleLoader, compiler, injector, preloadingStrategy) {
7336 this.router = router;
7337 this.injector = injector;
7338 this.preloadingStrategy = preloadingStrategy;
7339 /** @type {?} */
7340 const onStartLoad = (/**
7341 * @param {?} r
7342 * @return {?}
7343 */
7344 (r) => router.triggerEvent(new RouteConfigLoadStart(r)));
7345 /** @type {?} */
7346 const onEndLoad = (/**
7347 * @param {?} r
7348 * @return {?}
7349 */
7350 (r) => router.triggerEvent(new RouteConfigLoadEnd(r)));
7351 this.loader = new RouterConfigLoader(moduleLoader, compiler, onStartLoad, onEndLoad);
7352 }
7353 /**
7354 * @return {?}
7355 */
7356 setUpPreloading() {
7357 this.subscription =
7358 this.router.events
7359 .pipe(filter((/**
7360 * @param {?} e
7361 * @return {?}
7362 */
7363 (e) => e instanceof NavigationEnd)), concatMap((/**
7364 * @return {?}
7365 */
7366 () => this.preload())))
7367 .subscribe((/**
7368 * @return {?}
7369 */
7370 () => { }));
7371 }
7372 /**
7373 * @return {?}
7374 */
7375 preload() {
7376 /** @type {?} */
7377 const ngModule = this.injector.get(NgModuleRef);
7378 return this.processRoutes(ngModule, this.router.config);
7379 }
7380 // TODO(jasonaden): This class relies on code external to the class to call setUpPreloading. If
7381 // this hasn't been done, ngOnDestroy will fail as this.subscription will be undefined. This
7382 // should be refactored.
7383 /**
7384 * @return {?}
7385 */
7386 ngOnDestroy() { this.subscription.unsubscribe(); }
7387 /**
7388 * @private
7389 * @param {?} ngModule
7390 * @param {?} routes
7391 * @return {?}
7392 */
7393 processRoutes(ngModule, routes) {
7394 /** @type {?} */
7395 const res = [];
7396 for (const route of routes) {
7397 // we already have the config loaded, just recurse
7398 if (route.loadChildren && !route.canLoad && route._loadedConfig) {
7399 /** @type {?} */
7400 const childConfig = route._loadedConfig;
7401 res.push(this.processRoutes(childConfig.module, childConfig.routes));
7402 // no config loaded, fetch the config
7403 }
7404 else if (route.loadChildren && !route.canLoad) {
7405 res.push(this.preloadConfig(ngModule, route));
7406 // recurse into children
7407 }
7408 else if (route.children) {
7409 res.push(this.processRoutes(ngModule, route.children));
7410 }
7411 }
7412 return from(res).pipe(mergeAll(), map((/**
7413 * @param {?} _
7414 * @return {?}
7415 */
7416 (_) => void 0)));
7417 }
7418 /**
7419 * @private
7420 * @param {?} ngModule
7421 * @param {?} route
7422 * @return {?}
7423 */
7424 preloadConfig(ngModule, route) {
7425 return this.preloadingStrategy.preload(route, (/**
7426 * @return {?}
7427 */
7428 () => {
7429 /** @type {?} */
7430 const loaded$ = this.loader.load(ngModule.injector, route);
7431 return loaded$.pipe(mergeMap((/**
7432 * @param {?} config
7433 * @return {?}
7434 */
7435 (config) => {
7436 route._loadedConfig = config;
7437 return this.processRoutes(config.module, config.routes);
7438 })));
7439 }));
7440 }
7441}
7442RouterPreloader.decorators = [
7443 { type: Injectable }
7444];
7445/** @nocollapse */
7446RouterPreloader.ctorParameters = () => [
7447 { type: Router },
7448 { type: NgModuleFactoryLoader },
7449 { type: Compiler },
7450 { type: Injector },
7451 { type: PreloadingStrategy }
7452];
7453
7454/**
7455 * @fileoverview added by tsickle
7456 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7457 */
7458class RouterScroller {
7459 /**
7460 * @param {?} router
7461 * @param {?} viewportScroller
7462 * @param {?=} options
7463 */
7464 constructor(router, viewportScroller, options = {}) {
7465 this.router = router;
7466 this.viewportScroller = viewportScroller;
7467 this.options = options;
7468 this.lastId = 0;
7469 this.lastSource = 'imperative';
7470 this.restoredId = 0;
7471 this.store = {};
7472 // Default both options to 'disabled'
7473 options.scrollPositionRestoration = options.scrollPositionRestoration || 'disabled';
7474 options.anchorScrolling = options.anchorScrolling || 'disabled';
7475 }
7476 /**
7477 * @return {?}
7478 */
7479 init() {
7480 // we want to disable the automatic scrolling because having two places
7481 // responsible for scrolling results race conditions, especially given
7482 // that browser don't implement this behavior consistently
7483 if (this.options.scrollPositionRestoration !== 'disabled') {
7484 this.viewportScroller.setHistoryScrollRestoration('manual');
7485 }
7486 this.routerEventsSubscription = this.createScrollEvents();
7487 this.scrollEventsSubscription = this.consumeScrollEvents();
7488 }
7489 /**
7490 * @private
7491 * @return {?}
7492 */
7493 createScrollEvents() {
7494 return this.router.events.subscribe((/**
7495 * @param {?} e
7496 * @return {?}
7497 */
7498 e => {
7499 if (e instanceof NavigationStart) {
7500 // store the scroll position of the current stable navigations.
7501 this.store[this.lastId] = this.viewportScroller.getScrollPosition();
7502 this.lastSource = e.navigationTrigger;
7503 this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
7504 }
7505 else if (e instanceof NavigationEnd) {
7506 this.lastId = e.id;
7507 this.scheduleScrollEvent(e, this.router.parseUrl(e.urlAfterRedirects).fragment);
7508 }
7509 }));
7510 }
7511 /**
7512 * @private
7513 * @return {?}
7514 */
7515 consumeScrollEvents() {
7516 return this.router.events.subscribe((/**
7517 * @param {?} e
7518 * @return {?}
7519 */
7520 e => {
7521 if (!(e instanceof Scroll))
7522 return;
7523 // a popstate event. The pop state event will always ignore anchor scrolling.
7524 if (e.position) {
7525 if (this.options.scrollPositionRestoration === 'top') {
7526 this.viewportScroller.scrollToPosition([0, 0]);
7527 }
7528 else if (this.options.scrollPositionRestoration === 'enabled') {
7529 this.viewportScroller.scrollToPosition(e.position);
7530 }
7531 // imperative navigation "forward"
7532 }
7533 else {
7534 if (e.anchor && this.options.anchorScrolling === 'enabled') {
7535 this.viewportScroller.scrollToAnchor(e.anchor);
7536 }
7537 else if (this.options.scrollPositionRestoration !== 'disabled') {
7538 this.viewportScroller.scrollToPosition([0, 0]);
7539 }
7540 }
7541 }));
7542 }
7543 /**
7544 * @private
7545 * @param {?} routerEvent
7546 * @param {?} anchor
7547 * @return {?}
7548 */
7549 scheduleScrollEvent(routerEvent, anchor) {
7550 this.router.triggerEvent(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
7551 }
7552 /**
7553 * @return {?}
7554 */
7555 ngOnDestroy() {
7556 if (this.routerEventsSubscription) {
7557 this.routerEventsSubscription.unsubscribe();
7558 }
7559 if (this.scrollEventsSubscription) {
7560 this.scrollEventsSubscription.unsubscribe();
7561 }
7562 }
7563}
7564
7565/**
7566 * @fileoverview added by tsickle
7567 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
7568 */
7569/**
7570 * The directives defined in the `RouterModule`.
7571 * @type {?}
7572 */
7573const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent];
7574/**
7575 * A [DI token](guide/glossary/#di-token) for the router service.
7576 *
7577 * \@publicApi
7578 * @type {?}
7579 */
7580const ROUTER_CONFIGURATION = new InjectionToken('ROUTER_CONFIGURATION');
7581/**
7582 * \@docsNotRequired
7583 * @type {?}
7584 */
7585const ROUTER_FORROOT_GUARD = new InjectionToken('ROUTER_FORROOT_GUARD');
7586const ɵ0 = { enableTracing: false };
7587/** @type {?} */
7588const ROUTER_PROVIDERS = [
7589 Location,
7590 { provide: UrlSerializer, useClass: DefaultUrlSerializer },
7591 {
7592 provide: Router,
7593 useFactory: setupRouter,
7594 deps: [
7595 ApplicationRef, UrlSerializer, ChildrenOutletContexts, Location, Injector,
7596 NgModuleFactoryLoader, Compiler, ROUTES, ROUTER_CONFIGURATION,
7597 [UrlHandlingStrategy, new Optional()], [RouteReuseStrategy, new Optional()]
7598 ]
7599 },
7600 ChildrenOutletContexts,
7601 { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
7602 { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader },
7603 RouterPreloader,
7604 NoPreloading,
7605 PreloadAllModules,
7606 { provide: ROUTER_CONFIGURATION, useValue: ɵ0 },
7607];
7608/**
7609 * @return {?}
7610 */
7611function routerNgProbeToken() {
7612 return new NgProbeToken('Router', Router);
7613}
7614/**
7615 * \@usageNotes
7616 *
7617 * RouterModule can be imported multiple times: once per lazily-loaded bundle.
7618 * Since the router deals with a global shared resource--location, we cannot have
7619 * more than one router service active.
7620 *
7621 * That is why there are two ways to create the module: `RouterModule.forRoot` and
7622 * `RouterModule.forChild`.
7623 *
7624 * * `forRoot` creates a module that contains all the directives, the given routes, and the router
7625 * service itself.
7626 * * `forChild` creates a module that contains all the directives and the given routes, but does not
7627 * include the router service.
7628 *
7629 * When registered at the root, the module should be used as follows
7630 *
7631 * ```
7632 * \@NgModule({
7633 * imports: [RouterModule.forRoot(ROUTES)]
7634 * })
7635 * class MyNgModule {}
7636 * ```
7637 *
7638 * For submodules and lazy loaded submodules the module should be used as follows:
7639 *
7640 * ```
7641 * \@NgModule({
7642 * imports: [RouterModule.forChild(ROUTES)]
7643 * })
7644 * class MyNgModule {}
7645 * ```
7646 *
7647 * \@description
7648 *
7649 * Adds router directives and providers.
7650 *
7651 * Managing state transitions is one of the hardest parts of building applications. This is
7652 * especially true on the web, where you also need to ensure that the state is reflected in the URL.
7653 * In addition, we often want to split applications into multiple bundles and load them on demand.
7654 * Doing this transparently is not trivial.
7655 *
7656 * The Angular router service solves these problems. Using the router, you can declaratively specify
7657 * application states, manage state transitions while taking care of the URL, and load bundles on
7658 * demand.
7659 *
7660 * @see [Routing and Navigation](guide/router.html) for an
7661 * overview of how the router service should be used.
7662 *
7663 * \@publicApi
7664 */
7665class RouterModule {
7666 // Note: We are injecting the Router so it gets created eagerly...
7667 /**
7668 * @param {?} guard
7669 * @param {?} router
7670 */
7671 constructor(guard, router) { }
7672 /**
7673 * Creates and configures a module with all the router providers and directives.
7674 * Optionally sets up an application listener to perform an initial navigation.
7675 *
7676 * @param {?} routes An array of `Route` objects that define the navigation paths for the application.
7677 * @param {?=} config An `ExtraOptions` configuration object that controls how navigation is performed.
7678 * @return {?} The new router module.
7679 */
7680 static forRoot(routes, config) {
7681 return {
7682 ngModule: RouterModule,
7683 providers: [
7684 ROUTER_PROVIDERS,
7685 provideRoutes(routes),
7686 {
7687 provide: ROUTER_FORROOT_GUARD,
7688 useFactory: provideForRootGuard,
7689 deps: [[Router, new Optional(), new SkipSelf()]]
7690 },
7691 { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
7692 {
7693 provide: LocationStrategy,
7694 useFactory: provideLocationStrategy,
7695 deps: [
7696 PlatformLocation, [new Inject(APP_BASE_HREF), new Optional()], ROUTER_CONFIGURATION
7697 ]
7698 },
7699 {
7700 provide: RouterScroller,
7701 useFactory: createRouterScroller,
7702 deps: [Router, ViewportScroller, ROUTER_CONFIGURATION]
7703 },
7704 {
7705 provide: PreloadingStrategy,
7706 useExisting: config && config.preloadingStrategy ? config.preloadingStrategy :
7707 NoPreloading
7708 },
7709 { provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken },
7710 provideRouterInitializer(),
7711 ],
7712 };
7713 }
7714 /**
7715 * Creates a module with all the router directives and a provider registering routes.
7716 * @param {?} routes
7717 * @return {?}
7718 */
7719 static forChild(routes) {
7720 return { ngModule: RouterModule, providers: [provideRoutes(routes)] };
7721 }
7722}
7723RouterModule.decorators = [
7724 { type: NgModule, args: [{
7725 declarations: ROUTER_DIRECTIVES,
7726 exports: ROUTER_DIRECTIVES,
7727 entryComponents: [ɵEmptyOutletComponent]
7728 },] }
7729];
7730/** @nocollapse */
7731RouterModule.ctorParameters = () => [
7732 { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [ROUTER_FORROOT_GUARD,] }] },
7733 { type: Router, decorators: [{ type: Optional }] }
7734];
7735/**
7736 * @param {?} router
7737 * @param {?} viewportScroller
7738 * @param {?} config
7739 * @return {?}
7740 */
7741function createRouterScroller(router, viewportScroller, config) {
7742 if (config.scrollOffset) {
7743 viewportScroller.setOffset(config.scrollOffset);
7744 }
7745 return new RouterScroller(router, viewportScroller, config);
7746}
7747/**
7748 * @param {?} platformLocationStrategy
7749 * @param {?} baseHref
7750 * @param {?=} options
7751 * @return {?}
7752 */
7753function provideLocationStrategy(platformLocationStrategy, baseHref, options = {}) {
7754 return options.useHash ? new HashLocationStrategy(platformLocationStrategy, baseHref) :
7755 new PathLocationStrategy(platformLocationStrategy, baseHref);
7756}
7757/**
7758 * @param {?} router
7759 * @return {?}
7760 */
7761function provideForRootGuard(router) {
7762 if (router) {
7763 throw new Error(`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`);
7764 }
7765 return 'guarded';
7766}
7767/**
7768 * Registers a [DI provider](guide/glossary#provider) for a set of routes.
7769 * \@usageNotes
7770 *
7771 * ```
7772 * \@NgModule({
7773 * imports: [RouterModule.forChild(ROUTES)],
7774 * providers: [provideRoutes(EXTRA_ROUTES)]
7775 * })
7776 * class MyNgModule {}
7777 * ```
7778 *
7779 * \@publicApi
7780 * @param {?} routes The route configuration to provide.
7781 *
7782 * @return {?}
7783 */
7784function provideRoutes(routes) {
7785 return [
7786 { provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes },
7787 { provide: ROUTES, multi: true, useValue: routes },
7788 ];
7789}
7790/**
7791 * @param {?} ref
7792 * @param {?} urlSerializer
7793 * @param {?} contexts
7794 * @param {?} location
7795 * @param {?} injector
7796 * @param {?} loader
7797 * @param {?} compiler
7798 * @param {?} config
7799 * @param {?=} opts
7800 * @param {?=} urlHandlingStrategy
7801 * @param {?=} routeReuseStrategy
7802 * @return {?}
7803 */
7804function setupRouter(ref, urlSerializer, contexts, location, injector, loader, compiler, config, opts = {}, urlHandlingStrategy, routeReuseStrategy) {
7805 /** @type {?} */
7806 const router = new Router(null, urlSerializer, contexts, location, injector, loader, compiler, flatten(config));
7807 if (urlHandlingStrategy) {
7808 router.urlHandlingStrategy = urlHandlingStrategy;
7809 }
7810 if (routeReuseStrategy) {
7811 router.routeReuseStrategy = routeReuseStrategy;
7812 }
7813 if (opts.errorHandler) {
7814 router.errorHandler = opts.errorHandler;
7815 }
7816 if (opts.malformedUriErrorHandler) {
7817 router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
7818 }
7819 if (opts.enableTracing) {
7820 /** @type {?} */
7821 const dom = ɵgetDOM();
7822 router.events.subscribe((/**
7823 * @param {?} e
7824 * @return {?}
7825 */
7826 (e) => {
7827 dom.logGroup(`Router Event: ${((/** @type {?} */ (e.constructor))).name}`);
7828 dom.log(e.toString());
7829 dom.log(e);
7830 dom.logGroupEnd();
7831 }));
7832 }
7833 if (opts.onSameUrlNavigation) {
7834 router.onSameUrlNavigation = opts.onSameUrlNavigation;
7835 }
7836 if (opts.paramsInheritanceStrategy) {
7837 router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
7838 }
7839 if (opts.urlUpdateStrategy) {
7840 router.urlUpdateStrategy = opts.urlUpdateStrategy;
7841 }
7842 if (opts.relativeLinkResolution) {
7843 router.relativeLinkResolution = opts.relativeLinkResolution;
7844 }
7845 return router;
7846}
7847/**
7848 * @param {?} router
7849 * @return {?}
7850 */
7851function rootRoute(router) {
7852 return router.routerState.root;
7853}
7854/**
7855 * Router initialization requires two steps:
7856 *
7857 * First, we start the navigation in a `APP_INITIALIZER` to block the bootstrap if
7858 * a resolver or a guard executes asynchronously.
7859 *
7860 * Next, we actually run activation in a `BOOTSTRAP_LISTENER`, using the
7861 * `afterPreactivation` hook provided by the router.
7862 * The router navigation starts, reaches the point when preactivation is done, and then
7863 * pauses. It waits for the hook to be resolved. We then resolve it only in a bootstrap listener.
7864 */
7865class RouterInitializer {
7866 /**
7867 * @param {?} injector
7868 */
7869 constructor(injector) {
7870 this.injector = injector;
7871 this.initNavigation = false;
7872 this.resultOfPreactivationDone = new Subject();
7873 }
7874 /**
7875 * @return {?}
7876 */
7877 appInitializer() {
7878 /** @type {?} */
7879 const p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
7880 return p.then((/**
7881 * @return {?}
7882 */
7883 () => {
7884 /** @type {?} */
7885 let resolve = (/** @type {?} */ (null));
7886 /** @type {?} */
7887 const res = new Promise((/**
7888 * @param {?} r
7889 * @return {?}
7890 */
7891 r => resolve = r));
7892 /** @type {?} */
7893 const router = this.injector.get(Router);
7894 /** @type {?} */
7895 const opts = this.injector.get(ROUTER_CONFIGURATION);
7896 if (this.isLegacyDisabled(opts) || this.isLegacyEnabled(opts)) {
7897 resolve(true);
7898 }
7899 else if (opts.initialNavigation === 'disabled') {
7900 router.setUpLocationChangeListener();
7901 resolve(true);
7902 }
7903 else if (opts.initialNavigation === 'enabled') {
7904 router.hooks.afterPreactivation = (/**
7905 * @return {?}
7906 */
7907 () => {
7908 // only the initial navigation should be delayed
7909 if (!this.initNavigation) {
7910 this.initNavigation = true;
7911 resolve(true);
7912 return this.resultOfPreactivationDone;
7913 // subsequent navigations should not be delayed
7914 }
7915 else {
7916 return (/** @type {?} */ (of(null)));
7917 }
7918 });
7919 router.initialNavigation();
7920 }
7921 else {
7922 throw new Error(`Invalid initialNavigation options: '${opts.initialNavigation}'`);
7923 }
7924 return res;
7925 }));
7926 }
7927 /**
7928 * @param {?} bootstrappedComponentRef
7929 * @return {?}
7930 */
7931 bootstrapListener(bootstrappedComponentRef) {
7932 /** @type {?} */
7933 const opts = this.injector.get(ROUTER_CONFIGURATION);
7934 /** @type {?} */
7935 const preloader = this.injector.get(RouterPreloader);
7936 /** @type {?} */
7937 const routerScroller = this.injector.get(RouterScroller);
7938 /** @type {?} */
7939 const router = this.injector.get(Router);
7940 /** @type {?} */
7941 const ref = this.injector.get(ApplicationRef);
7942 if (bootstrappedComponentRef !== ref.components[0]) {
7943 return;
7944 }
7945 if (this.isLegacyEnabled(opts)) {
7946 router.initialNavigation();
7947 }
7948 else if (this.isLegacyDisabled(opts)) {
7949 router.setUpLocationChangeListener();
7950 }
7951 preloader.setUpPreloading();
7952 routerScroller.init();
7953 router.resetRootComponentType(ref.componentTypes[0]);
7954 this.resultOfPreactivationDone.next((/** @type {?} */ (null)));
7955 this.resultOfPreactivationDone.complete();
7956 }
7957 /**
7958 * @private
7959 * @param {?} opts
7960 * @return {?}
7961 */
7962 isLegacyEnabled(opts) {
7963 return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true ||
7964 opts.initialNavigation === undefined;
7965 }
7966 /**
7967 * @private
7968 * @param {?} opts
7969 * @return {?}
7970 */
7971 isLegacyDisabled(opts) {
7972 return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false;
7973 }
7974}
7975RouterInitializer.decorators = [
7976 { type: Injectable }
7977];
7978/** @nocollapse */
7979RouterInitializer.ctorParameters = () => [
7980 { type: Injector }
7981];
7982/**
7983 * @param {?} r
7984 * @return {?}
7985 */
7986function getAppInitializer(r) {
7987 return r.appInitializer.bind(r);
7988}
7989/**
7990 * @param {?} r
7991 * @return {?}
7992 */
7993function getBootstrapListener(r) {
7994 return r.bootstrapListener.bind(r);
7995}
7996/**
7997 * A [DI token](guide/glossary/#di-token) for the router initializer that
7998 * is called after the app is bootstrapped.
7999 *
8000 * \@publicApi
8001 * @type {?}
8002 */
8003const ROUTER_INITIALIZER = new InjectionToken('Router Initializer');
8004/**
8005 * @return {?}
8006 */
8007function provideRouterInitializer() {
8008 return [
8009 RouterInitializer,
8010 {
8011 provide: APP_INITIALIZER,
8012 multi: true,
8013 useFactory: getAppInitializer,
8014 deps: [RouterInitializer]
8015 },
8016 { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener, deps: [RouterInitializer] },
8017 { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
8018 ];
8019}
8020
8021/**
8022 * @fileoverview added by tsickle
8023 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8024 */
8025/**
8026 * \@publicApi
8027 * @type {?}
8028 */
8029const VERSION = new Version('8.1.3');
8030
8031/**
8032 * @fileoverview added by tsickle
8033 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8034 */
8035
8036/**
8037 * @fileoverview added by tsickle
8038 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8039 */
8040
8041/**
8042 * @fileoverview added by tsickle
8043 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8044 */
8045
8046/**
8047 * @fileoverview added by tsickle
8048 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
8049 */
8050
8051/**
8052 * Generated bundle index. Do not edit.
8053 */
8054
8055export { ɵEmptyOutletComponent as ɵangular_packages_router_router_l, ɵEmptyOutletComponent, ROUTER_FORROOT_GUARD as ɵangular_packages_router_router_a, RouterInitializer as ɵangular_packages_router_router_h, createRouterScroller as ɵangular_packages_router_router_c, getAppInitializer as ɵangular_packages_router_router_i, getBootstrapListener as ɵangular_packages_router_router_j, provideForRootGuard as ɵangular_packages_router_router_e, provideLocationStrategy as ɵangular_packages_router_router_d, provideRouterInitializer as ɵangular_packages_router_router_k, rootRoute as ɵangular_packages_router_router_g, routerNgProbeToken as ɵangular_packages_router_router_b, setupRouter as ɵangular_packages_router_router_f, RouterScroller as ɵangular_packages_router_router_o, Tree as ɵangular_packages_router_router_m, TreeNode as ɵangular_packages_router_router_n, RouterLink, RouterLinkWithHref, RouterLinkActive, RouterOutlet, ActivationEnd, ActivationStart, ChildActivationEnd, ChildActivationStart, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouterEvent, RoutesRecognized, Scroll, RouteReuseStrategy, Router, ROUTES, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, RouterModule, provideRoutes, ChildrenOutletContexts, OutletContext, NoPreloading, PreloadAllModules, PreloadingStrategy, RouterPreloader, ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot, PRIMARY_OUTLET, convertToParamMap, UrlHandlingStrategy, DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, flatten as ɵflatten };
8056//# sourceMappingURL=router.js.map