UNPKG

155 kBJavaScriptView Raw
1/**
2 * @license AngularJS v0.0.0-PLACEHOLDER
3 * (c) 2010-2016 Google, Inc. https://angular.io/
4 * License: MIT
5 */
6var __extends = (this && this.__extends) || function (d, b) {
7 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
8 function __() { this.constructor = d; }
9 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10};
11(function (global, factory) {
12 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/common'), require('@angular/core'), require('rxjs/Subject'), require('rxjs/observable/PromiseObservable'), require('rxjs/operator/toPromise'), require('rxjs/Observable'), require('@angular/platform-browser')) :
13 typeof define === 'function' && define.amd ? define(['exports', '@angular/common', '@angular/core', 'rxjs/Subject', 'rxjs/observable/PromiseObservable', 'rxjs/operator/toPromise', 'rxjs/Observable', '@angular/platform-browser'], factory) :
14 (factory((global.ng = global.ng || {}, global.ng.router_deprecated = global.ng.router_deprecated || {}), global.ng.common, global.ng.core, global.Rx, global.Rx, global.Rx.Observable.prototype, global.Rx, global.ng.platformBrowser));
15}(this, function (exports, _angular_common, _angular_core, rxjs_Subject, rxjs_observable_PromiseObservable, rxjs_operator_toPromise, rxjs_Observable, _angular_platformBrowser) {
16 'use strict';
17 var globalScope;
18 if (typeof window === 'undefined') {
19 if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
20 // TODO: Replace any with WorkerGlobalScope from lib.webworker.d.ts #3492
21 globalScope = self;
22 }
23 else {
24 globalScope = global;
25 }
26 }
27 else {
28 globalScope = window;
29 }
30 // Need to declare a new variable for global here since TypeScript
31 // exports the original value of the symbol.
32 var global$1 = globalScope;
33 var Type$1 = Function;
34 function getTypeNameForDebugging(type) {
35 if (type['name']) {
36 return type['name'];
37 }
38 return typeof type;
39 }
40 var Math = global$1.Math;
41 // TODO: remove calls to assert in production environment
42 // Note: Can't just export this and import in in other files
43 // as `assert` is a reserved keyword in Dart
44 global$1.assert = function assert(condition) {
45 // TODO: to be fixed properly via #2830, noop for now
46 };
47 function isPresent(obj) {
48 return obj !== undefined && obj !== null;
49 }
50 function isBlank(obj) {
51 return obj === undefined || obj === null;
52 }
53 function isString(obj) {
54 return typeof obj === 'string';
55 }
56 function isFunction(obj) {
57 return typeof obj === 'function';
58 }
59 function isType(obj) {
60 return isFunction(obj);
61 }
62 function isStringMap(obj) {
63 return typeof obj === 'object' && obj !== null;
64 }
65 function isArray(obj) {
66 return Array.isArray(obj);
67 }
68 function noop() { }
69 var StringWrapper = (function () {
70 function StringWrapper() {
71 }
72 StringWrapper.fromCharCode = function (code) { return String.fromCharCode(code); };
73 StringWrapper.charCodeAt = function (s, index) { return s.charCodeAt(index); };
74 StringWrapper.split = function (s, regExp) { return s.split(regExp); };
75 StringWrapper.equals = function (s, s2) { return s === s2; };
76 StringWrapper.stripLeft = function (s, charVal) {
77 if (s && s.length) {
78 var pos = 0;
79 for (var i = 0; i < s.length; i++) {
80 if (s[i] != charVal)
81 break;
82 pos++;
83 }
84 s = s.substring(pos);
85 }
86 return s;
87 };
88 StringWrapper.stripRight = function (s, charVal) {
89 if (s && s.length) {
90 var pos = s.length;
91 for (var i = s.length - 1; i >= 0; i--) {
92 if (s[i] != charVal)
93 break;
94 pos--;
95 }
96 s = s.substring(0, pos);
97 }
98 return s;
99 };
100 StringWrapper.replace = function (s, from, replace) {
101 return s.replace(from, replace);
102 };
103 StringWrapper.replaceAll = function (s, from, replace) {
104 return s.replace(from, replace);
105 };
106 StringWrapper.slice = function (s, from, to) {
107 if (from === void 0) { from = 0; }
108 if (to === void 0) { to = null; }
109 return s.slice(from, to === null ? undefined : to);
110 };
111 StringWrapper.replaceAllMapped = function (s, from, cb) {
112 return s.replace(from, function () {
113 var matches = [];
114 for (var _i = 0; _i < arguments.length; _i++) {
115 matches[_i - 0] = arguments[_i];
116 }
117 // Remove offset & string from the result array
118 matches.splice(-2, 2);
119 // The callback receives match, p1, ..., pn
120 return cb(matches);
121 });
122 };
123 StringWrapper.contains = function (s, substr) { return s.indexOf(substr) != -1; };
124 StringWrapper.compare = function (a, b) {
125 if (a < b) {
126 return -1;
127 }
128 else if (a > b) {
129 return 1;
130 }
131 else {
132 return 0;
133 }
134 };
135 return StringWrapper;
136 }());
137 var RegExpWrapper = (function () {
138 function RegExpWrapper() {
139 }
140 RegExpWrapper.create = function (regExpStr, flags) {
141 if (flags === void 0) { flags = ''; }
142 flags = flags.replace(/g/g, '');
143 return new global$1.RegExp(regExpStr, flags + 'g');
144 };
145 RegExpWrapper.firstMatch = function (regExp, input) {
146 // Reset multimatch regex state
147 regExp.lastIndex = 0;
148 return regExp.exec(input);
149 };
150 RegExpWrapper.test = function (regExp, input) {
151 regExp.lastIndex = 0;
152 return regExp.test(input);
153 };
154 RegExpWrapper.matcher = function (regExp, input) {
155 // Reset regex state for the case
156 // someone did not loop over all matches
157 // last time.
158 regExp.lastIndex = 0;
159 return { re: regExp, input: input };
160 };
161 RegExpWrapper.replaceAll = function (regExp, input, replace) {
162 var c = regExp.exec(input);
163 var res = '';
164 regExp.lastIndex = 0;
165 var prev = 0;
166 while (c) {
167 res += input.substring(prev, c.index);
168 res += replace(c);
169 prev = c.index + c[0].length;
170 regExp.lastIndex = prev;
171 c = regExp.exec(input);
172 }
173 res += input.substring(prev);
174 return res;
175 };
176 return RegExpWrapper;
177 }());
178 var RegExpMatcherWrapper = (function () {
179 function RegExpMatcherWrapper() {
180 }
181 RegExpMatcherWrapper.next = function (matcher) {
182 return matcher.re.exec(matcher.input);
183 };
184 return RegExpMatcherWrapper;
185 }());
186 function normalizeBlank(obj) {
187 return isBlank(obj) ? null : obj;
188 }
189 var PromiseCompleter = (function () {
190 function PromiseCompleter() {
191 var _this = this;
192 this.promise = new Promise(function (res, rej) {
193 _this.resolve = res;
194 _this.reject = rej;
195 });
196 }
197 return PromiseCompleter;
198 }());
199 var PromiseWrapper = (function () {
200 function PromiseWrapper() {
201 }
202 PromiseWrapper.resolve = function (obj) { return Promise.resolve(obj); };
203 PromiseWrapper.reject = function (obj, _) { return Promise.reject(obj); };
204 // Note: We can't rename this method into `catch`, as this is not a valid
205 // method name in Dart.
206 PromiseWrapper.catchError = function (promise, onError) {
207 return promise.catch(onError);
208 };
209 PromiseWrapper.all = function (promises) {
210 if (promises.length == 0)
211 return Promise.resolve([]);
212 return Promise.all(promises);
213 };
214 PromiseWrapper.then = function (promise, success, rejection) {
215 return promise.then(success, rejection);
216 };
217 PromiseWrapper.wrap = function (computation) {
218 return new Promise(function (res, rej) {
219 try {
220 res(computation());
221 }
222 catch (e) {
223 rej(e);
224 }
225 });
226 };
227 PromiseWrapper.scheduleMicrotask = function (computation) {
228 PromiseWrapper.then(PromiseWrapper.resolve(null), computation, function (_) { });
229 };
230 PromiseWrapper.isPromise = function (obj) { return obj instanceof Promise; };
231 PromiseWrapper.completer = function () { return new PromiseCompleter(); };
232 return PromiseWrapper;
233 }());
234 var ObservableWrapper = (function () {
235 function ObservableWrapper() {
236 }
237 // TODO(vsavkin): when we use rxnext, try inferring the generic type from the first arg
238 ObservableWrapper.subscribe = function (emitter, onNext, onError, onComplete) {
239 if (onComplete === void 0) { onComplete = function () { }; }
240 onError = (typeof onError === 'function') && onError || noop;
241 onComplete = (typeof onComplete === 'function') && onComplete || noop;
242 return emitter.subscribe({ next: onNext, error: onError, complete: onComplete });
243 };
244 ObservableWrapper.isObservable = function (obs) { return !!obs.subscribe; };
245 /**
246 * Returns whether `obs` has any subscribers listening to events.
247 */
248 ObservableWrapper.hasSubscribers = function (obs) { return obs.observers.length > 0; };
249 ObservableWrapper.dispose = function (subscription) { subscription.unsubscribe(); };
250 /**
251 * @deprecated - use callEmit() instead
252 */
253 ObservableWrapper.callNext = function (emitter, value) { emitter.next(value); };
254 ObservableWrapper.callEmit = function (emitter, value) { emitter.emit(value); };
255 ObservableWrapper.callError = function (emitter, error) { emitter.error(error); };
256 ObservableWrapper.callComplete = function (emitter) { emitter.complete(); };
257 ObservableWrapper.fromPromise = function (promise) {
258 return rxjs_observable_PromiseObservable.PromiseObservable.create(promise);
259 };
260 ObservableWrapper.toPromise = function (obj) { return rxjs_operator_toPromise.toPromise.call(obj); };
261 return ObservableWrapper;
262 }());
263 /**
264 * Use by directives and components to emit custom Events.
265 *
266 * ### Examples
267 *
268 * In the following example, `Zippy` alternatively emits `open` and `close` events when its
269 * title gets clicked:
270 *
271 * ```
272 * @Component({
273 * selector: 'zippy',
274 * template: `
275 * <div class="zippy">
276 * <div (click)="toggle()">Toggle</div>
277 * <div [hidden]="!visible">
278 * <ng-content></ng-content>
279 * </div>
280 * </div>`})
281 * export class Zippy {
282 * visible: boolean = true;
283 * @Output() open: EventEmitter<any> = new EventEmitter();
284 * @Output() close: EventEmitter<any> = new EventEmitter();
285 *
286 * toggle() {
287 * this.visible = !this.visible;
288 * if (this.visible) {
289 * this.open.emit(null);
290 * } else {
291 * this.close.emit(null);
292 * }
293 * }
294 * }
295 * ```
296 *
297 * The events payload can be accessed by the parameter `$event` on the components output event
298 * handler:
299 *
300 * ```
301 * <zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>
302 * ```
303 *
304 * Uses Rx.Observable but provides an adapter to make it work as specified here:
305 * https://github.com/jhusain/observable-spec
306 *
307 * Once a reference implementation of the spec is available, switch to it.
308 * @stable
309 */
310 var EventEmitter = (function (_super) {
311 __extends(EventEmitter, _super);
312 /**
313 * Creates an instance of [EventEmitter], which depending on [isAsync],
314 * delivers events synchronously or asynchronously.
315 */
316 function EventEmitter(isAsync) {
317 if (isAsync === void 0) { isAsync = false; }
318 _super.call(this);
319 this.__isAsync = isAsync;
320 }
321 EventEmitter.prototype.emit = function (value) { _super.prototype.next.call(this, value); };
322 /**
323 * @deprecated - use .emit(value) instead
324 */
325 EventEmitter.prototype.next = function (value) { _super.prototype.next.call(this, value); };
326 EventEmitter.prototype.subscribe = function (generatorOrNext, error, complete) {
327 var schedulerFn;
328 var errorFn = function (err) { return null; };
329 var completeFn = function () { return null; };
330 if (generatorOrNext && typeof generatorOrNext === 'object') {
331 schedulerFn = this.__isAsync ? function (value /** TODO #9100 */) {
332 setTimeout(function () { return generatorOrNext.next(value); });
333 } : function (value /** TODO #9100 */) { generatorOrNext.next(value); };
334 if (generatorOrNext.error) {
335 errorFn = this.__isAsync ? function (err) { setTimeout(function () { return generatorOrNext.error(err); }); } :
336 function (err) { generatorOrNext.error(err); };
337 }
338 if (generatorOrNext.complete) {
339 completeFn = this.__isAsync ? function () { setTimeout(function () { return generatorOrNext.complete(); }); } :
340 function () { generatorOrNext.complete(); };
341 }
342 }
343 else {
344 schedulerFn = this.__isAsync ? function (value /** TODO #9100 */) {
345 setTimeout(function () { return generatorOrNext(value); });
346 } : function (value /** TODO #9100 */) { generatorOrNext(value); };
347 if (error) {
348 errorFn =
349 this.__isAsync ? function (err) { setTimeout(function () { return error(err); }); } : function (err) { error(err); };
350 }
351 if (complete) {
352 completeFn =
353 this.__isAsync ? function () { setTimeout(function () { return complete(); }); } : function () { complete(); };
354 }
355 }
356 return _super.prototype.subscribe.call(this, schedulerFn, errorFn, completeFn);
357 };
358 return EventEmitter;
359 }(rxjs_Subject.Subject));
360 var Map$1 = global$1.Map;
361 var Set = global$1.Set;
362 // Safari and Internet Explorer do not support the iterable parameter to the
363 // Map constructor. We work around that by manually adding the items.
364 var createMapFromPairs = (function () {
365 try {
366 if (new Map$1([[1, 2]]).size === 1) {
367 return function createMapFromPairs(pairs) { return new Map$1(pairs); };
368 }
369 }
370 catch (e) {
371 }
372 return function createMapAndPopulateFromPairs(pairs) {
373 var map = new Map$1();
374 for (var i = 0; i < pairs.length; i++) {
375 var pair = pairs[i];
376 map.set(pair[0], pair[1]);
377 }
378 return map;
379 };
380 })();
381 var createMapFromMap = (function () {
382 try {
383 if (new Map$1(new Map$1())) {
384 return function createMapFromMap(m) { return new Map$1(m); };
385 }
386 }
387 catch (e) {
388 }
389 return function createMapAndPopulateFromMap(m) {
390 var map = new Map$1();
391 m.forEach(function (v, k) { map.set(k, v); });
392 return map;
393 };
394 })();
395 var _clearValues = (function () {
396 if ((new Map$1()).keys().next) {
397 return function _clearValues(m) {
398 var keyIterator = m.keys();
399 var k;
400 while (!((k = keyIterator.next()).done)) {
401 m.set(k.value, null);
402 }
403 };
404 }
405 else {
406 return function _clearValuesWithForeEach(m) {
407 m.forEach(function (v, k) { m.set(k, null); });
408 };
409 }
410 })();
411 // Safari doesn't implement MapIterator.next(), which is used is Traceur's polyfill of Array.from
412 // TODO(mlaval): remove the work around once we have a working polyfill of Array.from
413 var _arrayFromMap = (function () {
414 try {
415 if ((new Map$1()).values().next) {
416 return function createArrayFromMap(m, getValues) {
417 return getValues ? Array.from(m.values()) : Array.from(m.keys());
418 };
419 }
420 }
421 catch (e) {
422 }
423 return function createArrayFromMapWithForeach(m, getValues) {
424 var res = ListWrapper.createFixedSize(m.size), i = 0;
425 m.forEach(function (v, k) {
426 res[i] = getValues ? v : k;
427 i++;
428 });
429 return res;
430 };
431 })();
432 /**
433 * Wraps Javascript Objects
434 */
435 var StringMapWrapper = (function () {
436 function StringMapWrapper() {
437 }
438 StringMapWrapper.create = function () {
439 // Note: We are not using Object.create(null) here due to
440 // performance!
441 // http://jsperf.com/ng2-object-create-null
442 return {};
443 };
444 StringMapWrapper.contains = function (map, key) {
445 return map.hasOwnProperty(key);
446 };
447 StringMapWrapper.get = function (map, key) {
448 return map.hasOwnProperty(key) ? map[key] : undefined;
449 };
450 StringMapWrapper.set = function (map, key, value) { map[key] = value; };
451 StringMapWrapper.keys = function (map) { return Object.keys(map); };
452 StringMapWrapper.values = function (map) {
453 return Object.keys(map).reduce(function (r, a) {
454 r.push(map[a]);
455 return r;
456 }, []);
457 };
458 StringMapWrapper.isEmpty = function (map) {
459 for (var prop in map) {
460 return false;
461 }
462 return true;
463 };
464 StringMapWrapper.delete = function (map, key) { delete map[key]; };
465 StringMapWrapper.forEach = function (map, callback) {
466 for (var prop in map) {
467 if (map.hasOwnProperty(prop)) {
468 callback(map[prop], prop);
469 }
470 }
471 };
472 StringMapWrapper.merge = function (m1, m2) {
473 var m = {};
474 for (var attr in m1) {
475 if (m1.hasOwnProperty(attr)) {
476 m[attr] = m1[attr];
477 }
478 }
479 for (var attr in m2) {
480 if (m2.hasOwnProperty(attr)) {
481 m[attr] = m2[attr];
482 }
483 }
484 return m;
485 };
486 StringMapWrapper.equals = function (m1, m2) {
487 var k1 = Object.keys(m1);
488 var k2 = Object.keys(m2);
489 if (k1.length != k2.length) {
490 return false;
491 }
492 var key;
493 for (var i = 0; i < k1.length; i++) {
494 key = k1[i];
495 if (m1[key] !== m2[key]) {
496 return false;
497 }
498 }
499 return true;
500 };
501 return StringMapWrapper;
502 }());
503 var ListWrapper = (function () {
504 function ListWrapper() {
505 }
506 // JS has no way to express a statically fixed size list, but dart does so we
507 // keep both methods.
508 ListWrapper.createFixedSize = function (size) { return new Array(size); };
509 ListWrapper.createGrowableSize = function (size) { return new Array(size); };
510 ListWrapper.clone = function (array) { return array.slice(0); };
511 ListWrapper.forEachWithIndex = function (array, fn) {
512 for (var i = 0; i < array.length; i++) {
513 fn(array[i], i);
514 }
515 };
516 ListWrapper.first = function (array) {
517 if (!array)
518 return null;
519 return array[0];
520 };
521 ListWrapper.last = function (array) {
522 if (!array || array.length == 0)
523 return null;
524 return array[array.length - 1];
525 };
526 ListWrapper.indexOf = function (array, value, startIndex) {
527 if (startIndex === void 0) { startIndex = 0; }
528 return array.indexOf(value, startIndex);
529 };
530 ListWrapper.contains = function (list, el) { return list.indexOf(el) !== -1; };
531 ListWrapper.reversed = function (array) {
532 var a = ListWrapper.clone(array);
533 return a.reverse();
534 };
535 ListWrapper.concat = function (a, b) { return a.concat(b); };
536 ListWrapper.insert = function (list, index, value) { list.splice(index, 0, value); };
537 ListWrapper.removeAt = function (list, index) {
538 var res = list[index];
539 list.splice(index, 1);
540 return res;
541 };
542 ListWrapper.removeAll = function (list, items) {
543 for (var i = 0; i < items.length; ++i) {
544 var index = list.indexOf(items[i]);
545 list.splice(index, 1);
546 }
547 };
548 ListWrapper.remove = function (list, el) {
549 var index = list.indexOf(el);
550 if (index > -1) {
551 list.splice(index, 1);
552 return true;
553 }
554 return false;
555 };
556 ListWrapper.clear = function (list) { list.length = 0; };
557 ListWrapper.isEmpty = function (list) { return list.length == 0; };
558 ListWrapper.fill = function (list, value, start, end) {
559 if (start === void 0) { start = 0; }
560 if (end === void 0) { end = null; }
561 list.fill(value, start, end === null ? list.length : end);
562 };
563 ListWrapper.equals = function (a, b) {
564 if (a.length != b.length)
565 return false;
566 for (var i = 0; i < a.length; ++i) {
567 if (a[i] !== b[i])
568 return false;
569 }
570 return true;
571 };
572 ListWrapper.slice = function (l, from, to) {
573 if (from === void 0) { from = 0; }
574 if (to === void 0) { to = null; }
575 return l.slice(from, to === null ? undefined : to);
576 };
577 ListWrapper.splice = function (l, from, length) { return l.splice(from, length); };
578 ListWrapper.sort = function (l, compareFn) {
579 if (isPresent(compareFn)) {
580 l.sort(compareFn);
581 }
582 else {
583 l.sort();
584 }
585 };
586 ListWrapper.toString = function (l) { return l.toString(); };
587 ListWrapper.toJSON = function (l) { return JSON.stringify(l); };
588 ListWrapper.maximum = function (list, predicate) {
589 if (list.length == 0) {
590 return null;
591 }
592 var solution = null;
593 var maxValue = -Infinity;
594 for (var index = 0; index < list.length; index++) {
595 var candidate = list[index];
596 if (isBlank(candidate)) {
597 continue;
598 }
599 var candidateValue = predicate(candidate);
600 if (candidateValue > maxValue) {
601 solution = candidate;
602 maxValue = candidateValue;
603 }
604 }
605 return solution;
606 };
607 ListWrapper.flatten = function (list) {
608 var target = [];
609 _flattenArray(list, target);
610 return target;
611 };
612 ListWrapper.addAll = function (list, source) {
613 for (var i = 0; i < source.length; i++) {
614 list.push(source[i]);
615 }
616 };
617 return ListWrapper;
618 }());
619 function _flattenArray(source, target) {
620 if (isPresent(source)) {
621 for (var i = 0; i < source.length; i++) {
622 var item = source[i];
623 if (isArray(item)) {
624 _flattenArray(item, target);
625 }
626 else {
627 target.push(item);
628 }
629 }
630 }
631 return target;
632 }
633 // Safari and Internet Explorer do not support the iterable parameter to the
634 // Set constructor. We work around that by manually adding the items.
635 var createSetFromList = (function () {
636 var test = new Set([1, 2, 3]);
637 if (test.size === 3) {
638 return function createSetFromList(lst) { return new Set(lst); };
639 }
640 else {
641 return function createSetAndPopulateFromList(lst) {
642 var res = new Set(lst);
643 if (res.size !== lst.length) {
644 for (var i = 0; i < lst.length; i++) {
645 res.add(lst[i]);
646 }
647 }
648 return res;
649 };
650 }
651 })();
652 /**
653 * @stable
654 */
655 var BaseException$1 = (function (_super) {
656 __extends(BaseException$1, _super);
657 function BaseException$1(message) {
658 if (message === void 0) { message = '--'; }
659 _super.call(this, message);
660 this.message = message;
661 this.stack = (new Error(message)).stack;
662 }
663 BaseException$1.prototype.toString = function () { return this.message; };
664 return BaseException$1;
665 }(Error));
666 /**
667 * `RouteParams` is an immutable map of parameters for the given route
668 * based on the url matcher and optional parameters for that route.
669 *
670 * You can inject `RouteParams` into the constructor of a component to use it.
671 *
672 * ### Example
673 *
674 * ```
675 * import {Component} from '@angular/core';
676 * import {bootstrap} from '@angular/platform-browser/browser';
677 * import {Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig, RouteParams} from
678 * 'angular2/router';
679 *
680 * @Component({directives: [ROUTER_DIRECTIVES]})
681 * @RouteConfig([
682 * {path: '/user/:id', component: UserCmp, name: 'UserCmp'},
683 * ])
684 * class AppCmp {}
685 *
686 * @Component({ template: 'user: {{id}}' })
687 * class UserCmp {
688 * id: string;
689 * constructor(params: RouteParams) {
690 * this.id = params.get('id');
691 * }
692 * }
693 *
694 * bootstrap(AppCmp, ROUTER_PROVIDERS);
695 * ```
696 */
697 var RouteParams = (function () {
698 function RouteParams(params) {
699 this.params = params;
700 }
701 RouteParams.prototype.get = function (param) { return normalizeBlank(StringMapWrapper.get(this.params, param)); };
702 return RouteParams;
703 }());
704 /**
705 * `RouteData` is an immutable map of additional data you can configure in your {@link Route}.
706 *
707 * You can inject `RouteData` into the constructor of a component to use it.
708 *
709 * ### Example
710 *
711 * ```
712 * import {Component} from '@angular/core';
713 * import {bootstrap} from '@angular/platform-browser/browser';
714 * import {Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig, RouteData} from
715 * 'angular2/router';
716 *
717 * @Component({directives: [ROUTER_DIRECTIVES]})
718 * @RouteConfig([
719 * {path: '/user/:id', component: UserCmp, name: 'UserCmp', data: {isAdmin: true}},
720 * ])
721 * class AppCmp {}
722 *
723 * @Component({
724 * ...,
725 * template: 'user: {{isAdmin}}'
726 * })
727 * class UserCmp {
728 * string: isAdmin;
729 * constructor(data: RouteData) {
730 * this.isAdmin = data.get('isAdmin');
731 * }
732 * }
733 *
734 * bootstrap(AppCmp, ROUTER_PROVIDERS);
735 * ```
736 */
737 var RouteData = (function () {
738 function RouteData(data) {
739 if (data === void 0) { data = {}; }
740 this.data = data;
741 }
742 RouteData.prototype.get = function (key) { return normalizeBlank(StringMapWrapper.get(this.data, key)); };
743 return RouteData;
744 }());
745 var BLANK_ROUTE_DATA = new RouteData();
746 /**
747 * `Instruction` is a tree of {@link ComponentInstruction}s with all the information needed
748 * to transition each component in the app to a given route, including all auxiliary routes.
749 *
750 * `Instruction`s can be created using {@link Router#generate}, and can be used to
751 * perform route changes with {@link Router#navigateByInstruction}.
752 *
753 * ### Example
754 *
755 * ```
756 * import {Component} from '@angular/core';
757 * import {bootstrap} from '@angular/platform-browser/browser';
758 * import {Router, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig} from
759 * '@angular/router-deprecated';
760 *
761 * @Component({directives: [ROUTER_DIRECTIVES]})
762 * @RouteConfig([
763 * {...},
764 * ])
765 * class AppCmp {
766 * constructor(router: Router) {
767 * var instruction = router.generate(['/MyRoute']);
768 * router.navigateByInstruction(instruction);
769 * }
770 * }
771 *
772 * bootstrap(AppCmp, ROUTER_PROVIDERS);
773 * ```
774 */
775 var Instruction = (function () {
776 function Instruction(component, child, auxInstruction) {
777 this.component = component;
778 this.child = child;
779 this.auxInstruction = auxInstruction;
780 }
781 Object.defineProperty(Instruction.prototype, "urlPath", {
782 get: function () { return isPresent(this.component) ? this.component.urlPath : ''; },
783 enumerable: true,
784 configurable: true
785 });
786 Object.defineProperty(Instruction.prototype, "urlParams", {
787 get: function () { return isPresent(this.component) ? this.component.urlParams : []; },
788 enumerable: true,
789 configurable: true
790 });
791 Object.defineProperty(Instruction.prototype, "specificity", {
792 get: function () {
793 var total = '';
794 if (isPresent(this.component)) {
795 total += this.component.specificity;
796 }
797 if (isPresent(this.child)) {
798 total += this.child.specificity;
799 }
800 return total;
801 },
802 enumerable: true,
803 configurable: true
804 });
805 /**
806 * converts the instruction into a URL string
807 */
808 Instruction.prototype.toRootUrl = function () { return this.toUrlPath() + this.toUrlQuery(); };
809 /** @internal */
810 Instruction.prototype._toNonRootUrl = function () {
811 return this._stringifyPathMatrixAuxPrefixed() +
812 (isPresent(this.child) ? this.child._toNonRootUrl() : '');
813 };
814 Instruction.prototype.toUrlQuery = function () { return this.urlParams.length > 0 ? ('?' + this.urlParams.join('&')) : ''; };
815 /**
816 * Returns a new instruction that shares the state of the existing instruction, but with
817 * the given child {@link Instruction} replacing the existing child.
818 */
819 Instruction.prototype.replaceChild = function (child) {
820 return new ResolvedInstruction(this.component, child, this.auxInstruction);
821 };
822 /**
823 * If the final URL for the instruction is ``
824 */
825 Instruction.prototype.toUrlPath = function () {
826 return this.urlPath + this._stringifyAux() +
827 (isPresent(this.child) ? this.child._toNonRootUrl() : '');
828 };
829 // default instructions override these
830 Instruction.prototype.toLinkUrl = function () {
831 return this.urlPath + this._stringifyAux() +
832 (isPresent(this.child) ? this.child._toLinkUrl() : '') + this.toUrlQuery();
833 };
834 // this is the non-root version (called recursively)
835 /** @internal */
836 Instruction.prototype._toLinkUrl = function () {
837 return this._stringifyPathMatrixAuxPrefixed() +
838 (isPresent(this.child) ? this.child._toLinkUrl() : '');
839 };
840 /** @internal */
841 Instruction.prototype._stringifyPathMatrixAuxPrefixed = function () {
842 var primary = this._stringifyPathMatrixAux();
843 if (primary.length > 0) {
844 primary = '/' + primary;
845 }
846 return primary;
847 };
848 /** @internal */
849 Instruction.prototype._stringifyMatrixParams = function () {
850 return this.urlParams.length > 0 ? (';' + this.urlParams.join(';')) : '';
851 };
852 /** @internal */
853 Instruction.prototype._stringifyPathMatrixAux = function () {
854 if (isBlank(this.component) && isBlank(this.urlPath)) {
855 return '';
856 }
857 return this.urlPath + this._stringifyMatrixParams() + this._stringifyAux();
858 };
859 /** @internal */
860 Instruction.prototype._stringifyAux = function () {
861 var routes = [];
862 StringMapWrapper.forEach(this.auxInstruction, function (auxInstruction, _) {
863 routes.push(auxInstruction._stringifyPathMatrixAux());
864 });
865 if (routes.length > 0) {
866 return '(' + routes.join('//') + ')';
867 }
868 return '';
869 };
870 return Instruction;
871 }());
872 /**
873 * a resolved instruction has an outlet instruction for itself, but maybe not for...
874 */
875 var ResolvedInstruction = (function (_super) {
876 __extends(ResolvedInstruction, _super);
877 function ResolvedInstruction(component, child, auxInstruction) {
878 _super.call(this, component, child, auxInstruction);
879 }
880 ResolvedInstruction.prototype.resolveComponent = function () {
881 return PromiseWrapper.resolve(this.component);
882 };
883 return ResolvedInstruction;
884 }(Instruction));
885 /**
886 * Represents a resolved default route
887 */
888 var DefaultInstruction = (function (_super) {
889 __extends(DefaultInstruction, _super);
890 function DefaultInstruction(component, child) {
891 _super.call(this, component, child, {});
892 }
893 DefaultInstruction.prototype.toLinkUrl = function () { return ''; };
894 /** @internal */
895 DefaultInstruction.prototype._toLinkUrl = function () { return ''; };
896 return DefaultInstruction;
897 }(ResolvedInstruction));
898 /**
899 * Represents a component that may need to do some redirection or lazy loading at a later time.
900 */
901 var UnresolvedInstruction = (function (_super) {
902 __extends(UnresolvedInstruction, _super);
903 function UnresolvedInstruction(_resolver, _urlPath, _urlParams) {
904 if (_urlPath === void 0) { _urlPath = ''; }
905 if (_urlParams === void 0) { _urlParams = []; }
906 _super.call(this, null, null, {});
907 this._resolver = _resolver;
908 this._urlPath = _urlPath;
909 this._urlParams = _urlParams;
910 }
911 Object.defineProperty(UnresolvedInstruction.prototype, "urlPath", {
912 get: function () {
913 if (isPresent(this.component)) {
914 return this.component.urlPath;
915 }
916 if (isPresent(this._urlPath)) {
917 return this._urlPath;
918 }
919 return '';
920 },
921 enumerable: true,
922 configurable: true
923 });
924 Object.defineProperty(UnresolvedInstruction.prototype, "urlParams", {
925 get: function () {
926 if (isPresent(this.component)) {
927 return this.component.urlParams;
928 }
929 if (isPresent(this._urlParams)) {
930 return this._urlParams;
931 }
932 return [];
933 },
934 enumerable: true,
935 configurable: true
936 });
937 UnresolvedInstruction.prototype.resolveComponent = function () {
938 var _this = this;
939 if (isPresent(this.component)) {
940 return PromiseWrapper.resolve(this.component);
941 }
942 return this._resolver().then(function (instruction) {
943 _this.child = isPresent(instruction) ? instruction.child : null;
944 return _this.component = isPresent(instruction) ? instruction.component : null;
945 });
946 };
947 return UnresolvedInstruction;
948 }(Instruction));
949 var RedirectInstruction = (function (_super) {
950 __extends(RedirectInstruction, _super);
951 function RedirectInstruction(component, child, auxInstruction, _specificity) {
952 _super.call(this, component, child, auxInstruction);
953 this._specificity = _specificity;
954 }
955 Object.defineProperty(RedirectInstruction.prototype, "specificity", {
956 get: function () { return this._specificity; },
957 enumerable: true,
958 configurable: true
959 });
960 return RedirectInstruction;
961 }(ResolvedInstruction));
962 /**
963 * A `ComponentInstruction` represents the route state for a single component.
964 *
965 * `ComponentInstructions` is a public API. Instances of `ComponentInstruction` are passed
966 * to route lifecycle hooks, like {@link CanActivate}.
967 *
968 * `ComponentInstruction`s are [hash consed](https://en.wikipedia.org/wiki/Hash_consing). You should
969 * never construct one yourself with "new." Instead, rely on router's internal recognizer to
970 * construct `ComponentInstruction`s.
971 *
972 * You should not modify this object. It should be treated as immutable.
973 */
974 var ComponentInstruction = (function () {
975 /**
976 * @internal
977 */
978 function ComponentInstruction(urlPath, urlParams, data, componentType /** TODO #9100 */, terminal, specificity, params, routeName) {
979 if (params === void 0) { params = null; }
980 this.urlPath = urlPath;
981 this.urlParams = urlParams;
982 this.componentType = componentType;
983 this.terminal = terminal;
984 this.specificity = specificity;
985 this.params = params;
986 this.routeName = routeName;
987 this.reuse = false;
988 this.routeData = isPresent(data) ? data : BLANK_ROUTE_DATA;
989 }
990 return ComponentInstruction;
991 }());
992 var makeDecorator = _angular_core.__core_private__.makeDecorator;
993 var reflector = _angular_core.__core_private__.reflector;
994 /* @ts2dart_const */
995 var RouteLifecycleHook = (function () {
996 function RouteLifecycleHook(name) {
997 this.name = name;
998 }
999 return RouteLifecycleHook;
1000 }());
1001 /* @ts2dart_const */
1002 var CanActivateAnnotation = (function () {
1003 function CanActivateAnnotation(fn) {
1004 this.fn = fn;
1005 }
1006 return CanActivateAnnotation;
1007 }());
1008 var routerCanReuse =
1009 /*@ts2dart_const*/ new RouteLifecycleHook('routerCanReuse');
1010 var routerCanDeactivate =
1011 /*@ts2dart_const*/ new RouteLifecycleHook('routerCanDeactivate');
1012 var routerOnActivate =
1013 /*@ts2dart_const*/ new RouteLifecycleHook('routerOnActivate');
1014 var routerOnReuse =
1015 /*@ts2dart_const*/ new RouteLifecycleHook('routerOnReuse');
1016 var routerOnDeactivate =
1017 /*@ts2dart_const*/ new RouteLifecycleHook('routerOnDeactivate');
1018 function hasLifecycleHook(e, type /** TODO #9100 */) {
1019 if (!(type instanceof _angular_core.Type))
1020 return false;
1021 return e.name in type.prototype;
1022 }
1023 function getCanActivateHook(type /** TODO #9100 */) {
1024 var annotations = reflector.annotations(type);
1025 for (var i = 0; i < annotations.length; i += 1) {
1026 var annotation = annotations[i];
1027 if (annotation instanceof CanActivateAnnotation) {
1028 return annotation.fn;
1029 }
1030 }
1031 return null;
1032 }
1033 /**
1034 * The `RouteConfig` decorator defines routes for a given component.
1035 *
1036 * It takes an array of {@link RouteDefinition}s.
1037 * @ts2dart_const
1038 */
1039 var RouteConfigAnnotation = (function () {
1040 function RouteConfigAnnotation(configs) {
1041 this.configs = configs;
1042 }
1043 return RouteConfigAnnotation;
1044 }());
1045 /* @ts2dart_const */
1046 var AbstractRoute = (function () {
1047 function AbstractRoute(_a) {
1048 var name = _a.name, useAsDefault = _a.useAsDefault, path = _a.path, regex = _a.regex, regex_group_names = _a.regex_group_names, serializer = _a.serializer, data = _a.data;
1049 this.name = name;
1050 this.useAsDefault = useAsDefault;
1051 this.path = path;
1052 this.regex = regex;
1053 this.regex_group_names = regex_group_names;
1054 this.serializer = serializer;
1055 this.data = data;
1056 }
1057 return AbstractRoute;
1058 }());
1059 /**
1060 * `Route` is a type of {@link RouteDefinition} used to route a path to a component.
1061 *
1062 * It has the following properties:
1063 * - `path` is a string that uses the route matcher DSL.
1064 * - `component` a component type.
1065 * - `name` is an optional `CamelCase` string representing the name of the route.
1066 * - `data` is an optional property of any type representing arbitrary route metadata for the given
1067 * route. It is injectable via {@link RouteData}.
1068 * - `useAsDefault` is a boolean value. If `true`, the child route will be navigated to if no child
1069 * route is specified during the navigation.
1070 *
1071 * ### Example
1072 * ```
1073 * import {RouteConfig, Route} from '@angular/router-deprecated';
1074 *
1075 * @RouteConfig([
1076 * new Route({path: '/home', component: HomeCmp, name: 'HomeCmp' })
1077 * ])
1078 * class MyApp {}
1079 * ```
1080 * @ts2dart_const
1081 */
1082 var Route = (function (_super) {
1083 __extends(Route, _super);
1084 function Route(_a) {
1085 var name = _a.name, useAsDefault = _a.useAsDefault, path = _a.path, regex = _a.regex, regex_group_names = _a.regex_group_names, serializer = _a.serializer, data = _a.data, component = _a.component;
1086 _super.call(this, {
1087 name: name,
1088 useAsDefault: useAsDefault,
1089 path: path,
1090 regex: regex,
1091 regex_group_names: regex_group_names,
1092 serializer: serializer,
1093 data: data
1094 });
1095 this.aux = null;
1096 this.component = component;
1097 }
1098 return Route;
1099 }(AbstractRoute));
1100 /**
1101 * `AuxRoute` is a type of {@link RouteDefinition} used to define an auxiliary route.
1102 *
1103 * It takes an object with the following properties:
1104 * - `path` is a string that uses the route matcher DSL.
1105 * - `component` a component type.
1106 * - `name` is an optional `CamelCase` string representing the name of the route.
1107 * - `data` is an optional property of any type representing arbitrary route metadata for the given
1108 * route. It is injectable via {@link RouteData}.
1109 *
1110 * ### Example
1111 * ```
1112 * import {RouteConfig, AuxRoute} from '@angular/router-deprecated';
1113 *
1114 * @RouteConfig([
1115 * new AuxRoute({path: '/home', component: HomeCmp})
1116 * ])
1117 * class MyApp {}
1118 * ```
1119 * @ts2dart_const
1120 */
1121 var AuxRoute = (function (_super) {
1122 __extends(AuxRoute, _super);
1123 function AuxRoute(_a) {
1124 var name = _a.name, useAsDefault = _a.useAsDefault, path = _a.path, regex = _a.regex, regex_group_names = _a.regex_group_names, serializer = _a.serializer, data = _a.data, component = _a.component;
1125 _super.call(this, {
1126 name: name,
1127 useAsDefault: useAsDefault,
1128 path: path,
1129 regex: regex,
1130 regex_group_names: regex_group_names,
1131 serializer: serializer,
1132 data: data
1133 });
1134 this.component = component;
1135 }
1136 return AuxRoute;
1137 }(AbstractRoute));
1138 /**
1139 * `AsyncRoute` is a type of {@link RouteDefinition} used to route a path to an asynchronously
1140 * loaded component.
1141 *
1142 * It has the following properties:
1143 * - `path` is a string that uses the route matcher DSL.
1144 * - `loader` is a function that returns a promise that resolves to a component.
1145 * - `name` is an optional `CamelCase` string representing the name of the route.
1146 * - `data` is an optional property of any type representing arbitrary route metadata for the given
1147 * route. It is injectable via {@link RouteData}.
1148 * - `useAsDefault` is a boolean value. If `true`, the child route will be navigated to if no child
1149 * route is specified during the navigation.
1150 *
1151 * ### Example
1152 * ```
1153 * import {RouteConfig, AsyncRoute} from '@angular/router-deprecated';
1154 *
1155 * @RouteConfig([
1156 * new AsyncRoute({path: '/home', loader: () => Promise.resolve(MyLoadedCmp), name:
1157 * 'MyLoadedCmp'})
1158 * ])
1159 * class MyApp {}
1160 * ```
1161 * @ts2dart_const
1162 */
1163 var AsyncRoute = (function (_super) {
1164 __extends(AsyncRoute, _super);
1165 function AsyncRoute(_a) {
1166 var name = _a.name, useAsDefault = _a.useAsDefault, path = _a.path, regex = _a.regex, regex_group_names = _a.regex_group_names, serializer = _a.serializer, data = _a.data, loader = _a.loader;
1167 _super.call(this, {
1168 name: name,
1169 useAsDefault: useAsDefault,
1170 path: path,
1171 regex: regex,
1172 regex_group_names: regex_group_names,
1173 serializer: serializer,
1174 data: data
1175 });
1176 this.aux = null;
1177 this.loader = loader;
1178 }
1179 return AsyncRoute;
1180 }(AbstractRoute));
1181 /**
1182 * `Redirect` is a type of {@link RouteDefinition} used to route a path to a canonical route.
1183 *
1184 * It has the following properties:
1185 * - `path` is a string that uses the route matcher DSL.
1186 * - `redirectTo` is an array representing the link DSL.
1187 *
1188 * Note that redirects **do not** affect how links are generated. For that, see the `useAsDefault`
1189 * option.
1190 *
1191 * ### Example
1192 * ```
1193 * import {RouteConfig, Route, Redirect} from '@angular/router-deprecated';
1194 *
1195 * @RouteConfig([
1196 * new Redirect({path: '/', redirectTo: ['/Home'] }),
1197 * new Route({path: '/home', component: HomeCmp, name: 'Home'})
1198 * ])
1199 * class MyApp {}
1200 * ```
1201 * @ts2dart_const
1202 */
1203 var Redirect = (function (_super) {
1204 __extends(Redirect, _super);
1205 function Redirect(_a) {
1206 var name = _a.name, useAsDefault = _a.useAsDefault, path = _a.path, regex = _a.regex, regex_group_names = _a.regex_group_names, serializer = _a.serializer, data = _a.data, redirectTo = _a.redirectTo;
1207 _super.call(this, {
1208 name: name,
1209 useAsDefault: useAsDefault,
1210 path: path,
1211 regex: regex,
1212 regex_group_names: regex_group_names,
1213 serializer: serializer,
1214 data: data
1215 });
1216 this.redirectTo = redirectTo;
1217 }
1218 return Redirect;
1219 }(AbstractRoute));
1220 function convertUrlParamsToArray(urlParams) {
1221 var paramsArray = [];
1222 if (isBlank(urlParams)) {
1223 return [];
1224 }
1225 StringMapWrapper.forEach(urlParams, function (value /** TODO #9100 */, key /** TODO #9100 */) {
1226 paramsArray.push((value === true) ? key : key + '=' + value);
1227 });
1228 return paramsArray;
1229 }
1230 // Convert an object of url parameters into a string that can be used in an URL
1231 function serializeParams(urlParams, joiner) {
1232 if (joiner === void 0) { joiner = '&'; }
1233 return convertUrlParamsToArray(urlParams).join(joiner);
1234 }
1235 /**
1236 * This class represents a parsed URL
1237 */
1238 var Url = (function () {
1239 function Url(path, child, auxiliary, params) {
1240 if (child === void 0) { child = null; }
1241 if (auxiliary === void 0) { auxiliary = []; }
1242 if (params === void 0) { params = {}; }
1243 this.path = path;
1244 this.child = child;
1245 this.auxiliary = auxiliary;
1246 this.params = params;
1247 }
1248 Url.prototype.toString = function () {
1249 return this.path + this._matrixParamsToString() + this._auxToString() + this._childString();
1250 };
1251 Url.prototype.segmentToString = function () { return this.path + this._matrixParamsToString(); };
1252 /** @internal */
1253 Url.prototype._auxToString = function () {
1254 return this.auxiliary.length > 0 ?
1255 ('(' + this.auxiliary.map(function (sibling) { return sibling.toString(); }).join('//') + ')') :
1256 '';
1257 };
1258 Url.prototype._matrixParamsToString = function () {
1259 var paramString = serializeParams(this.params, ';');
1260 if (paramString.length > 0) {
1261 return ';' + paramString;
1262 }
1263 return '';
1264 };
1265 /** @internal */
1266 Url.prototype._childString = function () { return isPresent(this.child) ? ('/' + this.child.toString()) : ''; };
1267 return Url;
1268 }());
1269 var RootUrl = (function (_super) {
1270 __extends(RootUrl, _super);
1271 function RootUrl(path, child, auxiliary, params) {
1272 if (child === void 0) { child = null; }
1273 if (auxiliary === void 0) { auxiliary = []; }
1274 if (params === void 0) { params = null; }
1275 _super.call(this, path, child, auxiliary, params);
1276 }
1277 RootUrl.prototype.toString = function () {
1278 return this.path + this._auxToString() + this._childString() + this._queryParamsToString();
1279 };
1280 RootUrl.prototype.segmentToString = function () { return this.path + this._queryParamsToString(); };
1281 RootUrl.prototype._queryParamsToString = function () {
1282 if (isBlank(this.params)) {
1283 return '';
1284 }
1285 return '?' + serializeParams(this.params);
1286 };
1287 return RootUrl;
1288 }(Url));
1289 var SEGMENT_RE = RegExpWrapper.create('^[^\\/\\(\\)\\?;=&#]+');
1290 function matchUrlSegment(str) {
1291 var match = RegExpWrapper.firstMatch(SEGMENT_RE, str);
1292 return isPresent(match) ? match[0] : '';
1293 }
1294 var QUERY_PARAM_VALUE_RE = RegExpWrapper.create('^[^\\(\\)\\?;&#]+');
1295 function matchUrlQueryParamValue(str) {
1296 var match = RegExpWrapper.firstMatch(QUERY_PARAM_VALUE_RE, str);
1297 return isPresent(match) ? match[0] : '';
1298 }
1299 var UrlParser = (function () {
1300 function UrlParser() {
1301 }
1302 UrlParser.prototype.peekStartsWith = function (str) { return this._remaining.startsWith(str); };
1303 UrlParser.prototype.capture = function (str) {
1304 if (!this._remaining.startsWith(str)) {
1305 throw new BaseException$1("Expected \"" + str + "\".");
1306 }
1307 this._remaining = this._remaining.substring(str.length);
1308 };
1309 UrlParser.prototype.parse = function (url) {
1310 this._remaining = url;
1311 if (url == '' || url == '/') {
1312 return new Url('');
1313 }
1314 return this.parseRoot();
1315 };
1316 // segment + (aux segments) + (query params)
1317 UrlParser.prototype.parseRoot = function () {
1318 if (this.peekStartsWith('/')) {
1319 this.capture('/');
1320 }
1321 var path = matchUrlSegment(this._remaining);
1322 this.capture(path);
1323 var aux = [];
1324 if (this.peekStartsWith('(')) {
1325 aux = this.parseAuxiliaryRoutes();
1326 }
1327 if (this.peekStartsWith(';')) {
1328 // TODO: should these params just be dropped?
1329 this.parseMatrixParams();
1330 }
1331 var child = null;
1332 if (this.peekStartsWith('/') && !this.peekStartsWith('//')) {
1333 this.capture('/');
1334 child = this.parseSegment();
1335 }
1336 var queryParams = null;
1337 if (this.peekStartsWith('?')) {
1338 queryParams = this.parseQueryParams();
1339 }
1340 return new RootUrl(path, child, aux, queryParams);
1341 };
1342 // segment + (matrix params) + (aux segments)
1343 UrlParser.prototype.parseSegment = function () {
1344 if (this._remaining.length == 0) {
1345 return null;
1346 }
1347 if (this.peekStartsWith('/')) {
1348 this.capture('/');
1349 }
1350 var path = matchUrlSegment(this._remaining);
1351 this.capture(path);
1352 var matrixParams = null;
1353 if (this.peekStartsWith(';')) {
1354 matrixParams = this.parseMatrixParams();
1355 }
1356 var aux = [];
1357 if (this.peekStartsWith('(')) {
1358 aux = this.parseAuxiliaryRoutes();
1359 }
1360 var child = null;
1361 if (this.peekStartsWith('/') && !this.peekStartsWith('//')) {
1362 this.capture('/');
1363 child = this.parseSegment();
1364 }
1365 return new Url(path, child, aux, matrixParams);
1366 };
1367 UrlParser.prototype.parseQueryParams = function () {
1368 var params = {};
1369 this.capture('?');
1370 this.parseQueryParam(params);
1371 while (this._remaining.length > 0 && this.peekStartsWith('&')) {
1372 this.capture('&');
1373 this.parseQueryParam(params);
1374 }
1375 return params;
1376 };
1377 UrlParser.prototype.parseMatrixParams = function () {
1378 var params = {};
1379 while (this._remaining.length > 0 && this.peekStartsWith(';')) {
1380 this.capture(';');
1381 this.parseParam(params);
1382 }
1383 return params;
1384 };
1385 UrlParser.prototype.parseParam = function (params) {
1386 var key = matchUrlSegment(this._remaining);
1387 if (isBlank(key)) {
1388 return;
1389 }
1390 this.capture(key);
1391 var value = true;
1392 if (this.peekStartsWith('=')) {
1393 this.capture('=');
1394 var valueMatch = matchUrlSegment(this._remaining);
1395 if (isPresent(valueMatch)) {
1396 value = valueMatch;
1397 this.capture(value);
1398 }
1399 }
1400 params[key] = value;
1401 };
1402 UrlParser.prototype.parseQueryParam = function (params) {
1403 var key = matchUrlSegment(this._remaining);
1404 if (isBlank(key)) {
1405 return;
1406 }
1407 this.capture(key);
1408 var value = true;
1409 if (this.peekStartsWith('=')) {
1410 this.capture('=');
1411 var valueMatch = matchUrlQueryParamValue(this._remaining);
1412 if (isPresent(valueMatch)) {
1413 value = valueMatch;
1414 this.capture(value);
1415 }
1416 }
1417 params[key] = value;
1418 };
1419 UrlParser.prototype.parseAuxiliaryRoutes = function () {
1420 var routes = [];
1421 this.capture('(');
1422 while (!this.peekStartsWith(')') && this._remaining.length > 0) {
1423 routes.push(this.parseSegment());
1424 if (this.peekStartsWith('//')) {
1425 this.capture('//');
1426 }
1427 }
1428 this.capture(')');
1429 return routes;
1430 };
1431 return UrlParser;
1432 }());
1433 var parser = new UrlParser();
1434 // RouteMatch objects hold information about a match between a rule and a URL
1435 var RouteMatch = (function () {
1436 function RouteMatch() {
1437 }
1438 return RouteMatch;
1439 }());
1440 var PathMatch = (function (_super) {
1441 __extends(PathMatch, _super);
1442 function PathMatch(instruction, remaining, remainingAux) {
1443 _super.call(this);
1444 this.instruction = instruction;
1445 this.remaining = remaining;
1446 this.remainingAux = remainingAux;
1447 }
1448 return PathMatch;
1449 }(RouteMatch));
1450 var RedirectMatch = (function (_super) {
1451 __extends(RedirectMatch, _super);
1452 function RedirectMatch(redirectTo, specificity /** TODO #9100 */) {
1453 _super.call(this);
1454 this.redirectTo = redirectTo;
1455 this.specificity = specificity;
1456 }
1457 return RedirectMatch;
1458 }(RouteMatch));
1459 var RedirectRule = (function () {
1460 function RedirectRule(_pathRecognizer, redirectTo) {
1461 this._pathRecognizer = _pathRecognizer;
1462 this.redirectTo = redirectTo;
1463 this.hash = this._pathRecognizer.hash;
1464 }
1465 Object.defineProperty(RedirectRule.prototype, "path", {
1466 get: function () { return this._pathRecognizer.toString(); },
1467 set: function (val) { throw new BaseException$1('you cannot set the path of a RedirectRule directly'); },
1468 enumerable: true,
1469 configurable: true
1470 });
1471 /**
1472 * Returns `null` or a `ParsedUrl` representing the new path to match
1473 */
1474 RedirectRule.prototype.recognize = function (beginningSegment) {
1475 var match = null;
1476 if (isPresent(this._pathRecognizer.matchUrl(beginningSegment))) {
1477 match = new RedirectMatch(this.redirectTo, this._pathRecognizer.specificity);
1478 }
1479 return PromiseWrapper.resolve(match);
1480 };
1481 RedirectRule.prototype.generate = function (params) {
1482 throw new BaseException$1("Tried to generate a redirect.");
1483 };
1484 return RedirectRule;
1485 }());
1486 // represents something like '/foo/:bar'
1487 var RouteRule = (function () {
1488 // TODO: cache component instruction instances by params and by ParsedUrl instance
1489 function RouteRule(_routePath, handler, _routeName) {
1490 this._routePath = _routePath;
1491 this.handler = handler;
1492 this._routeName = _routeName;
1493 this._cache = new Map$1();
1494 this.specificity = this._routePath.specificity;
1495 this.hash = this._routePath.hash;
1496 this.terminal = this._routePath.terminal;
1497 }
1498 Object.defineProperty(RouteRule.prototype, "path", {
1499 get: function () { return this._routePath.toString(); },
1500 set: function (val) { throw new BaseException$1('you cannot set the path of a RouteRule directly'); },
1501 enumerable: true,
1502 configurable: true
1503 });
1504 RouteRule.prototype.recognize = function (beginningSegment) {
1505 var _this = this;
1506 var res = this._routePath.matchUrl(beginningSegment);
1507 if (isBlank(res)) {
1508 return null;
1509 }
1510 return this.handler.resolveComponentType().then(function (_) {
1511 var componentInstruction = _this._getInstruction(res.urlPath, res.urlParams, res.allParams);
1512 return new PathMatch(componentInstruction, res.rest, res.auxiliary);
1513 });
1514 };
1515 RouteRule.prototype.generate = function (params) {
1516 var generated = this._routePath.generateUrl(params);
1517 var urlPath = generated.urlPath;
1518 var urlParams = generated.urlParams;
1519 return this._getInstruction(urlPath, convertUrlParamsToArray(urlParams), params);
1520 };
1521 RouteRule.prototype.generateComponentPathValues = function (params) {
1522 return this._routePath.generateUrl(params);
1523 };
1524 RouteRule.prototype._getInstruction = function (urlPath, urlParams, params) {
1525 if (isBlank(this.handler.componentType)) {
1526 throw new BaseException$1("Tried to get instruction before the type was loaded.");
1527 }
1528 var hashKey = urlPath + '?' + urlParams.join('&');
1529 if (this._cache.has(hashKey)) {
1530 return this._cache.get(hashKey);
1531 }
1532 var instruction = new ComponentInstruction(urlPath, urlParams, this.handler.data, this.handler.componentType, this.terminal, this.specificity, params, this._routeName);
1533 this._cache.set(hashKey, instruction);
1534 return instruction;
1535 };
1536 return RouteRule;
1537 }());
1538 var AsyncRouteHandler = (function () {
1539 function AsyncRouteHandler(_loader, data) {
1540 if (data === void 0) { data = null; }
1541 this._loader = _loader;
1542 /** @internal */
1543 this._resolvedComponent = null;
1544 this.data = isPresent(data) ? new RouteData(data) : BLANK_ROUTE_DATA;
1545 }
1546 AsyncRouteHandler.prototype.resolveComponentType = function () {
1547 var _this = this;
1548 if (isPresent(this._resolvedComponent)) {
1549 return this._resolvedComponent;
1550 }
1551 return this._resolvedComponent = this._loader().then(function (componentType) {
1552 _this.componentType = componentType;
1553 return componentType;
1554 });
1555 };
1556 return AsyncRouteHandler;
1557 }());
1558 var SyncRouteHandler = (function () {
1559 function SyncRouteHandler(componentType, data) {
1560 this.componentType = componentType;
1561 /** @internal */
1562 this._resolvedComponent = null;
1563 this._resolvedComponent = PromiseWrapper.resolve(componentType);
1564 this.data = isPresent(data) ? new RouteData(data) : BLANK_ROUTE_DATA;
1565 }
1566 SyncRouteHandler.prototype.resolveComponentType = function () { return this._resolvedComponent; };
1567 return SyncRouteHandler;
1568 }());
1569 var TouchMap = (function () {
1570 function TouchMap(map) {
1571 var _this = this;
1572 this.map = {};
1573 this.keys = {};
1574 if (isPresent(map)) {
1575 StringMapWrapper.forEach(map, function (value /** TODO #9100 */, key /** TODO #9100 */) {
1576 _this.map[key] = isPresent(value) ? value.toString() : null;
1577 _this.keys[key] = true;
1578 });
1579 }
1580 }
1581 TouchMap.prototype.get = function (key) {
1582 StringMapWrapper.delete(this.keys, key);
1583 return this.map[key];
1584 };
1585 TouchMap.prototype.getUnused = function () {
1586 var _this = this;
1587 var unused = {};
1588 var keys = StringMapWrapper.keys(this.keys);
1589 keys.forEach(function (key) { return unused[key] = StringMapWrapper.get(_this.map, key); });
1590 return unused;
1591 };
1592 return TouchMap;
1593 }());
1594 function normalizeString(obj) {
1595 if (isBlank(obj)) {
1596 return null;
1597 }
1598 else {
1599 return obj.toString();
1600 }
1601 }
1602 var MatchedUrl = (function () {
1603 function MatchedUrl(urlPath, urlParams, allParams, auxiliary, rest) {
1604 this.urlPath = urlPath;
1605 this.urlParams = urlParams;
1606 this.allParams = allParams;
1607 this.auxiliary = auxiliary;
1608 this.rest = rest;
1609 }
1610 return MatchedUrl;
1611 }());
1612 var GeneratedUrl = (function () {
1613 function GeneratedUrl(urlPath, urlParams) {
1614 this.urlPath = urlPath;
1615 this.urlParams = urlParams;
1616 }
1617 return GeneratedUrl;
1618 }());
1619 /**
1620 * Identified by a `...` URL segment. This indicates that the
1621 * Route will continue to be matched by child `Router`s.
1622 */
1623 var ContinuationPathSegment = (function () {
1624 function ContinuationPathSegment() {
1625 this.name = '';
1626 this.specificity = '';
1627 this.hash = '...';
1628 }
1629 ContinuationPathSegment.prototype.generate = function (params) { return ''; };
1630 ContinuationPathSegment.prototype.match = function (path) { return true; };
1631 return ContinuationPathSegment;
1632 }());
1633 /**
1634 * Identified by a string not starting with a `:` or `*`.
1635 * Only matches the URL segments that equal the segment path
1636 */
1637 var StaticPathSegment = (function () {
1638 function StaticPathSegment(path) {
1639 this.path = path;
1640 this.name = '';
1641 this.specificity = '2';
1642 this.hash = path;
1643 }
1644 StaticPathSegment.prototype.match = function (path) { return path == this.path; };
1645 StaticPathSegment.prototype.generate = function (params) { return this.path; };
1646 return StaticPathSegment;
1647 }());
1648 /**
1649 * Identified by a string starting with `:`. Indicates a segment
1650 * that can contain a value that will be extracted and provided to
1651 * a matching `Instruction`.
1652 */
1653 var DynamicPathSegment = (function () {
1654 function DynamicPathSegment(name) {
1655 this.name = name;
1656 this.specificity = '1';
1657 this.hash = ':';
1658 }
1659 DynamicPathSegment.prototype.match = function (path) { return path.length > 0; };
1660 DynamicPathSegment.prototype.generate = function (params) {
1661 if (!StringMapWrapper.contains(params.map, this.name)) {
1662 throw new BaseException$1("Route generator for '" + this.name + "' was not included in parameters passed.");
1663 }
1664 return encodeDynamicSegment(normalizeString(params.get(this.name)));
1665 };
1666 return DynamicPathSegment;
1667 }());
1668 DynamicPathSegment.paramMatcher = /^:([^\/]+)$/g;
1669 /**
1670 * Identified by a string starting with `*` Indicates that all the following
1671 * segments match this route and that the value of these segments should
1672 * be provided to a matching `Instruction`.
1673 */
1674 var StarPathSegment = (function () {
1675 function StarPathSegment(name) {
1676 this.name = name;
1677 this.specificity = '0';
1678 this.hash = '*';
1679 }
1680 StarPathSegment.prototype.match = function (path) { return true; };
1681 StarPathSegment.prototype.generate = function (params) { return normalizeString(params.get(this.name)); };
1682 return StarPathSegment;
1683 }());
1684 StarPathSegment.wildcardMatcher = /^\*([^\/]+)$/g;
1685 /**
1686 * Parses a URL string using a given matcher DSL, and generates URLs from param maps
1687 */
1688 var ParamRoutePath = (function () {
1689 /**
1690 * Takes a string representing the matcher DSL
1691 */
1692 function ParamRoutePath(routePath) {
1693 this.routePath = routePath;
1694 this.terminal = true;
1695 this._assertValidPath(routePath);
1696 this._parsePathString(routePath);
1697 this.specificity = this._calculateSpecificity();
1698 this.hash = this._calculateHash();
1699 var lastSegment = this._segments[this._segments.length - 1];
1700 this.terminal = !(lastSegment instanceof ContinuationPathSegment);
1701 }
1702 ParamRoutePath.prototype.matchUrl = function (url) {
1703 var nextUrlSegment = url;
1704 var currentUrlSegment;
1705 var positionalParams = {};
1706 var captured = [];
1707 for (var i = 0; i < this._segments.length; i += 1) {
1708 var pathSegment = this._segments[i];
1709 if (pathSegment instanceof ContinuationPathSegment) {
1710 break;
1711 }
1712 currentUrlSegment = nextUrlSegment;
1713 if (isPresent(currentUrlSegment)) {
1714 // the star segment consumes all of the remaining URL, including matrix params
1715 if (pathSegment instanceof StarPathSegment) {
1716 positionalParams[pathSegment.name] =
1717 currentUrlSegment.toString();
1718 captured.push(currentUrlSegment.toString());
1719 nextUrlSegment = null;
1720 break;
1721 }
1722 captured.push(currentUrlSegment.path);
1723 if (pathSegment instanceof DynamicPathSegment) {
1724 positionalParams[pathSegment.name] =
1725 decodeDynamicSegment(currentUrlSegment.path);
1726 }
1727 else if (!pathSegment.match(currentUrlSegment.path)) {
1728 return null;
1729 }
1730 nextUrlSegment = currentUrlSegment.child;
1731 }
1732 else if (!pathSegment.match('')) {
1733 return null;
1734 }
1735 }
1736 if (this.terminal && isPresent(nextUrlSegment)) {
1737 return null;
1738 }
1739 var urlPath = captured.join('/');
1740 var auxiliary = [];
1741 var urlParams = [];
1742 var allParams = positionalParams;
1743 if (isPresent(currentUrlSegment)) {
1744 // If this is the root component, read query params. Otherwise, read matrix params.
1745 var paramsSegment = url instanceof RootUrl ? url : currentUrlSegment;
1746 if (isPresent(paramsSegment.params)) {
1747 allParams = StringMapWrapper.merge(paramsSegment.params, positionalParams);
1748 urlParams = convertUrlParamsToArray(paramsSegment.params);
1749 }
1750 else {
1751 allParams = positionalParams;
1752 }
1753 auxiliary = currentUrlSegment.auxiliary;
1754 }
1755 return new MatchedUrl(urlPath, urlParams, allParams, auxiliary, nextUrlSegment);
1756 };
1757 ParamRoutePath.prototype.generateUrl = function (params) {
1758 var paramTokens = new TouchMap(params);
1759 var path = [];
1760 for (var i = 0; i < this._segments.length; i++) {
1761 var segment = this._segments[i];
1762 if (!(segment instanceof ContinuationPathSegment)) {
1763 path.push(segment.generate(paramTokens));
1764 }
1765 }
1766 var urlPath = path.join('/');
1767 var nonPositionalParams = paramTokens.getUnused();
1768 var urlParams = nonPositionalParams;
1769 return new GeneratedUrl(urlPath, urlParams);
1770 };
1771 ParamRoutePath.prototype.toString = function () { return this.routePath; };
1772 ParamRoutePath.prototype._parsePathString = function (routePath) {
1773 // normalize route as not starting with a "/". Recognition will
1774 // also normalize.
1775 if (routePath.startsWith('/')) {
1776 routePath = routePath.substring(1);
1777 }
1778 var segmentStrings = routePath.split('/');
1779 this._segments = [];
1780 var limit = segmentStrings.length - 1;
1781 for (var i = 0; i <= limit; i++) {
1782 var segment = segmentStrings[i], match;
1783 if (isPresent(match = RegExpWrapper.firstMatch(DynamicPathSegment.paramMatcher, segment))) {
1784 this._segments.push(new DynamicPathSegment(match[1]));
1785 }
1786 else if (isPresent(match = RegExpWrapper.firstMatch(StarPathSegment.wildcardMatcher, segment))) {
1787 this._segments.push(new StarPathSegment(match[1]));
1788 }
1789 else if (segment == '...') {
1790 if (i < limit) {
1791 throw new BaseException$1("Unexpected \"...\" before the end of the path for \"" + routePath + "\".");
1792 }
1793 this._segments.push(new ContinuationPathSegment());
1794 }
1795 else {
1796 this._segments.push(new StaticPathSegment(segment));
1797 }
1798 }
1799 };
1800 ParamRoutePath.prototype._calculateSpecificity = function () {
1801 // The "specificity" of a path is used to determine which route is used when multiple routes
1802 // match
1803 // a URL. Static segments (like "/foo") are the most specific, followed by dynamic segments
1804 // (like
1805 // "/:id"). Star segments add no specificity. Segments at the start of the path are more
1806 // specific
1807 // than proceeding ones.
1808 //
1809 // The code below uses place values to combine the different types of segments into a single
1810 // string that we can sort later. Each static segment is marked as a specificity of "2," each
1811 // dynamic segment is worth "1" specificity, and stars are worth "0" specificity.
1812 var i /** TODO #9100 */, length = this._segments.length, specificity;
1813 if (length == 0) {
1814 // a single slash (or "empty segment" is as specific as a static segment
1815 specificity += '2';
1816 }
1817 else {
1818 specificity = '';
1819 for (i = 0; i < length; i++) {
1820 specificity += this._segments[i].specificity;
1821 }
1822 }
1823 return specificity;
1824 };
1825 ParamRoutePath.prototype._calculateHash = function () {
1826 // this function is used to determine whether a route config path like `/foo/:id` collides with
1827 // `/foo/:name`
1828 var i /** TODO #9100 */, length = this._segments.length;
1829 var hashParts = [];
1830 for (i = 0; i < length; i++) {
1831 hashParts.push(this._segments[i].hash);
1832 }
1833 return hashParts.join('/');
1834 };
1835 ParamRoutePath.prototype._assertValidPath = function (path) {
1836 if (StringWrapper.contains(path, '#')) {
1837 throw new BaseException$1("Path \"" + path + "\" should not include \"#\". Use \"HashLocationStrategy\" instead.");
1838 }
1839 var illegalCharacter = RegExpWrapper.firstMatch(ParamRoutePath.RESERVED_CHARS, path);
1840 if (isPresent(illegalCharacter)) {
1841 throw new BaseException$1("Path \"" + path + "\" contains \"" + illegalCharacter[0] + "\" which is not allowed in a route config.");
1842 }
1843 };
1844 return ParamRoutePath;
1845 }());
1846 ParamRoutePath.RESERVED_CHARS = RegExpWrapper.create('//|\\(|\\)|;|\\?|=');
1847 var REGEXP_PERCENT = /%/g;
1848 var REGEXP_SLASH = /\//g;
1849 var REGEXP_OPEN_PARENT = /\(/g;
1850 var REGEXP_CLOSE_PARENT = /\)/g;
1851 var REGEXP_SEMICOLON = /;/g;
1852 function encodeDynamicSegment(value) {
1853 if (isBlank(value)) {
1854 return null;
1855 }
1856 value = StringWrapper.replaceAll(value, REGEXP_PERCENT, '%25');
1857 value = StringWrapper.replaceAll(value, REGEXP_SLASH, '%2F');
1858 value = StringWrapper.replaceAll(value, REGEXP_OPEN_PARENT, '%28');
1859 value = StringWrapper.replaceAll(value, REGEXP_CLOSE_PARENT, '%29');
1860 value = StringWrapper.replaceAll(value, REGEXP_SEMICOLON, '%3B');
1861 return value;
1862 }
1863 var REGEXP_ENC_SEMICOLON = /%3B/ig;
1864 var REGEXP_ENC_CLOSE_PARENT = /%29/ig;
1865 var REGEXP_ENC_OPEN_PARENT = /%28/ig;
1866 var REGEXP_ENC_SLASH = /%2F/ig;
1867 var REGEXP_ENC_PERCENT = /%25/ig;
1868 function decodeDynamicSegment(value) {
1869 if (isBlank(value)) {
1870 return null;
1871 }
1872 value = StringWrapper.replaceAll(value, REGEXP_ENC_SEMICOLON, ';');
1873 value = StringWrapper.replaceAll(value, REGEXP_ENC_CLOSE_PARENT, ')');
1874 value = StringWrapper.replaceAll(value, REGEXP_ENC_OPEN_PARENT, '(');
1875 value = StringWrapper.replaceAll(value, REGEXP_ENC_SLASH, '/');
1876 value = StringWrapper.replaceAll(value, REGEXP_ENC_PERCENT, '%');
1877 return value;
1878 }
1879 function computeNumberOfRegexGroups(regex) {
1880 // cleverly compute regex groups by appending an alternative empty matching
1881 // pattern and match against an empty string, the resulting match still
1882 // receives all the other groups
1883 var test_regex = RegExpWrapper.create(regex + '|');
1884 var matcher = RegExpWrapper.matcher(test_regex, '');
1885 var match = RegExpMatcherWrapper.next(matcher);
1886 return match.length;
1887 }
1888 var RegexRoutePath = (function () {
1889 function RegexRoutePath(_reString, _serializer, _groupNames) {
1890 this._reString = _reString;
1891 this._serializer = _serializer;
1892 this._groupNames = _groupNames;
1893 this.terminal = true;
1894 this.specificity = '2';
1895 this.hash = this._reString;
1896 this._regex = RegExpWrapper.create(this._reString);
1897 if (this._groupNames != null) {
1898 var groups = computeNumberOfRegexGroups(this._reString);
1899 if (groups != _groupNames.length) {
1900 throw new _angular_core.BaseException("Regex group names [" + this._groupNames.join(',') + "] must contain names for each matching group and a name for the complete match as its first element of regex '" + this._reString + "'. " + groups + " group names are expected.");
1901 }
1902 }
1903 }
1904 RegexRoutePath.prototype.matchUrl = function (url) {
1905 var urlPath = url.toString();
1906 var params = {};
1907 var matcher = RegExpWrapper.matcher(this._regex, urlPath);
1908 var match = RegExpMatcherWrapper.next(matcher);
1909 if (isBlank(match)) {
1910 return null;
1911 }
1912 for (var i = 0; i < match.length; i += 1) {
1913 params[this._groupNames != null ? this._groupNames[i] : i.toString()] = match[i];
1914 }
1915 return new MatchedUrl(urlPath, [], params, [], null);
1916 };
1917 RegexRoutePath.prototype.generateUrl = function (params) { return this._serializer(params); };
1918 RegexRoutePath.prototype.toString = function () { return this._reString; };
1919 return RegexRoutePath;
1920 }());
1921 /**
1922 * A `RuleSet` is responsible for recognizing routes for a particular component.
1923 * It is consumed by `RouteRegistry`, which knows how to recognize an entire hierarchy of
1924 * components.
1925 */
1926 var RuleSet = (function () {
1927 function RuleSet() {
1928 this.rulesByName = new Map$1();
1929 // map from name to rule
1930 this.auxRulesByName = new Map$1();
1931 // map from starting path to rule
1932 this.auxRulesByPath = new Map$1();
1933 // TODO: optimize this into a trie
1934 this.rules = [];
1935 // the rule to use automatically when recognizing or generating from this rule set
1936 this.defaultRule = null;
1937 }
1938 /**
1939 * Configure additional rules in this rule set from a route definition
1940 * @returns {boolean} true if the config is terminal
1941 */
1942 RuleSet.prototype.config = function (config) {
1943 var handler;
1944 if (isPresent(config.name) && config.name[0].toUpperCase() != config.name[0]) {
1945 var suggestedName = config.name[0].toUpperCase() + config.name.substring(1);
1946 throw new BaseException$1("Route \"" + config.path + "\" with name \"" + config.name + "\" does not begin with an uppercase letter. Route names should be PascalCase like \"" + suggestedName + "\".");
1947 }
1948 if (config instanceof AuxRoute) {
1949 handler = new SyncRouteHandler(config.component, config.data);
1950 var routePath_1 = this._getRoutePath(config);
1951 var auxRule = new RouteRule(routePath_1, handler, config.name);
1952 this.auxRulesByPath.set(routePath_1.toString(), auxRule);
1953 if (isPresent(config.name)) {
1954 this.auxRulesByName.set(config.name, auxRule);
1955 }
1956 return auxRule.terminal;
1957 }
1958 var useAsDefault = false;
1959 if (config instanceof Redirect) {
1960 var routePath_2 = this._getRoutePath(config);
1961 var redirector = new RedirectRule(routePath_2, config.redirectTo);
1962 this._assertNoHashCollision(redirector.hash, config.path);
1963 this.rules.push(redirector);
1964 return true;
1965 }
1966 if (config instanceof Route) {
1967 handler = new SyncRouteHandler(config.component, config.data);
1968 useAsDefault = isPresent(config.useAsDefault) && config.useAsDefault;
1969 }
1970 else if (config instanceof AsyncRoute) {
1971 handler = new AsyncRouteHandler(config.loader, config.data);
1972 useAsDefault = isPresent(config.useAsDefault) && config.useAsDefault;
1973 }
1974 var routePath = this._getRoutePath(config);
1975 var newRule = new RouteRule(routePath, handler, config.name);
1976 this._assertNoHashCollision(newRule.hash, config.path);
1977 if (useAsDefault) {
1978 if (isPresent(this.defaultRule)) {
1979 throw new BaseException$1("Only one route can be default");
1980 }
1981 this.defaultRule = newRule;
1982 }
1983 this.rules.push(newRule);
1984 if (isPresent(config.name)) {
1985 this.rulesByName.set(config.name, newRule);
1986 }
1987 return newRule.terminal;
1988 };
1989 /**
1990 * Given a URL, returns a list of `RouteMatch`es, which are partial recognitions for some route.
1991 */
1992 RuleSet.prototype.recognize = function (urlParse) {
1993 var solutions = [];
1994 this.rules.forEach(function (routeRecognizer) {
1995 var pathMatch = routeRecognizer.recognize(urlParse);
1996 if (isPresent(pathMatch)) {
1997 solutions.push(pathMatch);
1998 }
1999 });
2000 // handle cases where we are routing just to an aux route
2001 if (solutions.length == 0 && isPresent(urlParse) && urlParse.auxiliary.length > 0) {
2002 return [PromiseWrapper.resolve(new PathMatch(null, null, urlParse.auxiliary))];
2003 }
2004 return solutions;
2005 };
2006 RuleSet.prototype.recognizeAuxiliary = function (urlParse) {
2007 var routeRecognizer = this.auxRulesByPath.get(urlParse.path);
2008 if (isPresent(routeRecognizer)) {
2009 return [routeRecognizer.recognize(urlParse)];
2010 }
2011 return [PromiseWrapper.resolve(null)];
2012 };
2013 RuleSet.prototype.hasRoute = function (name) { return this.rulesByName.has(name); };
2014 RuleSet.prototype.componentLoaded = function (name) {
2015 return this.hasRoute(name) && isPresent(this.rulesByName.get(name).handler.componentType);
2016 };
2017 RuleSet.prototype.loadComponent = function (name) {
2018 return this.rulesByName.get(name).handler.resolveComponentType();
2019 };
2020 RuleSet.prototype.generate = function (name, params) {
2021 var rule = this.rulesByName.get(name);
2022 if (isBlank(rule)) {
2023 return null;
2024 }
2025 return rule.generate(params);
2026 };
2027 RuleSet.prototype.generateAuxiliary = function (name, params) {
2028 var rule = this.auxRulesByName.get(name);
2029 if (isBlank(rule)) {
2030 return null;
2031 }
2032 return rule.generate(params);
2033 };
2034 RuleSet.prototype._assertNoHashCollision = function (hash, path /** TODO #9100 */) {
2035 this.rules.forEach(function (rule) {
2036 if (hash == rule.hash) {
2037 throw new BaseException$1("Configuration '" + path + "' conflicts with existing route '" + rule.path + "'");
2038 }
2039 });
2040 };
2041 RuleSet.prototype._getRoutePath = function (config) {
2042 if (isPresent(config.regex)) {
2043 if (isFunction(config.serializer)) {
2044 return new RegexRoutePath(config.regex, config.serializer, config.regex_group_names);
2045 }
2046 else {
2047 throw new BaseException$1("Route provides a regex property, '" + config.regex + "', but no serializer property");
2048 }
2049 }
2050 if (isPresent(config.path)) {
2051 // Auxiliary routes do not have a slash at the start
2052 var path = (config instanceof AuxRoute && config.path.startsWith('/')) ?
2053 config.path.substring(1) :
2054 config.path;
2055 return new ParamRoutePath(path);
2056 }
2057 throw new BaseException$1('Route must provide either a path or regex property');
2058 };
2059 return RuleSet;
2060 }());
2061 // Copied from RouteConfig in route_config_impl.
2062 /**
2063 * The `RouteConfig` decorator defines routes for a given component.
2064 *
2065 * It takes an array of {@link RouteDefinition}s.
2066 */
2067 var RouteConfig = makeDecorator(RouteConfigAnnotation);
2068 /**
2069 * Given a JS Object that represents a route config, returns a corresponding Route, AsyncRoute,
2070 * AuxRoute or Redirect object.
2071 *
2072 * Also wraps an AsyncRoute's loader function to add the loaded component's route config to the
2073 * `RouteRegistry`.
2074 */
2075 function normalizeRouteConfig(config, registry) {
2076 if (config instanceof AsyncRoute) {
2077 var wrappedLoader = wrapLoaderToReconfigureRegistry(config.loader, registry);
2078 return new AsyncRoute({
2079 path: config.path,
2080 loader: wrappedLoader,
2081 name: config.name,
2082 data: config.data,
2083 useAsDefault: config.useAsDefault
2084 });
2085 }
2086 if (config instanceof Route || config instanceof Redirect || config instanceof AuxRoute) {
2087 return config;
2088 }
2089 if ((+!!config.component) + (+!!config.redirectTo) + (+!!config.loader) != 1) {
2090 throw new BaseException$1("Route config should contain exactly one \"component\", \"loader\", or \"redirectTo\" property.");
2091 }
2092 if (config.loader) {
2093 var wrappedLoader = wrapLoaderToReconfigureRegistry(config.loader, registry);
2094 return new AsyncRoute({
2095 path: config.path,
2096 loader: wrappedLoader,
2097 name: config.name,
2098 data: config.data,
2099 useAsDefault: config.useAsDefault
2100 });
2101 }
2102 if (config.aux) {
2103 return new AuxRoute({ path: config.aux, component: config.component, name: config.name });
2104 }
2105 if (config.component) {
2106 if (typeof config.component == 'object') {
2107 var componentDefinitionObject = config.component;
2108 if (componentDefinitionObject.type == 'constructor') {
2109 return new Route({
2110 path: config.path,
2111 component: componentDefinitionObject.constructor,
2112 name: config.name,
2113 data: config.data,
2114 useAsDefault: config.useAsDefault
2115 });
2116 }
2117 else if (componentDefinitionObject.type == 'loader') {
2118 return new AsyncRoute({
2119 path: config.path,
2120 loader: componentDefinitionObject.loader,
2121 name: config.name,
2122 data: config.data,
2123 useAsDefault: config.useAsDefault
2124 });
2125 }
2126 else {
2127 throw new BaseException$1("Invalid component type \"" + componentDefinitionObject.type + "\". Valid types are \"constructor\" and \"loader\".");
2128 }
2129 }
2130 return new Route(config);
2131 }
2132 if (config.redirectTo) {
2133 return new Redirect({ path: config.path, redirectTo: config.redirectTo });
2134 }
2135 return config;
2136 }
2137 function wrapLoaderToReconfigureRegistry(loader, registry) {
2138 return function () {
2139 return loader().then(function (componentType /** TODO #9100 */) {
2140 registry.configFromComponent(componentType);
2141 return componentType;
2142 });
2143 };
2144 }
2145 function assertComponentExists(component, path) {
2146 if (!isType(component)) {
2147 throw new BaseException$1("Component for route \"" + path + "\" is not defined, or is not a class.");
2148 }
2149 }
2150 var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
2151 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2152 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2153 r = Reflect.decorate(decorators, target, key, desc);
2154 else
2155 for (var i = decorators.length - 1; i >= 0; i--)
2156 if (d = decorators[i])
2157 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2158 return c > 3 && r && Object.defineProperty(target, key, r), r;
2159 };
2160 var __metadata$2 = (this && this.__metadata) || function (k, v) {
2161 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
2162 return Reflect.metadata(k, v);
2163 };
2164 var __param$1 = (this && this.__param) || function (paramIndex, decorator) {
2165 return function (target, key) { decorator(target, key, paramIndex); };
2166 };
2167 var _resolveToNull = PromiseWrapper.resolve(null);
2168 // A LinkItemArray is an array, which describes a set of routes
2169 // The items in the array are found in groups:
2170 // - the first item is the name of the route
2171 // - the next items are:
2172 // - an object containing parameters
2173 // - or an array describing an aux route
2174 // export type LinkRouteItem = string | Object;
2175 // export type LinkItem = LinkRouteItem | Array<LinkRouteItem>;
2176 // export type LinkItemArray = Array<LinkItem>;
2177 /**
2178 * Token used to bind the component with the top-level {@link RouteConfig}s for the
2179 * application.
2180 *
2181 * ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
2182 *
2183 * ```
2184 * import {Component} from '@angular/core';
2185 * import {
2186 * ROUTER_DIRECTIVES,
2187 * ROUTER_PROVIDERS,
2188 * RouteConfig
2189 * } from '@angular/router-deprecated';
2190 *
2191 * @Component({directives: [ROUTER_DIRECTIVES]})
2192 * @RouteConfig([
2193 * {...},
2194 * ])
2195 * class AppCmp {
2196 * // ...
2197 * }
2198 *
2199 * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
2200 * ```
2201 */
2202 var ROUTER_PRIMARY_COMPONENT =
2203 /*@ts2dart_const*/ new _angular_core.OpaqueToken('RouterPrimaryComponent');
2204 /**
2205 * The RouteRegistry holds route configurations for each component in an Angular app.
2206 * It is responsible for creating Instructions from URLs, and generating URLs based on route and
2207 * parameters.
2208 */
2209 exports.RouteRegistry = (function () {
2210 function RouteRegistry(_rootComponent) {
2211 this._rootComponent = _rootComponent;
2212 this._rules = new Map$1();
2213 }
2214 /**
2215 * Given a component and a configuration object, add the route to this registry
2216 */
2217 RouteRegistry.prototype.config = function (parentComponent, config) {
2218 config = normalizeRouteConfig(config, this);
2219 // this is here because Dart type guard reasons
2220 if (config instanceof Route) {
2221 assertComponentExists(config.component, config.path);
2222 }
2223 else if (config instanceof AuxRoute) {
2224 assertComponentExists(config.component, config.path);
2225 }
2226 var rules = this._rules.get(parentComponent);
2227 if (isBlank(rules)) {
2228 rules = new RuleSet();
2229 this._rules.set(parentComponent, rules);
2230 }
2231 var terminal = rules.config(config);
2232 if (config instanceof Route) {
2233 if (terminal) {
2234 assertTerminalComponent(config.component, config.path);
2235 }
2236 else {
2237 this.configFromComponent(config.component);
2238 }
2239 }
2240 };
2241 /**
2242 * Reads the annotations of a component and configures the registry based on them
2243 */
2244 RouteRegistry.prototype.configFromComponent = function (component) {
2245 var _this = this;
2246 if (!isType(component)) {
2247 return;
2248 }
2249 // Don't read the annotations from a type more than once –
2250 // this prevents an infinite loop if a component routes recursively.
2251 if (this._rules.has(component)) {
2252 return;
2253 }
2254 var annotations = reflector.annotations(component);
2255 if (isPresent(annotations)) {
2256 for (var i = 0; i < annotations.length; i++) {
2257 var annotation = annotations[i];
2258 if (annotation instanceof RouteConfigAnnotation) {
2259 var routeCfgs = annotation.configs;
2260 routeCfgs.forEach(function (config) { return _this.config(component, config); });
2261 }
2262 }
2263 }
2264 };
2265 /**
2266 * Given a URL and a parent component, return the most specific instruction for navigating
2267 * the application into the state specified by the url
2268 */
2269 RouteRegistry.prototype.recognize = function (url, ancestorInstructions) {
2270 var parsedUrl = parser.parse(url);
2271 return this._recognize(parsedUrl, []);
2272 };
2273 /**
2274 * Recognizes all parent-child routes, but creates unresolved auxiliary routes
2275 */
2276 RouteRegistry.prototype._recognize = function (parsedUrl, ancestorInstructions, _aux) {
2277 var _this = this;
2278 if (_aux === void 0) { _aux = false; }
2279 var parentInstruction = ListWrapper.last(ancestorInstructions);
2280 var parentComponent = isPresent(parentInstruction) ? parentInstruction.component.componentType :
2281 this._rootComponent;
2282 var rules = this._rules.get(parentComponent);
2283 if (isBlank(rules)) {
2284 return _resolveToNull;
2285 }
2286 // Matches some beginning part of the given URL
2287 var possibleMatches = _aux ? rules.recognizeAuxiliary(parsedUrl) : rules.recognize(parsedUrl);
2288 var matchPromises = possibleMatches.map(function (candidate) { return candidate.then(function (candidate) {
2289 if (candidate instanceof PathMatch) {
2290 var auxParentInstructions = ancestorInstructions.length > 0 ? [ListWrapper.last(ancestorInstructions)] : [];
2291 var auxInstructions = _this._auxRoutesToUnresolved(candidate.remainingAux, auxParentInstructions);
2292 var instruction = new ResolvedInstruction(candidate.instruction, null, auxInstructions);
2293 if (isBlank(candidate.instruction) || candidate.instruction.terminal) {
2294 return instruction;
2295 }
2296 var newAncestorInstructions = ancestorInstructions.concat([instruction]);
2297 return _this._recognize(candidate.remaining, newAncestorInstructions)
2298 .then(function (childInstruction) {
2299 if (isBlank(childInstruction)) {
2300 return null;
2301 }
2302 // redirect instructions are already absolute
2303 if (childInstruction instanceof RedirectInstruction) {
2304 return childInstruction;
2305 }
2306 instruction.child = childInstruction;
2307 return instruction;
2308 });
2309 }
2310 if (candidate instanceof RedirectMatch) {
2311 var instruction = _this.generate(candidate.redirectTo, ancestorInstructions.concat([null]));
2312 return new RedirectInstruction(instruction.component, instruction.child, instruction.auxInstruction, candidate.specificity);
2313 }
2314 }); });
2315 if ((isBlank(parsedUrl) || parsedUrl.path == '') && possibleMatches.length == 0) {
2316 return PromiseWrapper.resolve(this.generateDefault(parentComponent));
2317 }
2318 return PromiseWrapper.all(matchPromises).then(mostSpecific);
2319 };
2320 RouteRegistry.prototype._auxRoutesToUnresolved = function (auxRoutes, parentInstructions) {
2321 var _this = this;
2322 var unresolvedAuxInstructions = {};
2323 auxRoutes.forEach(function (auxUrl) {
2324 unresolvedAuxInstructions[auxUrl.path] = new UnresolvedInstruction(function () { return _this._recognize(auxUrl, parentInstructions, true); });
2325 });
2326 return unresolvedAuxInstructions;
2327 };
2328 /**
2329 * Given a normalized list with component names and params like: `['user', {id: 3 }]`
2330 * generates a url with a leading slash relative to the provided `parentComponent`.
2331 *
2332 * If the optional param `_aux` is `true`, then we generate starting at an auxiliary
2333 * route boundary.
2334 */
2335 RouteRegistry.prototype.generate = function (linkParams, ancestorInstructions, _aux) {
2336 if (_aux === void 0) { _aux = false; }
2337 var params = splitAndFlattenLinkParams(linkParams);
2338 var prevInstruction;
2339 // The first segment should be either '.' (generate from parent) or '' (generate from root).
2340 // When we normalize above, we strip all the slashes, './' becomes '.' and '/' becomes ''.
2341 if (ListWrapper.first(params) == '') {
2342 params.shift();
2343 prevInstruction = ListWrapper.first(ancestorInstructions);
2344 ancestorInstructions = [];
2345 }
2346 else {
2347 prevInstruction = ancestorInstructions.length > 0 ? ancestorInstructions.pop() : null;
2348 if (ListWrapper.first(params) == '.') {
2349 params.shift();
2350 }
2351 else if (ListWrapper.first(params) == '..') {
2352 while (ListWrapper.first(params) == '..') {
2353 if (ancestorInstructions.length <= 0) {
2354 throw new BaseException$1("Link \"" + ListWrapper.toJSON(linkParams) + "\" has too many \"../\" segments.");
2355 }
2356 prevInstruction = ancestorInstructions.pop();
2357 params = ListWrapper.slice(params, 1);
2358 }
2359 }
2360 else {
2361 // we must only peak at the link param, and not consume it
2362 var routeName = ListWrapper.first(params);
2363 var parentComponentType = this._rootComponent;
2364 var grandparentComponentType = null;
2365 if (ancestorInstructions.length > 1) {
2366 var parentComponentInstruction = ancestorInstructions[ancestorInstructions.length - 1];
2367 var grandComponentInstruction = ancestorInstructions[ancestorInstructions.length - 2];
2368 parentComponentType = parentComponentInstruction.component.componentType;
2369 grandparentComponentType = grandComponentInstruction.component.componentType;
2370 }
2371 else if (ancestorInstructions.length == 1) {
2372 parentComponentType = ancestorInstructions[0].component.componentType;
2373 grandparentComponentType = this._rootComponent;
2374 }
2375 // For a link with no leading `./`, `/`, or `../`, we look for a sibling and child.
2376 // If both exist, we throw. Otherwise, we prefer whichever exists.
2377 var childRouteExists = this.hasRoute(routeName, parentComponentType);
2378 var parentRouteExists = isPresent(grandparentComponentType) &&
2379 this.hasRoute(routeName, grandparentComponentType);
2380 if (parentRouteExists && childRouteExists) {
2381 var msg = "Link \"" + ListWrapper.toJSON(linkParams) + "\" is ambiguous, use \"./\" or \"../\" to disambiguate.";
2382 throw new BaseException$1(msg);
2383 }
2384 if (parentRouteExists) {
2385 prevInstruction = ancestorInstructions.pop();
2386 }
2387 }
2388 }
2389 if (params[params.length - 1] == '') {
2390 params.pop();
2391 }
2392 if (params.length > 0 && params[0] == '') {
2393 params.shift();
2394 }
2395 if (params.length < 1) {
2396 var msg = "Link \"" + ListWrapper.toJSON(linkParams) + "\" must include a route name.";
2397 throw new BaseException$1(msg);
2398 }
2399 var generatedInstruction = this._generate(params, ancestorInstructions, prevInstruction, _aux, linkParams);
2400 // we don't clone the first (root) element
2401 for (var i = ancestorInstructions.length - 1; i >= 0; i--) {
2402 var ancestorInstruction = ancestorInstructions[i];
2403 if (isBlank(ancestorInstruction)) {
2404 break;
2405 }
2406 generatedInstruction = ancestorInstruction.replaceChild(generatedInstruction);
2407 }
2408 return generatedInstruction;
2409 };
2410 /*
2411 * Internal helper that does not make any assertions about the beginning of the link DSL.
2412 * `ancestorInstructions` are parents that will be cloned.
2413 * `prevInstruction` is the existing instruction that would be replaced, but which might have
2414 * aux routes that need to be cloned.
2415 */
2416 RouteRegistry.prototype._generate = function (linkParams, ancestorInstructions, prevInstruction, _aux, _originalLink) {
2417 var _this = this;
2418 if (_aux === void 0) { _aux = false; }
2419 var parentComponentType = this._rootComponent;
2420 var componentInstruction = null;
2421 var auxInstructions = {};
2422 var parentInstruction = ListWrapper.last(ancestorInstructions);
2423 if (isPresent(parentInstruction) && isPresent(parentInstruction.component)) {
2424 parentComponentType = parentInstruction.component.componentType;
2425 }
2426 if (linkParams.length == 0) {
2427 var defaultInstruction = this.generateDefault(parentComponentType);
2428 if (isBlank(defaultInstruction)) {
2429 throw new BaseException$1("Link \"" + ListWrapper.toJSON(_originalLink) + "\" does not resolve to a terminal instruction.");
2430 }
2431 return defaultInstruction;
2432 }
2433 // for non-aux routes, we want to reuse the predecessor's existing primary and aux routes
2434 // and only override routes for which the given link DSL provides
2435 if (isPresent(prevInstruction) && !_aux) {
2436 auxInstructions = StringMapWrapper.merge(prevInstruction.auxInstruction, auxInstructions);
2437 componentInstruction = prevInstruction.component;
2438 }
2439 var rules = this._rules.get(parentComponentType);
2440 if (isBlank(rules)) {
2441 throw new BaseException$1("Component \"" + getTypeNameForDebugging(parentComponentType) + "\" has no route config.");
2442 }
2443 var linkParamIndex = 0;
2444 var routeParams = {};
2445 // first, recognize the primary route if one is provided
2446 if (linkParamIndex < linkParams.length && isString(linkParams[linkParamIndex])) {
2447 var routeName = linkParams[linkParamIndex];
2448 if (routeName == '' || routeName == '.' || routeName == '..') {
2449 throw new BaseException$1("\"" + routeName + "/\" is only allowed at the beginning of a link DSL.");
2450 }
2451 linkParamIndex += 1;
2452 if (linkParamIndex < linkParams.length) {
2453 var linkParam = linkParams[linkParamIndex];
2454 if (isStringMap(linkParam) && !isArray(linkParam)) {
2455 routeParams = linkParam;
2456 linkParamIndex += 1;
2457 }
2458 }
2459 var routeRecognizer = (_aux ? rules.auxRulesByName : rules.rulesByName).get(routeName);
2460 if (isBlank(routeRecognizer)) {
2461 throw new BaseException$1("Component \"" + getTypeNameForDebugging(parentComponentType) + "\" has no route named \"" + routeName + "\".");
2462 }
2463 // Create an "unresolved instruction" for async routes
2464 // we'll figure out the rest of the route when we resolve the instruction and
2465 // perform a navigation
2466 if (isBlank(routeRecognizer.handler.componentType)) {
2467 var generatedUrl = routeRecognizer.generateComponentPathValues(routeParams);
2468 return new UnresolvedInstruction(function () {
2469 return routeRecognizer.handler.resolveComponentType().then(function (_) {
2470 return _this._generate(linkParams, ancestorInstructions, prevInstruction, _aux, _originalLink);
2471 });
2472 }, generatedUrl.urlPath, convertUrlParamsToArray(generatedUrl.urlParams));
2473 }
2474 componentInstruction = _aux ? rules.generateAuxiliary(routeName, routeParams) :
2475 rules.generate(routeName, routeParams);
2476 }
2477 // Next, recognize auxiliary instructions.
2478 // If we have an ancestor instruction, we preserve whatever aux routes are active from it.
2479 while (linkParamIndex < linkParams.length && isArray(linkParams[linkParamIndex])) {
2480 var auxParentInstruction = [parentInstruction];
2481 var auxInstruction = this._generate(linkParams[linkParamIndex], auxParentInstruction, null, true, _originalLink);
2482 // TODO: this will not work for aux routes with parameters or multiple segments
2483 auxInstructions[auxInstruction.component.urlPath] = auxInstruction;
2484 linkParamIndex += 1;
2485 }
2486 var instruction = new ResolvedInstruction(componentInstruction, null, auxInstructions);
2487 // If the component is sync, we can generate resolved child route instructions
2488 // If not, we'll resolve the instructions at navigation time
2489 if (isPresent(componentInstruction) && isPresent(componentInstruction.componentType)) {
2490 var childInstruction = null;
2491 if (componentInstruction.terminal) {
2492 if (linkParamIndex >= linkParams.length) {
2493 }
2494 }
2495 else {
2496 var childAncestorComponents = ancestorInstructions.concat([instruction]);
2497 var remainingLinkParams = linkParams.slice(linkParamIndex);
2498 childInstruction = this._generate(remainingLinkParams, childAncestorComponents, null, false, _originalLink);
2499 }
2500 instruction.child = childInstruction;
2501 }
2502 return instruction;
2503 };
2504 RouteRegistry.prototype.hasRoute = function (name, parentComponent) {
2505 var rules = this._rules.get(parentComponent);
2506 if (isBlank(rules)) {
2507 return false;
2508 }
2509 return rules.hasRoute(name);
2510 };
2511 RouteRegistry.prototype.generateDefault = function (componentCursor) {
2512 var _this = this;
2513 if (isBlank(componentCursor)) {
2514 return null;
2515 }
2516 var rules = this._rules.get(componentCursor);
2517 if (isBlank(rules) || isBlank(rules.defaultRule)) {
2518 return null;
2519 }
2520 var defaultChild = null;
2521 if (isPresent(rules.defaultRule.handler.componentType)) {
2522 var componentInstruction = rules.defaultRule.generate({});
2523 if (!rules.defaultRule.terminal) {
2524 defaultChild = this.generateDefault(rules.defaultRule.handler.componentType);
2525 }
2526 return new DefaultInstruction(componentInstruction, defaultChild);
2527 }
2528 return new UnresolvedInstruction(function () {
2529 return rules.defaultRule.handler.resolveComponentType().then(function (_) { return _this.generateDefault(componentCursor); });
2530 });
2531 };
2532 return RouteRegistry;
2533 }());
2534 exports.RouteRegistry = __decorate$2([
2535 _angular_core.Injectable(),
2536 __param$1(0, _angular_core.Inject(ROUTER_PRIMARY_COMPONENT)),
2537 __metadata$2('design:paramtypes', [Type$1])
2538 ], exports.RouteRegistry);
2539 /*
2540 * Given: ['/a/b', {c: 2}]
2541 * Returns: ['', 'a', 'b', {c: 2}]
2542 */
2543 function splitAndFlattenLinkParams(linkParams) {
2544 var accumulation = [];
2545 linkParams.forEach(function (item) {
2546 if (isString(item)) {
2547 var strItem = item;
2548 accumulation = accumulation.concat(strItem.split('/'));
2549 }
2550 else {
2551 accumulation.push(item);
2552 }
2553 });
2554 return accumulation;
2555 }
2556 /*
2557 * Given a list of instructions, returns the most specific instruction
2558 */
2559 function mostSpecific(instructions) {
2560 instructions = instructions.filter(function (instruction) { return isPresent(instruction); });
2561 if (instructions.length == 0) {
2562 return null;
2563 }
2564 if (instructions.length == 1) {
2565 return instructions[0];
2566 }
2567 var first = instructions[0];
2568 var rest = instructions.slice(1);
2569 return rest.reduce(function (instruction, contender) {
2570 if (compareSpecificityStrings(contender.specificity, instruction.specificity) == -1) {
2571 return contender;
2572 }
2573 return instruction;
2574 }, first);
2575 }
2576 /*
2577 * Expects strings to be in the form of "[0-2]+"
2578 * Returns -1 if string A should be sorted above string B, 1 if it should be sorted after,
2579 * or 0 if they are the same.
2580 */
2581 function compareSpecificityStrings(a, b) {
2582 var l = Math.min(a.length, b.length);
2583 for (var i = 0; i < l; i += 1) {
2584 var ai = StringWrapper.charCodeAt(a, i);
2585 var bi = StringWrapper.charCodeAt(b, i);
2586 var difference = bi - ai;
2587 if (difference != 0) {
2588 return difference;
2589 }
2590 }
2591 return a.length - b.length;
2592 }
2593 function assertTerminalComponent(component /** TODO #9100 */, path /** TODO #9100 */) {
2594 if (!isType(component)) {
2595 return;
2596 }
2597 var annotations = reflector.annotations(component);
2598 if (isPresent(annotations)) {
2599 for (var i = 0; i < annotations.length; i++) {
2600 var annotation = annotations[i];
2601 if (annotation instanceof RouteConfigAnnotation) {
2602 throw new BaseException$1("Child routes are not allowed for \"" + path + "\". Use \"...\" on the parent's route path.");
2603 }
2604 }
2605 }
2606 }
2607 var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
2608 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2609 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2610 r = Reflect.decorate(decorators, target, key, desc);
2611 else
2612 for (var i = decorators.length - 1; i >= 0; i--)
2613 if (d = decorators[i])
2614 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2615 return c > 3 && r && Object.defineProperty(target, key, r), r;
2616 };
2617 var __metadata$1 = (this && this.__metadata) || function (k, v) {
2618 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
2619 return Reflect.metadata(k, v);
2620 };
2621 var __param = (this && this.__param) || function (paramIndex, decorator) {
2622 return function (target, key) { decorator(target, key, paramIndex); };
2623 };
2624 var _resolveToTrue = PromiseWrapper.resolve(true);
2625 var _resolveToFalse = PromiseWrapper.resolve(false);
2626 /**
2627 * The `Router` is responsible for mapping URLs to components.
2628 *
2629 * You can see the state of the router by inspecting the read-only field `router.navigating`.
2630 * This may be useful for showing a spinner, for instance.
2631 *
2632 * ## Concepts
2633 *
2634 * Routers and component instances have a 1:1 correspondence.
2635 *
2636 * The router holds reference to a number of {@link RouterOutlet}.
2637 * An outlet is a placeholder that the router dynamically fills in depending on the current URL.
2638 *
2639 * When the router navigates from a URL, it must first recognize it and serialize it into an
2640 * `Instruction`.
2641 * The router uses the `RouteRegistry` to get an `Instruction`.
2642 */
2643 exports.Router = (function () {
2644 function Router(registry, parent, hostComponent, root) {
2645 this.registry = registry;
2646 this.parent = parent;
2647 this.hostComponent = hostComponent;
2648 this.root = root;
2649 this.navigating = false;
2650 /**
2651 * The current `Instruction` for the router
2652 */
2653 this.currentInstruction = null;
2654 this._currentNavigation = _resolveToTrue;
2655 this._outlet = null;
2656 this._auxRouters = new Map$1();
2657 this._subject = new EventEmitter();
2658 }
2659 /**
2660 * Constructs a child router. You probably don't need to use this unless you're writing a reusable
2661 * component.
2662 */
2663 Router.prototype.childRouter = function (hostComponent) {
2664 return this._childRouter = new ChildRouter(this, hostComponent);
2665 };
2666 /**
2667 * Constructs a child router. You probably don't need to use this unless you're writing a reusable
2668 * component.
2669 */
2670 Router.prototype.auxRouter = function (hostComponent) { return new ChildRouter(this, hostComponent); };
2671 /**
2672 * Register an outlet to be notified of primary route changes.
2673 *
2674 * You probably don't need to use this unless you're writing a reusable component.
2675 */
2676 Router.prototype.registerPrimaryOutlet = function (outlet) {
2677 if (isPresent(outlet.name)) {
2678 throw new BaseException$1("registerPrimaryOutlet expects to be called with an unnamed outlet.");
2679 }
2680 if (isPresent(this._outlet)) {
2681 throw new BaseException$1("Primary outlet is already registered.");
2682 }
2683 this._outlet = outlet;
2684 if (isPresent(this.currentInstruction)) {
2685 return this.commit(this.currentInstruction, false);
2686 }
2687 return _resolveToTrue;
2688 };
2689 /**
2690 * Unregister an outlet (because it was destroyed, etc).
2691 *
2692 * You probably don't need to use this unless you're writing a custom outlet implementation.
2693 */
2694 Router.prototype.unregisterPrimaryOutlet = function (outlet) {
2695 if (isPresent(outlet.name)) {
2696 throw new BaseException$1("registerPrimaryOutlet expects to be called with an unnamed outlet.");
2697 }
2698 this._outlet = null;
2699 };
2700 /**
2701 * Register an outlet to notified of auxiliary route changes.
2702 *
2703 * You probably don't need to use this unless you're writing a reusable component.
2704 */
2705 Router.prototype.registerAuxOutlet = function (outlet) {
2706 var outletName = outlet.name;
2707 if (isBlank(outletName)) {
2708 throw new BaseException$1("registerAuxOutlet expects to be called with an outlet with a name.");
2709 }
2710 var router = this.auxRouter(this.hostComponent);
2711 this._auxRouters.set(outletName, router);
2712 router._outlet = outlet;
2713 var auxInstruction;
2714 if (isPresent(this.currentInstruction) &&
2715 isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) {
2716 return router.commit(auxInstruction);
2717 }
2718 return _resolveToTrue;
2719 };
2720 /**
2721 * Given an instruction, returns `true` if the instruction is currently active,
2722 * otherwise `false`.
2723 */
2724 Router.prototype.isRouteActive = function (instruction) {
2725 var router = this;
2726 var currentInstruction = this.currentInstruction;
2727 if (isBlank(currentInstruction)) {
2728 return false;
2729 }
2730 // `instruction` corresponds to the root router
2731 while (isPresent(router.parent) && isPresent(instruction.child)) {
2732 router = router.parent;
2733 instruction = instruction.child;
2734 }
2735 var reason = true;
2736 // check the instructions in depth
2737 do {
2738 if (isBlank(instruction.component) || isBlank(currentInstruction.component) ||
2739 currentInstruction.component.routeName != instruction.component.routeName) {
2740 return false;
2741 }
2742 if (isPresent(instruction.component.params)) {
2743 StringMapWrapper.forEach(instruction.component.params, function (value /** TODO #9100 */, key /** TODO #9100 */) {
2744 if (currentInstruction.component.params[key] !== value) {
2745 reason = false;
2746 }
2747 });
2748 }
2749 currentInstruction = currentInstruction.child;
2750 instruction = instruction.child;
2751 } while (isPresent(currentInstruction) && isPresent(instruction) &&
2752 !(instruction instanceof DefaultInstruction) && reason);
2753 // ignore DefaultInstruction
2754 return reason && (isBlank(instruction) || instruction instanceof DefaultInstruction);
2755 };
2756 /**
2757 * Dynamically update the routing configuration and trigger a navigation.
2758 *
2759 * ### Usage
2760 *
2761 * ```
2762 * router.config([
2763 * { 'path': '/', 'component': IndexComp },
2764 * { 'path': '/user/:id', 'component': UserComp },
2765 * ]);
2766 * ```
2767 */
2768 Router.prototype.config = function (definitions) {
2769 var _this = this;
2770 definitions.forEach(function (routeDefinition) { _this.registry.config(_this.hostComponent, routeDefinition); });
2771 return this.renavigate();
2772 };
2773 /**
2774 * Navigate based on the provided Route Link DSL. It's preferred to navigate with this method
2775 * over `navigateByUrl`.
2776 *
2777 * ### Usage
2778 *
2779 * This method takes an array representing the Route Link DSL:
2780 * ```
2781 * ['./MyCmp', {param: 3}]
2782 * ```
2783 * See the {@link RouterLink} directive for more.
2784 */
2785 Router.prototype.navigate = function (linkParams) {
2786 var instruction = this.generate(linkParams);
2787 return this.navigateByInstruction(instruction, false);
2788 };
2789 /**
2790 * Navigate to a URL. Returns a promise that resolves when navigation is complete.
2791 * It's preferred to navigate with `navigate` instead of this method, since URLs are more brittle.
2792 *
2793 * If the given URL begins with a `/`, router will navigate absolutely.
2794 * If the given URL does not begin with `/`, the router will navigate relative to this component.
2795 */
2796 Router.prototype.navigateByUrl = function (url, _skipLocationChange) {
2797 var _this = this;
2798 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
2799 return this._currentNavigation = this._currentNavigation.then(function (_) {
2800 _this.lastNavigationAttempt = url;
2801 _this._startNavigating();
2802 return _this._afterPromiseFinishNavigating(_this.recognize(url).then(function (instruction) {
2803 if (isBlank(instruction)) {
2804 return false;
2805 }
2806 return _this._navigate(instruction, _skipLocationChange);
2807 }));
2808 });
2809 };
2810 /**
2811 * Navigate via the provided instruction. Returns a promise that resolves when navigation is
2812 * complete.
2813 */
2814 Router.prototype.navigateByInstruction = function (instruction, _skipLocationChange) {
2815 var _this = this;
2816 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
2817 if (isBlank(instruction)) {
2818 return _resolveToFalse;
2819 }
2820 return this._currentNavigation = this._currentNavigation.then(function (_) {
2821 _this._startNavigating();
2822 return _this._afterPromiseFinishNavigating(_this._navigate(instruction, _skipLocationChange));
2823 });
2824 };
2825 /** @internal */
2826 Router.prototype._settleInstruction = function (instruction) {
2827 var _this = this;
2828 return instruction.resolveComponent().then(function (_) {
2829 var unsettledInstructions = [];
2830 if (isPresent(instruction.component)) {
2831 instruction.component.reuse = false;
2832 }
2833 if (isPresent(instruction.child)) {
2834 unsettledInstructions.push(_this._settleInstruction(instruction.child));
2835 }
2836 StringMapWrapper.forEach(instruction.auxInstruction, function (instruction, _ /** TODO #9100 */) {
2837 unsettledInstructions.push(_this._settleInstruction(instruction));
2838 });
2839 return PromiseWrapper.all(unsettledInstructions);
2840 });
2841 };
2842 /** @internal */
2843 Router.prototype._navigate = function (instruction, _skipLocationChange) {
2844 var _this = this;
2845 return this._settleInstruction(instruction)
2846 .then(function (_) { return _this._routerCanReuse(instruction); })
2847 .then(function (_) { return _this._canActivate(instruction); })
2848 .then(function (result) {
2849 if (!result) {
2850 return false;
2851 }
2852 return _this._routerCanDeactivate(instruction).then(function (result) {
2853 if (result) {
2854 return _this.commit(instruction, _skipLocationChange).then(function (_) {
2855 _this._emitNavigationFinish(instruction.component);
2856 return true;
2857 });
2858 }
2859 });
2860 });
2861 };
2862 Router.prototype._emitNavigationFinish = function (instruction) {
2863 ObservableWrapper.callEmit(this._subject, { status: 'success', instruction: instruction });
2864 };
2865 /** @internal */
2866 Router.prototype._emitNavigationFail = function (url) {
2867 ObservableWrapper.callEmit(this._subject, { status: 'fail', url: url });
2868 };
2869 Router.prototype._afterPromiseFinishNavigating = function (promise) {
2870 var _this = this;
2871 return PromiseWrapper.catchError(promise.then(function (_) { return _this._finishNavigating(); }), function (err) {
2872 _this._finishNavigating();
2873 throw err;
2874 });
2875 };
2876 /*
2877 * Recursively set reuse flags
2878 */
2879 /** @internal */
2880 Router.prototype._routerCanReuse = function (instruction) {
2881 var _this = this;
2882 if (isBlank(this._outlet)) {
2883 return _resolveToFalse;
2884 }
2885 if (isBlank(instruction.component)) {
2886 return _resolveToTrue;
2887 }
2888 return this._outlet.routerCanReuse(instruction.component).then(function (result) {
2889 instruction.component.reuse = result;
2890 if (result && isPresent(_this._childRouter) && isPresent(instruction.child)) {
2891 return _this._childRouter._routerCanReuse(instruction.child);
2892 }
2893 });
2894 };
2895 Router.prototype._canActivate = function (nextInstruction) {
2896 return canActivateOne(nextInstruction, this.currentInstruction);
2897 };
2898 Router.prototype._routerCanDeactivate = function (instruction) {
2899 var _this = this;
2900 if (isBlank(this._outlet)) {
2901 return _resolveToTrue;
2902 }
2903 var next;
2904 var childInstruction = null;
2905 var reuse = false;
2906 var componentInstruction = null;
2907 if (isPresent(instruction)) {
2908 childInstruction = instruction.child;
2909 componentInstruction = instruction.component;
2910 reuse = isBlank(instruction.component) || instruction.component.reuse;
2911 }
2912 if (reuse) {
2913 next = _resolveToTrue;
2914 }
2915 else {
2916 next = this._outlet.routerCanDeactivate(componentInstruction);
2917 }
2918 // TODO: aux route lifecycle hooks
2919 return next.then(function (result) {
2920 if (result == false) {
2921 return false;
2922 }
2923 if (isPresent(_this._childRouter)) {
2924 // TODO: ideally, this closure would map to async-await in Dart.
2925 // For now, casting to any to suppress an error.
2926 return _this._childRouter._routerCanDeactivate(childInstruction);
2927 }
2928 return true;
2929 });
2930 };
2931 /**
2932 * Updates this router and all descendant routers according to the given instruction
2933 */
2934 Router.prototype.commit = function (instruction, _skipLocationChange) {
2935 var _this = this;
2936 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
2937 this.currentInstruction = instruction;
2938 var next = _resolveToTrue;
2939 if (isPresent(this._outlet) && isPresent(instruction.component)) {
2940 var componentInstruction = instruction.component;
2941 if (componentInstruction.reuse) {
2942 next = this._outlet.reuse(componentInstruction);
2943 }
2944 else {
2945 next =
2946 this.deactivate(instruction).then(function (_) { return _this._outlet.activate(componentInstruction); });
2947 }
2948 if (isPresent(instruction.child)) {
2949 next = next.then(function (_) {
2950 if (isPresent(_this._childRouter)) {
2951 return _this._childRouter.commit(instruction.child);
2952 }
2953 });
2954 }
2955 }
2956 var promises = [];
2957 this._auxRouters.forEach(function (router, name) {
2958 if (isPresent(instruction.auxInstruction[name])) {
2959 promises.push(router.commit(instruction.auxInstruction[name]));
2960 }
2961 });
2962 return next.then(function (_) { return PromiseWrapper.all(promises); });
2963 };
2964 /** @internal */
2965 Router.prototype._startNavigating = function () { this.navigating = true; };
2966 /** @internal */
2967 Router.prototype._finishNavigating = function () { this.navigating = false; };
2968 /**
2969 * Subscribe to URL updates from the router
2970 */
2971 Router.prototype.subscribe = function (onNext, onError) {
2972 return ObservableWrapper.subscribe(this._subject, onNext, onError);
2973 };
2974 /**
2975 * Removes the contents of this router's outlet and all descendant outlets
2976 */
2977 Router.prototype.deactivate = function (instruction) {
2978 var _this = this;
2979 var childInstruction = null;
2980 var componentInstruction = null;
2981 if (isPresent(instruction)) {
2982 childInstruction = instruction.child;
2983 componentInstruction = instruction.component;
2984 }
2985 var next = _resolveToTrue;
2986 if (isPresent(this._childRouter)) {
2987 next = this._childRouter.deactivate(childInstruction);
2988 }
2989 if (isPresent(this._outlet)) {
2990 next = next.then(function (_) { return _this._outlet.deactivate(componentInstruction); });
2991 }
2992 // TODO: handle aux routes
2993 return next;
2994 };
2995 /**
2996 * Given a URL, returns an instruction representing the component graph
2997 */
2998 Router.prototype.recognize = function (url) {
2999 var ancestorComponents = this._getAncestorInstructions();
3000 return this.registry.recognize(url, ancestorComponents);
3001 };
3002 Router.prototype._getAncestorInstructions = function () {
3003 var ancestorInstructions = [this.currentInstruction];
3004 var ancestorRouter = this;
3005 while (isPresent(ancestorRouter = ancestorRouter.parent)) {
3006 ancestorInstructions.unshift(ancestorRouter.currentInstruction);
3007 }
3008 return ancestorInstructions;
3009 };
3010 /**
3011 * Navigates to either the last URL successfully navigated to, or the last URL requested if the
3012 * router has yet to successfully navigate.
3013 */
3014 Router.prototype.renavigate = function () {
3015 if (isBlank(this.lastNavigationAttempt)) {
3016 return this._currentNavigation;
3017 }
3018 return this.navigateByUrl(this.lastNavigationAttempt);
3019 };
3020 /**
3021 * Generate an `Instruction` based on the provided Route Link DSL.
3022 */
3023 Router.prototype.generate = function (linkParams) {
3024 var ancestorInstructions = this._getAncestorInstructions();
3025 return this.registry.generate(linkParams, ancestorInstructions);
3026 };
3027 return Router;
3028 }());
3029 exports.Router = __decorate$1([
3030 _angular_core.Injectable(),
3031 __metadata$1('design:paramtypes', [exports.RouteRegistry, exports.Router, Object, exports.Router])
3032 ], exports.Router);
3033 exports.RootRouter = (function (_super) {
3034 __extends(RootRouter, _super);
3035 function RootRouter(registry, location, primaryComponent) {
3036 var _this = this;
3037 _super.call(this, registry, null, primaryComponent);
3038 this.root = this;
3039 this._location = location;
3040 this._locationSub = this._location.subscribe(function (change) {
3041 // we call recognize ourselves
3042 _this.recognize(change['url']).then(function (instruction) {
3043 if (isPresent(instruction)) {
3044 _this.navigateByInstruction(instruction, isPresent(change['pop'])).then(function (_) {
3045 // this is a popstate event; no need to change the URL
3046 if (isPresent(change['pop']) && change['type'] != 'hashchange') {
3047 return;
3048 }
3049 var emitPath = instruction.toUrlPath();
3050 var emitQuery = instruction.toUrlQuery();
3051 if (emitPath.length > 0 && emitPath[0] != '/') {
3052 emitPath = '/' + emitPath;
3053 }
3054 // We've opted to use pushstate and popState APIs regardless of whether you
3055 // an app uses HashLocationStrategy or PathLocationStrategy.
3056 // However, apps that are migrating might have hash links that operate outside
3057 // angular to which routing must respond.
3058 // Therefore we know that all hashchange events occur outside Angular.
3059 // To support these cases where we respond to hashchanges and redirect as a
3060 // result, we need to replace the top item on the stack.
3061 if (change['type'] == 'hashchange') {
3062 if (instruction.toRootUrl() != _this._location.path()) {
3063 _this._location.replaceState(emitPath, emitQuery);
3064 }
3065 }
3066 else {
3067 _this._location.go(emitPath, emitQuery);
3068 }
3069 });
3070 }
3071 else {
3072 _this._emitNavigationFail(change['url']);
3073 }
3074 });
3075 });
3076 this.registry.configFromComponent(primaryComponent);
3077 this.navigateByUrl(location.path());
3078 }
3079 RootRouter.prototype.commit = function (instruction, _skipLocationChange) {
3080 var _this = this;
3081 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
3082 var emitPath = instruction.toUrlPath();
3083 var emitQuery = instruction.toUrlQuery();
3084 if (emitPath.length > 0 && emitPath[0] != '/') {
3085 emitPath = '/' + emitPath;
3086 }
3087 var promise = _super.prototype.commit.call(this, instruction);
3088 if (!_skipLocationChange) {
3089 if (this._location.isCurrentPathEqualTo(emitPath, emitQuery)) {
3090 promise = promise.then(function (_) { _this._location.replaceState(emitPath, emitQuery); });
3091 }
3092 else {
3093 promise = promise.then(function (_) { _this._location.go(emitPath, emitQuery); });
3094 }
3095 }
3096 return promise;
3097 };
3098 RootRouter.prototype.dispose = function () {
3099 if (isPresent(this._locationSub)) {
3100 ObservableWrapper.dispose(this._locationSub);
3101 this._locationSub = null;
3102 }
3103 };
3104 return RootRouter;
3105 }(exports.Router));
3106 exports.RootRouter = __decorate$1([
3107 _angular_core.Injectable(),
3108 __param(2, _angular_core.Inject(ROUTER_PRIMARY_COMPONENT)),
3109 __metadata$1('design:paramtypes', [exports.RouteRegistry, _angular_common.Location, Type$1])
3110 ], exports.RootRouter);
3111 var ChildRouter = (function (_super) {
3112 __extends(ChildRouter, _super);
3113 function ChildRouter(parent, hostComponent /** TODO #9100 */) {
3114 _super.call(this, parent.registry, parent, hostComponent, parent.root);
3115 this.parent = parent;
3116 }
3117 ChildRouter.prototype.navigateByUrl = function (url, _skipLocationChange) {
3118 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
3119 // Delegate navigation to the root router
3120 return this.parent.navigateByUrl(url, _skipLocationChange);
3121 };
3122 ChildRouter.prototype.navigateByInstruction = function (instruction, _skipLocationChange) {
3123 if (_skipLocationChange === void 0) { _skipLocationChange = false; }
3124 // Delegate navigation to the root router
3125 return this.parent.navigateByInstruction(instruction, _skipLocationChange);
3126 };
3127 return ChildRouter;
3128 }(exports.Router));
3129 function canActivateOne(nextInstruction, prevInstruction) {
3130 var next = _resolveToTrue;
3131 if (isBlank(nextInstruction.component)) {
3132 return next;
3133 }
3134 if (isPresent(nextInstruction.child)) {
3135 next = canActivateOne(nextInstruction.child, isPresent(prevInstruction) ? prevInstruction.child : null);
3136 }
3137 return next.then(function (result) {
3138 if (result == false) {
3139 return false;
3140 }
3141 if (nextInstruction.component.reuse) {
3142 return true;
3143 }
3144 var hook = getCanActivateHook(nextInstruction.component.componentType);
3145 if (isPresent(hook)) {
3146 return hook(nextInstruction.component, isPresent(prevInstruction) ? prevInstruction.component : null);
3147 }
3148 return true;
3149 });
3150 }
3151 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3152 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3153 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3154 r = Reflect.decorate(decorators, target, key, desc);
3155 else
3156 for (var i = decorators.length - 1; i >= 0; i--)
3157 if (d = decorators[i])
3158 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3159 return c > 3 && r && Object.defineProperty(target, key, r), r;
3160 };
3161 var __metadata = (this && this.__metadata) || function (k, v) {
3162 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
3163 return Reflect.metadata(k, v);
3164 };
3165 /**
3166 * The RouterLink directive lets you link to specific parts of your app.
3167 *
3168 * Consider the following route configuration:
3169
3170 * ```
3171 * @RouteConfig([
3172 * { path: '/user', component: UserCmp, name: 'User' }
3173 * ]);
3174 * class MyComp {}
3175 * ```
3176 *
3177 * When linking to this `User` route, you can write:
3178 *
3179 * ```
3180 * <a [routerLink]="['./User']">link to user component</a>
3181 * ```
3182 *
3183 * RouterLink expects the value to be an array of route names, followed by the params
3184 * for that level of routing. For instance `['/Team', {teamId: 1}, 'User', {userId: 2}]`
3185 * means that we want to generate a link for the `Team` route with params `{teamId: 1}`,
3186 * and with a child route `User` with params `{userId: 2}`.
3187 *
3188 * The first route name should be prepended with `/`, `./`, or `../`.
3189 * If the route begins with `/`, the router will look up the route from the root of the app.
3190 * If the route begins with `./`, the router will instead look in the current component's
3191 * children for the route. And if the route begins with `../`, the router will look at the
3192 * current component's parent.
3193 */
3194 exports.RouterLink = (function () {
3195 function RouterLink(_router, _location) {
3196 var _this = this;
3197 this._router = _router;
3198 this._location = _location;
3199 // we need to update the link whenever a route changes to account for aux routes
3200 this._router.subscribe(function (_) { return _this._updateLink(); });
3201 }
3202 // because auxiliary links take existing primary and auxiliary routes into account,
3203 // we need to update the link whenever params or other routes change.
3204 RouterLink.prototype._updateLink = function () {
3205 this._navigationInstruction = this._router.generate(this._routeParams);
3206 var navigationHref = this._navigationInstruction.toLinkUrl();
3207 this.visibleHref = this._location.prepareExternalUrl(navigationHref);
3208 };
3209 Object.defineProperty(RouterLink.prototype, "isRouteActive", {
3210 get: function () { return this._router.isRouteActive(this._navigationInstruction); },
3211 enumerable: true,
3212 configurable: true
3213 });
3214 Object.defineProperty(RouterLink.prototype, "routeParams", {
3215 set: function (changes) {
3216 this._routeParams = changes;
3217 this._updateLink();
3218 },
3219 enumerable: true,
3220 configurable: true
3221 });
3222 RouterLink.prototype.onClick = function () {
3223 // If no target, or if target is _self, prevent default browser behavior
3224 if (!isString(this.target) || this.target == '_self') {
3225 this._router.navigateByInstruction(this._navigationInstruction);
3226 return false;
3227 }
3228 return true;
3229 };
3230 return RouterLink;
3231 }());
3232 exports.RouterLink = __decorate([
3233 _angular_core.Directive({
3234 selector: '[routerLink]',
3235 inputs: ['routeParams: routerLink', 'target: target'],
3236 host: {
3237 '(click)': 'onClick()',
3238 '[attr.href]': 'visibleHref',
3239 '[class.router-link-active]': 'isRouteActive'
3240 }
3241 }),
3242 __metadata('design:paramtypes', [exports.Router, _angular_common.Location])
3243 ], exports.RouterLink);
3244 /**
3245 * Defines route lifecycle hook `CanActivate`, which is called by the router to determine
3246 * if a component can be instantiated as part of a navigation.
3247 *
3248 * <aside class="is-right">
3249 * Note that unlike other lifecycle hooks, this one uses an annotation rather than an interface.
3250 * This is because the `CanActivate` function is called before the component is instantiated.
3251 * </aside>
3252 *
3253 * The `CanActivate` hook is called with two {@link ComponentInstruction}s as parameters, the first
3254 * representing the current route being navigated to, and the second parameter representing the
3255 * previous route or `null`.
3256 *
3257 * ```typescript
3258 * @CanActivate((next, prev) => boolean | Promise<boolean>)
3259 * ```
3260 *
3261 * If `CanActivate` returns or resolves to `false`, the navigation is cancelled.
3262 * If `CanActivate` throws or rejects, the navigation is also cancelled.
3263 * If `CanActivate` returns or resolves to `true`, navigation continues, the component is
3264 * instantiated, and the {@link OnActivate} hook of that component is called if implemented.
3265 *
3266 * ### Example
3267 *
3268 * {@example router/ts/can_activate/can_activate_example.ts region='canActivate' }
3269 */
3270 var CanActivate = makeDecorator(CanActivateAnnotation);
3271 var __decorate$3 = (this && this.__decorate) || function (decorators, target, key, desc) {
3272 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3273 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3274 r = Reflect.decorate(decorators, target, key, desc);
3275 else
3276 for (var i = decorators.length - 1; i >= 0; i--)
3277 if (d = decorators[i])
3278 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3279 return c > 3 && r && Object.defineProperty(target, key, r), r;
3280 };
3281 var __metadata$3 = (this && this.__metadata) || function (k, v) {
3282 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
3283 return Reflect.metadata(k, v);
3284 };
3285 var __param$2 = (this && this.__param) || function (paramIndex, decorator) {
3286 return function (target, key) { decorator(target, key, paramIndex); };
3287 };
3288 var _resolveToTrue$1 = PromiseWrapper.resolve(true);
3289 /**
3290 * A router outlet is a placeholder that Angular dynamically fills based on the application's route.
3291 *
3292 * ## Use
3293 *
3294 * ```
3295 * <router-outlet></router-outlet>
3296 * ```
3297 */
3298 exports.RouterOutlet = (function () {
3299 function RouterOutlet(_viewContainerRef, _loader, _parentRouter, nameAttr) {
3300 this._viewContainerRef = _viewContainerRef;
3301 this._loader = _loader;
3302 this._parentRouter = _parentRouter;
3303 this.name = null;
3304 this._componentRef = null;
3305 this._currentInstruction = null;
3306 this.activateEvents = new EventEmitter();
3307 if (isPresent(nameAttr)) {
3308 this.name = nameAttr;
3309 this._parentRouter.registerAuxOutlet(this);
3310 }
3311 else {
3312 this._parentRouter.registerPrimaryOutlet(this);
3313 }
3314 }
3315 /**
3316 * Called by the Router to instantiate a new component during the commit phase of a navigation.
3317 * This method in turn is responsible for calling the `routerOnActivate` hook of its child.
3318 */
3319 RouterOutlet.prototype.activate = function (nextInstruction) {
3320 var _this = this;
3321 var previousInstruction = this._currentInstruction;
3322 this._currentInstruction = nextInstruction;
3323 var componentType = nextInstruction.componentType;
3324 var childRouter = this._parentRouter.childRouter(componentType);
3325 var providers = _angular_core.ReflectiveInjector.resolve([
3326 { provide: RouteData, useValue: nextInstruction.routeData },
3327 { provide: RouteParams, useValue: new RouteParams(nextInstruction.params) },
3328 { provide: exports.Router, useValue: childRouter }
3329 ]);
3330 this._componentRef =
3331 this._loader.loadNextToLocation(componentType, this._viewContainerRef, providers);
3332 return this._componentRef.then(function (componentRef) {
3333 _this.activateEvents.emit(componentRef.instance);
3334 if (hasLifecycleHook(routerOnActivate, componentType)) {
3335 return _this._componentRef.then(function (ref) { return ref.instance.routerOnActivate(nextInstruction, previousInstruction); });
3336 }
3337 else {
3338 return componentRef;
3339 }
3340 });
3341 };
3342 /**
3343 * Called by the {@link Router} during the commit phase of a navigation when an outlet
3344 * reuses a component between different routes.
3345 * This method in turn is responsible for calling the `routerOnReuse` hook of its child.
3346 */
3347 RouterOutlet.prototype.reuse = function (nextInstruction) {
3348 var previousInstruction = this._currentInstruction;
3349 this._currentInstruction = nextInstruction;
3350 // it's possible the component is removed before it can be reactivated (if nested withing
3351 // another dynamically loaded component, for instance). In that case, we simply activate
3352 // a new one.
3353 if (isBlank(this._componentRef)) {
3354 return this.activate(nextInstruction);
3355 }
3356 else {
3357 return PromiseWrapper.resolve(hasLifecycleHook(routerOnReuse, this._currentInstruction.componentType) ?
3358 this._componentRef.then(function (ref) { return ref.instance.routerOnReuse(nextInstruction, previousInstruction); }) :
3359 true);
3360 }
3361 };
3362 /**
3363 * Called by the {@link Router} when an outlet disposes of a component's contents.
3364 * This method in turn is responsible for calling the `routerOnDeactivate` hook of its child.
3365 */
3366 RouterOutlet.prototype.deactivate = function (nextInstruction) {
3367 var _this = this;
3368 var next = _resolveToTrue$1;
3369 if (isPresent(this._componentRef) && isPresent(this._currentInstruction) &&
3370 hasLifecycleHook(routerOnDeactivate, this._currentInstruction.componentType)) {
3371 next = this._componentRef.then(function (ref) { return ref.instance
3372 .routerOnDeactivate(nextInstruction, _this._currentInstruction); });
3373 }
3374 return next.then(function (_) {
3375 if (isPresent(_this._componentRef)) {
3376 var onDispose = _this._componentRef.then(function (ref) { return ref.destroy(); });
3377 _this._componentRef = null;
3378 return onDispose;
3379 }
3380 });
3381 };
3382 /**
3383 * Called by the {@link Router} during recognition phase of a navigation.
3384 *
3385 * If this resolves to `false`, the given navigation is cancelled.
3386 *
3387 * This method delegates to the child component's `routerCanDeactivate` hook if it exists,
3388 * and otherwise resolves to true.
3389 */
3390 RouterOutlet.prototype.routerCanDeactivate = function (nextInstruction) {
3391 var _this = this;
3392 if (isBlank(this._currentInstruction)) {
3393 return _resolveToTrue$1;
3394 }
3395 if (hasLifecycleHook(routerCanDeactivate, this._currentInstruction.componentType)) {
3396 return this._componentRef.then(function (ref) { return ref.instance
3397 .routerCanDeactivate(nextInstruction, _this._currentInstruction); });
3398 }
3399 else {
3400 return _resolveToTrue$1;
3401 }
3402 };
3403 /**
3404 * Called by the {@link Router} during recognition phase of a navigation.
3405 *
3406 * If the new child component has a different Type than the existing child component,
3407 * this will resolve to `false`. You can't reuse an old component when the new component
3408 * is of a different Type.
3409 *
3410 * Otherwise, this method delegates to the child component's `routerCanReuse` hook if it exists,
3411 * or resolves to true if the hook is not present.
3412 */
3413 RouterOutlet.prototype.routerCanReuse = function (nextInstruction) {
3414 var _this = this;
3415 var result;
3416 if (isBlank(this._currentInstruction) ||
3417 this._currentInstruction.componentType != nextInstruction.componentType) {
3418 result = false;
3419 }
3420 else if (hasLifecycleHook(routerCanReuse, this._currentInstruction.componentType)) {
3421 result = this._componentRef.then(function (ref) { return ref.instance.routerCanReuse(nextInstruction, _this._currentInstruction); });
3422 }
3423 else {
3424 result = nextInstruction == this._currentInstruction ||
3425 (isPresent(nextInstruction.params) && isPresent(this._currentInstruction.params) &&
3426 StringMapWrapper.equals(nextInstruction.params, this._currentInstruction.params));
3427 }
3428 return PromiseWrapper.resolve(result);
3429 };
3430 RouterOutlet.prototype.ngOnDestroy = function () { this._parentRouter.unregisterPrimaryOutlet(this); };
3431 return RouterOutlet;
3432 }());
3433 __decorate$3([
3434 _angular_core.Output('activate'),
3435 __metadata$3('design:type', Object)
3436 ], exports.RouterOutlet.prototype, "activateEvents", void 0);
3437 exports.RouterOutlet = __decorate$3([
3438 _angular_core.Directive({ selector: 'router-outlet' }),
3439 __param$2(3, _angular_core.Attribute('name')),
3440 __metadata$3('design:paramtypes', [_angular_core.ViewContainerRef, _angular_core.DynamicComponentLoader, exports.Router, String])
3441 ], exports.RouterOutlet);
3442 /**
3443 * The Platform agnostic ROUTER PROVIDERS
3444 */
3445 var ROUTER_PROVIDERS_COMMON = [
3446 exports.RouteRegistry,
3447 /* @ts2dart_Provider */ { provide: _angular_common.LocationStrategy, useClass: _angular_common.PathLocationStrategy }, _angular_common.Location, {
3448 provide: exports.Router,
3449 useFactory: routerFactory,
3450 deps: [exports.RouteRegistry, _angular_common.Location, ROUTER_PRIMARY_COMPONENT, _angular_core.ApplicationRef]
3451 },
3452 {
3453 provide: ROUTER_PRIMARY_COMPONENT,
3454 useFactory: routerPrimaryComponentFactory,
3455 deps: /*@ts2dart_const*/ ([_angular_core.ApplicationRef])
3456 }
3457 ];
3458 function routerFactory(registry, location, primaryComponent, appRef) {
3459 var rootRouter = new exports.RootRouter(registry, location, primaryComponent);
3460 appRef.registerDisposeListener(function () { return rootRouter.dispose(); });
3461 return rootRouter;
3462 }
3463 function routerPrimaryComponentFactory(app) {
3464 if (app.componentTypes.length == 0) {
3465 throw new BaseException$1('Bootstrap at least one component before injecting Router.');
3466 }
3467 return app.componentTypes[0];
3468 }
3469 /**
3470 * A list of providers. To use the router, you must add this to your application.
3471 *
3472 * ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
3473 *
3474 * ```
3475 * import {Component} from '@angular/core';
3476 * import {
3477 * ROUTER_DIRECTIVES,
3478 * ROUTER_PROVIDERS,
3479 * RouteConfig
3480 * } from '@angular/router-deprecated';
3481 *
3482 * @Component({directives: [ROUTER_DIRECTIVES]})
3483 * @RouteConfig([
3484 * {...},
3485 * ])
3486 * class AppCmp {
3487 * // ...
3488 * }
3489 *
3490 * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
3491 * ```
3492 */
3493 var ROUTER_PROVIDERS = [
3494 ROUTER_PROVIDERS_COMMON,
3495 /*@ts2dart_const*/ (
3496 /* @ts2dart_Provider */ { provide: _angular_common.PlatformLocation, useClass: _angular_platformBrowser.BrowserPlatformLocation }),
3497 ];
3498 /**
3499 * Use {@link ROUTER_PROVIDERS} instead.
3500 *
3501 * @deprecated
3502 */
3503 var ROUTER_BINDINGS = ROUTER_PROVIDERS;
3504 /**
3505 * A list of directives. To use the router directives like {@link RouterOutlet} and
3506 * {@link RouterLink}, add this to your `directives` array in the {@link View} decorator of your
3507 * component.
3508 *
3509 * ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
3510 *
3511 * ```
3512 * import {Component} from '@angular/core';
3513 * import {ROUTER_DIRECTIVES, ROUTER_PROVIDERS, RouteConfig} from '@angular/router-deprecated';
3514 *
3515 * @Component({directives: [ROUTER_DIRECTIVES]})
3516 * @RouteConfig([
3517 * {...},
3518 * ])
3519 * class AppCmp {
3520 * // ...
3521 * }
3522 *
3523 * bootstrap(AppCmp, [ROUTER_PROVIDERS]);
3524 * ```
3525 */
3526 var ROUTER_DIRECTIVES = [exports.RouterOutlet, exports.RouterLink];
3527 exports.ROUTER_DIRECTIVES = ROUTER_DIRECTIVES;
3528 exports.RouteData = RouteData;
3529 exports.RouteParams = RouteParams;
3530 exports.ROUTER_PRIMARY_COMPONENT = ROUTER_PRIMARY_COMPONENT;
3531 exports.CanActivate = CanActivate;
3532 exports.Instruction = Instruction;
3533 exports.ComponentInstruction = ComponentInstruction;
3534 exports.OpaqueToken = _angular_core.OpaqueToken;
3535 exports.ROUTER_PROVIDERS_COMMON = ROUTER_PROVIDERS_COMMON;
3536 exports.ROUTER_PROVIDERS = ROUTER_PROVIDERS;
3537 exports.ROUTER_BINDINGS = ROUTER_BINDINGS;
3538 exports.RouteConfig = RouteConfig;
3539 exports.AsyncRoute = AsyncRoute;
3540 exports.AuxRoute = AuxRoute;
3541 exports.Redirect = Redirect;
3542 exports.Route = Route;
3543}));