UNPKG

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