Compare commits

...

10 Commits

Author SHA1 Message Date
6b57928d35 docs: add changelog for 2.4.10 2017-03-16 19:26:58 -07:00
47471ee49e release: cut the 2.4.10 release 2017-03-16 19:22:09 -07:00
b0ae464695 ci: changing deployment token 2017-03-16 16:11:17 -07:00
34403cda60 fix(router): do not finish bootstrap until all the routes are resolved (#15121)
Cherry-pick of 5df998d086 onto 2.4.x branch.

DEPRECATION:

Use `RouterModule.forRoot(routes, {initialNavigation: 'enabled'})` instead of
`RouterModule.forRoot(routes, {initialNavigtaion: true})`.

Before doing this, move the initialization logic affecting the router
from the bootstrapped component to the boostrapped module.

Similarly, use `RouterModule.forRoot(routes, {initialNavigation: 'disabled'})`
instead of `RouterModule.forRoot(routes, {initialNavigation: false})`.

Deprecated options: 'legacy_enabled', `true` (same as 'legacy_enabled'),
'legacy_disabled', `false` (same as 'legacy_disabled').

The "Router Initial Navigation" design document covers this change.
Read more here:
https://docs.google.com/document/d/1Hlw1fPaVs-PCj5KPeJRKhrQGAvFOxdvTlwAcnZosu5A/edit?usp=sharing
2017-03-16 15:39:30 -07:00
e5c9bbcbdd fix(compiler): fix decoding surrogate pairs (#15154) 2017-03-16 15:37:25 -07:00
80fe41a88e release: cut v2.4.9 2017-03-01 23:11:26 -08:00
af652a7c8b docs: add release notes for 2.4.9 2017-03-01 23:11:08 -08:00
de36f8a3b9 revert: fix(router): do not finish bootstrap until all the routes are resolved (#14327)
This reverts commit 541de26f7e because it introduced a regression.

Closes #14681, #14588
2017-02-27 14:37:33 -08:00
b658fa9ea0 fix(http): Make ResponseOptionsArgs an interface
closes #13708
2017-02-20 17:34:30 -08:00
2a123463ac fix(router): improve robustness (#14602)
sync a 4.x change from https://github.com/angular/angular/pull/14155
2017-02-20 16:59:28 -08:00
14 changed files with 305 additions and 78 deletions

View File

@ -23,9 +23,9 @@ cache:
env:
global:
# GITHUB_TOKEN_ANGULAR
# GITHUB_TOKEN_ANGULAR=<github token, a personal access token of the angular-builds account, account access in valentine>
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
- secure: "fq/U7VDMWO8O8SnAQkdbkoSe2X92PVqg4d044HmRYVmcf6YbO48+xeGJ8yOk0pCBwl3ISO4Q2ot0x546kxfiYBuHkZetlngZxZCtQiFT9kyId8ZKcYdXaIW9OVdw3Gh3tQyUwDucfkVhqcs52D6NZjyE2aWZ4/d1V4kWRO/LMgo="
- secure: "rNqXoy2gqjbF5tBXlRBy+oiYntO3BtzcxZuEtlLMzNaTNzC4dyMOFub0GkzIPWwOzkARoEU9Kv+bC97fDVbCBUKeyzzEqxqddUKhzRxeaYjsefJ6XeTvBvDxwo7wDwyxZSuWdBeGAe4eARVHm7ypsd+AlvqxtzjyS27TK2BzdL4="
matrix:
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
- CI_MODE=js

View File

@ -1,3 +1,29 @@
<a name="2.4.10"></a>
## [2.4.10](https://github.com/angular/angular/compare/2.4.9...2.4.10) (2017-03-17)
### Bug Fixes
* **compiler:** fix decoding surrogate pairs ([#15154](https://github.com/angular/angular/issues/15154)) ([e5c9bbc](https://github.com/angular/angular/commit/e5c9bbc))
* **router:** do not finish bootstrap until all the routes are resolved ([#15121](https://github.com/angular/angular/issues/15121)) ([34403cd](https://github.com/angular/angular/commit/34403cd))
<a name="2.4.9"></a>
## [2.4.9](https://github.com/angular/angular/compare/2.4.8...2.4.9) (2017-03-02)
### Bug Fixes
* **http:** Make ResponseOptionsArgs an interface ([b658fa9](https://github.com/angular/angular/commit/b658fa9)), closes [#13708](https://github.com/angular/angular/issues/13708)
* **router:** improve robustness ([#14602](https://github.com/angular/angular/issues/14602)) ([2a12346](https://github.com/angular/angular/commit/2a12346))
### Reverts
* fix(router): do not finish bootstrap until all the routes are resolved ([#14327](https://github.com/angular/angular/issues/14327)) ([de36f8a](https://github.com/angular/angular/commit/de36f8a)), closes [#14681](https://github.com/angular/angular/issues/14681) [#14588](https://github.com/angular/angular/issues/14588)
<a name="2.4.8"></a>
## [2.4.8](https://github.com/angular/angular/compare/2.4.7...2.4.8) (2017-02-18)

View File

@ -206,47 +206,38 @@ enum Endian {
Big,
}
function utf8Encode(str: string): string {
let encoded: string = '';
export function utf8Encode(str: string): string {
let encoded = '';
for (let index = 0; index < str.length; index++) {
const codePoint = decodeSurrogatePairs(str, index);
let codePoint = str.charCodeAt(index);
// decode surrogate
// see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > (index + 1)) {
const low = str.charCodeAt(index + 1);
if (low >= 0xdc00 && low <= 0xdfff) {
index++;
codePoint = ((codePoint - 0xd800) << 10) + low - 0xdc00 + 0x10000;
}
}
if (codePoint <= 0x7f) {
encoded += String.fromCharCode(codePoint);
} else if (codePoint <= 0x7ff) {
encoded += String.fromCharCode(0xc0 | codePoint >>> 6, 0x80 | codePoint & 0x3f);
encoded += String.fromCharCode(((codePoint >> 6) & 0x1F) | 0xc0, (codePoint & 0x3f) | 0x80);
} else if (codePoint <= 0xffff) {
encoded += String.fromCharCode(
0xe0 | codePoint >>> 12, 0x80 | codePoint >>> 6 & 0x3f, 0x80 | codePoint & 0x3f);
(codePoint >> 12) | 0xe0, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);
} else if (codePoint <= 0x1fffff) {
encoded += String.fromCharCode(
0xf0 | codePoint >>> 18, 0x80 | codePoint >>> 12 & 0x3f, 0x80 | codePoint >>> 6 & 0x3f,
0x80 | codePoint & 0x3f);
((codePoint >> 18) & 0x07) | 0xf0, ((codePoint >> 12) & 0x3f) | 0x80,
((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);
}
}
return encoded;
}
// see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
function decodeSurrogatePairs(str: string, index: number): number {
if (index < 0 || index >= str.length) {
throw new Error(`index=${index} is out of range in "${str}"`);
}
const high = str.charCodeAt(index);
if (high >= 0xd800 && high <= 0xdfff && str.length > index + 1) {
const low = byteAt(str, index + 1);
if (low >= 0xdc00 && low <= 0xdfff) {
return (high - 0xd800) * 0x400 + low - 0xdc00 + 0x10000;
}
}
return high;
}
function add32(a: number, b: number): number {
return add32to64(a, b)[1];
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {computeMsgId, sha1} from '../../src/i18n/digest';
import {computeMsgId, sha1, utf8Encode} from '../../src/i18n/digest';
export function main(): void {
describe('digest', () => {
@ -100,7 +100,46 @@ export function main(): void {
}
expect(computeMsgId(result, '')).toEqual('2122606631351252558');
});
});
describe('utf8encode', () => {
// tests from https://github.com/mathiasbynens/wtf-8
it('should encode to utf8', () => {
const tests = [
['abc', 'abc'],
// // 1-byte
['\0', '\0'],
// // 2-byte
['\u0080', '\xc2\x80'],
['\u05ca', '\xd7\x8a'],
['\u07ff', '\xdf\xbf'],
// // 3-byte
['\u0800', '\xe0\xa0\x80'],
['\u2c3c', '\xe2\xb0\xbc'],
['\uffff', '\xef\xbf\xbf'],
// //4-byte
['\uD800\uDC00', '\xF0\x90\x80\x80'],
['\uD834\uDF06', '\xF0\x9D\x8C\x86'],
['\uDBFF\uDFFF', '\xF4\x8F\xBF\xBF'],
// unmatched surrogate halves
// high surrogates: 0xD800 to 0xDBFF
['\uD800', '\xED\xA0\x80'],
['\uD800\uD800', '\xED\xA0\x80\xED\xA0\x80'],
['\uD800A', '\xED\xA0\x80A'],
['\uD800\uD834\uDF06\uD800', '\xED\xA0\x80\xF0\x9D\x8C\x86\xED\xA0\x80'],
['\uD9AF', '\xED\xA6\xAF'],
['\uDBFF', '\xED\xAF\xBF'],
// low surrogates: 0xDC00 to 0xDFFF
['\uDC00', '\xED\xB0\x80'],
['\uDC00\uDC00', '\xED\xB0\x80\xED\xB0\x80'],
['\uDC00A', '\xED\xB0\x80A'],
['\uDC00\uD834\uDF06\uDC00', '\xED\xB0\x80\xF0\x9D\x8C\x86\xED\xB0\x80'],
['\uDEEE', '\xED\xBB\xAE'],
['\uDFFF', '\xED\xBF\xBF'],
];
tests.forEach(
([input, output]: [string, string]) => { expect(utf8Encode(input)).toEqual(output); });
});
});
});
}

View File

@ -66,9 +66,11 @@ export interface RequestArgs extends RequestOptionsArgs { url: string; }
*
* @experimental
*/
export type ResponseOptionsArgs = {
body?: string | Object | FormData | ArrayBuffer | Blob; status?: number; statusText?: string;
export interface ResponseOptionsArgs {
body?: string|Object|FormData|ArrayBuffer|Blob;
status?: number;
statusText?: string;
headers?: Headers;
type?: ResponseType;
url?: string;
};
}

View File

@ -12,7 +12,6 @@ import {APP_INITIALIZER, NgZone, OpaqueToken} from '@angular/core';
import {WebWorkerPlatformLocation} from './platform_location';
/**
* Those providers should be added when the router is used in a worker context in addition to the
* {@link ROUTER_PROVIDERS} and after them.

View File

@ -278,6 +278,7 @@ type NavigationParams = {
source: NavigationSource,
};
/**
* @internal
*/
@ -290,7 +291,6 @@ function defaultRouterHook(snapshot: RouterStateSnapshot): Observable<void> {
return of (null);
}
/**
* Does not detach any subtrees. Reuses routes as long as their route config is the same.
*/
@ -340,6 +340,7 @@ export class Router {
navigated: boolean = false;
/**
* Extracts and merges URLs. Used for Angular 1 to Angular 2 migrations.
* Used by RouterModule. This allows us to
* pause the navigation either before preactivation or after it.
* @internal
@ -350,7 +351,7 @@ export class Router {
};
/**
* Extracts and merges URLs. Used for Angular 1 to Angular 2 migrations.
* Extracts and merges URLs. Used for AngularJS to Angular migrations.
*/
urlHandlingStrategy: UrlHandlingStrategy = new DefaultUrlHandlingStrategy();

View File

@ -44,10 +44,13 @@ export class RouterConfigLoader {
if (typeof loadChildren === 'string') {
return fromPromise(this.loader.load(loadChildren));
} else {
const offlineMode = this.compiler instanceof Compiler;
return mergeMap.call(
wrapIntoObservable(loadChildren()),
(t: any) => offlineMode ? of (<any>t) : fromPromise(this.compiler.compileModuleAsync(t)));
return mergeMap.call(wrapIntoObservable(loadChildren()), (t: NgModuleFactory<any>| any) => {
if (t instanceof NgModuleFactory) {
return of (t);
} else {
return fromPromise(this.compiler.compileModuleAsync(t));
}
});
}
}
}

View File

@ -112,7 +112,7 @@ export function routerNgProbeToken() {
* In addition, we often want to split applications into multiple bundles and load them on demand.
* Doing this transparently is not trivial.
*
* The Angular router solves these problems. Using the router, you can declaratively specify
* The Angular 2 router solves these problems. Using the router, you can declaratively specify
* application states, manage state transitions while taking care of the URL, and load bundles on
* demand.
*
@ -210,6 +210,32 @@ export function provideRoutes(routes: Routes): any {
];
}
/**
* @whatItDoes Represents an option to configure when the initial navigation is performed.
*
* @description
* * 'enabled' - the initial navigation starts before the root component is created.
* The bootstrap is blocked until the initial navigation is complete.
* * 'disabled' - the initial navigation is not performed. The location listener is set up before
* the root component gets created.
* * 'legacy_enabled'- the initial navigation starts after the root component has been created.
* The bootstrap is not blocked until the initial navigation is complete. @deprecated
* * 'legacy_disabled'- the initial navigation is not performed. The location listener is set up
* after @deprecated
* the root component gets created.
* * `true` - same as 'legacy_enabled'. @deprecated
* * `false` - same as 'legacy_disabled'. @deprecated
*
* The 'enabled' option should be used for applications unless there is a reason to have
* more control over when the router starts its initial navigation due to some complex
* initialization logic. In this case, 'disabled' should be used.
*
* The 'legacy_enabled' and 'legacy_disabled' should not be used for new applications.
*
* @experimental
*/
export type InitialNavigation =
boolean | 'enabled' | 'disabled' | 'legacy_enabled' | 'legacy_disabled';
/**
* @whatItDoes Represents options to configure the router.
@ -230,7 +256,7 @@ export interface ExtraOptions {
/**
* Disables the initial navigation.
*/
initialNavigation?: boolean;
initialNavigation?: InitialNavigation;
/**
* A custom error handler.
@ -293,7 +319,7 @@ export function rootRoute(router: Router): ActivatedRoute {
*/
@Injectable()
export class RouterInitializer {
private initNavigation: boolean;
private initNavigation: boolean = false;
private resultOfPreactivationDone = new Subject<void>();
constructor(private injector: Injector) {}
@ -306,9 +332,14 @@ export class RouterInitializer {
const router = this.injector.get(Router);
const opts = this.injector.get(ROUTER_CONFIGURATION);
if (opts.initialNavigation === false) {
if (this.isLegacyDisabled(opts) || this.isLegacyEnabled(opts)) {
resolve(true);
} else if (opts.initialNavigation === 'disabled') {
router.setUpLocationChangeListener();
} else {
resolve(true);
} else if (opts.initialNavigation === 'enabled') {
router.hooks.afterPreactivation = () => {
// only the initial navigation should be delayed
if (!this.initNavigation) {
@ -322,6 +353,9 @@ export class RouterInitializer {
}
};
router.initialNavigation();
} else {
throw new Error(`Invalid initialNavigation options: '${opts.initialNavigation}'`);
}
return res;
@ -329,20 +363,35 @@ export class RouterInitializer {
}
bootstrapListener(bootstrappedComponentRef: ComponentRef<any>): void {
const opts = this.injector.get(ROUTER_CONFIGURATION);
const preloader = this.injector.get(RouterPreloader);
const router = this.injector.get(Router);
const ref = this.injector.get(ApplicationRef);
if (bootstrappedComponentRef !== ref.components[0]) {
return;
}
const preloader = this.injector.get(RouterPreloader);
if (this.isLegacyEnabled(opts)) {
router.initialNavigation();
} else if (this.isLegacyDisabled(opts)) {
router.setUpLocationChangeListener();
}
preloader.setUpPreloading();
const router = this.injector.get(Router);
router.resetRootComponentType(ref.componentTypes[0]);
this.resultOfPreactivationDone.next(null);
this.resultOfPreactivationDone.complete();
}
private isLegacyEnabled(opts: ExtraOptions): boolean {
return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true ||
opts.initialNavigation === undefined;
}
private isLegacyDisabled(opts: ExtraOptions): boolean {
return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false;
}
}
export function getAppInitializer(r: RouterInitializer) {

View File

@ -8,25 +8,26 @@
import {APP_BASE_HREF} from '@angular/common';
import {ApplicationRef, CUSTOM_ELEMENTS_SCHEMA, Component, NgModule, destroyPlatform} from '@angular/core';
import {inject} from '@angular/core/testing';
import {BrowserModule, DOCUMENT} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {Resolve, Router, RouterModule} from '@angular/router';
import {NavigationEnd, Resolve, Router, RouterModule} from '@angular/router';
import {getDOM} from '../src/private_import_platform-browser';
describe('bootstrap', () => {
let log: any[] = [];
let testProviders: any[] = null;
@Component({selector: 'test-app', template: 'root <router-outlet></router-outlet>'})
class RootCmp {
constructor() { log.push('RootCmp'); }
}
@Component({selector: 'test-app2', template: 'root <router-outlet></router-outlet>'})
class SecondRootCmp {
}
@Component({selector: 'test', template: 'test'})
class TestCmp {
}
class TestResolver implements Resolve<any> {
resolve() {
let resolve: any = null;
@ -36,38 +37,154 @@ describe('bootstrap', () => {
}
}
let testProviders: any[] = null;
beforeEach(() => {
beforeEach(inject([DOCUMENT], (doc: any) => {
destroyPlatform();
const fakeDoc = getDOM().createHtmlDocument();
const el1 = getDOM().createElement('test-app', fakeDoc);
const el2 = getDOM().createElement('test-app2', fakeDoc);
getDOM().appendChild(fakeDoc.body, el1);
getDOM().appendChild(fakeDoc.body, el2);
testProviders =
[{provide: DOCUMENT, useValue: fakeDoc}, {provide: APP_BASE_HREF, useValue: ''}];
});
it('should wait for resolvers to complete', (done) => {
const el1 = getDOM().createElement('test-app', doc);
const el2 = getDOM().createElement('test-app2', doc);
getDOM().appendChild(doc.body, el1);
getDOM().appendChild(doc.body, el2);
log = [];
testProviders = [{provide: APP_BASE_HREF, useValue: ''}];
}));
afterEach(inject([DOCUMENT], (doc: any) => {
const oldRoots = getDOM().querySelectorAll(doc, 'test-app,test-app2');
for (let i = 0; i < oldRoots.length; i++) {
getDOM().remove(oldRoots[i]);
}
}));
it('should wait for resolvers to complete when initialNavigation = enabled', (done) => {
@Component({selector: 'test', template: 'test'})
class TestCmpEnabled {
}
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(
[{path: '**', component: TestCmp, resolve: {test: TestResolver}}], {useHash: true})
BrowserModule, RouterModule.forRoot(
[{path: '**', component: TestCmpEnabled, resolve: {test: TestResolver}}],
{useHash: true, initialNavigation: 'enabled'})
],
declarations: [SecondRootCmp, RootCmp, TestCmp],
declarations: [RootCmp, TestCmpEnabled],
bootstrap: [RootCmp],
providers: [...testProviders, TestResolver],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
class TestModule {
constructor(router: Router) {
log.push('TestModule');
router.events.subscribe(e => log.push(e.constructor.name));
}
}
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
const router = res.injector.get(Router);
const data = router.routerState.snapshot.root.firstChild.data;
expect(data['test']).toEqual('test-data');
expect(log).toEqual(
['TestModule', 'NavigationStart', 'RoutesRecognized', 'RootCmp', 'NavigationEnd']);
done();
});
});
it('should NOT wait for resolvers to complete when initialNavigation = legacy_enabled',
(done) => {
@Component({selector: 'test', template: 'test'})
class TestCmpLegacyEnabled {
}
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(
[{path: '**', component: TestCmpLegacyEnabled, resolve: {test: TestResolver}}],
{useHash: true, initialNavigation: 'legacy_enabled'})
],
declarations: [RootCmp, TestCmpLegacyEnabled],
bootstrap: [RootCmp],
providers: [...testProviders, TestResolver],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
class TestModule {
constructor(router: Router) {
log.push('TestModule');
router.events.subscribe(e => log.push(e.constructor.name));
}
}
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
const router = res.injector.get(Router);
expect(router.routerState.snapshot.root.firstChild).toBeNull();
// NavigationEnd has not been emitted yet because bootstrap returned too early
expect(log).toEqual(['TestModule', 'RootCmp', 'NavigationStart', 'RoutesRecognized']);
router.events.subscribe((e: any) => {
if (e instanceof NavigationEnd) {
done();
}
});
});
});
it('should not run navigation when initialNavigation = disabled', (done) => {
@Component({selector: 'test', template: 'test'})
class TestCmpDiabled {
}
@NgModule({
imports: [
BrowserModule, RouterModule.forRoot(
[{path: '**', component: TestCmpDiabled, resolve: {test: TestResolver}}],
{useHash: true, initialNavigation: 'disabled'})
],
declarations: [RootCmp, TestCmpDiabled],
bootstrap: [RootCmp],
providers: [...testProviders, TestResolver],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
class TestModule {
constructor(router: Router) {
log.push('TestModule');
router.events.subscribe(e => log.push(e.constructor.name));
}
}
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
const router = res.injector.get(Router);
expect(log).toEqual(['TestModule', 'RootCmp']);
done();
});
});
it('should not run navigation when initialNavigation = legacy_disabled', (done) => {
@Component({selector: 'test', template: 'test'})
class TestCmpLegacyDisabled {
}
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(
[{path: '**', component: TestCmpLegacyDisabled, resolve: {test: TestResolver}}],
{useHash: true, initialNavigation: 'legacy_disabled'})
],
declarations: [RootCmp, TestCmpLegacyDisabled],
bootstrap: [RootCmp],
providers: [...testProviders, TestResolver],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
class TestModule {
constructor(router: Router) {
log.push('TestModule');
router.events.subscribe(e => log.push(e.constructor.name));
}
}
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
const router = res.injector.get(Router);
expect(log).toEqual(['TestModule', 'RootCmp']);
done();
});
});

View File

@ -5,14 +5,14 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {APP_BOOTSTRAP_LISTENER, ComponentRef, OpaqueToken} from '@angular/core';
import {Router} from '@angular/router';
import {UpgradeModule} from '@angular/upgrade/static';
/**
* @whatItDoes Creates an initializer that in addition to setting up the Angular
* @whatItDoes Creates an initializer that in addition to setting up the Angular 2
* router sets up the ngRoute integration.
*
* @howToUse
@ -72,4 +72,4 @@ export function setUpLocationSync(ngUpgrade: UpgradeModule) {
url.href = next;
router.navigateByUrl(url.pathname);
});
}
}

View File

@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "2.4.8",
"version": "2.4.10",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular 2 - a web framework for modern web apps",

View File

@ -191,14 +191,14 @@ export declare class ResponseOptions {
}
/** @experimental */
export declare type ResponseOptionsArgs = {
export interface ResponseOptionsArgs {
body?: string | Object | FormData | ArrayBuffer | Blob;
headers?: Headers;
status?: number;
statusText?: string;
headers?: Headers;
type?: ResponseType;
url?: string;
};
}
/** @experimental */
export declare enum ResponseType {

View File

@ -76,7 +76,7 @@ export declare type Event = NavigationStart | NavigationEnd | NavigationCancel |
export interface ExtraOptions {
enableTracing?: boolean;
errorHandler?: ErrorHandler;
initialNavigation?: boolean;
initialNavigation?: InitialNavigation;
preloadingStrategy?: any;
useHash?: boolean;
}