Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
6b57928d35 | |||
47471ee49e | |||
b0ae464695 | |||
34403cda60 | |||
e5c9bbcbdd | |||
80fe41a88e | |||
af652a7c8b | |||
de36f8a3b9 | |||
b658fa9ea0 | |||
2a123463ac |
@ -23,9 +23,9 @@ cache:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
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.
|
# 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:
|
matrix:
|
||||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||||
- CI_MODE=js
|
- CI_MODE=js
|
||||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -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>
|
<a name="2.4.8"></a>
|
||||||
## [2.4.8](https://github.com/angular/angular/compare/2.4.7...2.4.8) (2017-02-18)
|
## [2.4.8](https://github.com/angular/angular/compare/2.4.7...2.4.8) (2017-02-18)
|
||||||
|
|
||||||
|
@ -206,47 +206,38 @@ enum Endian {
|
|||||||
Big,
|
Big,
|
||||||
}
|
}
|
||||||
|
|
||||||
function utf8Encode(str: string): string {
|
export function utf8Encode(str: string): string {
|
||||||
let encoded: string = '';
|
let encoded = '';
|
||||||
|
|
||||||
for (let index = 0; index < str.length; index++) {
|
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) {
|
if (codePoint <= 0x7f) {
|
||||||
encoded += String.fromCharCode(codePoint);
|
encoded += String.fromCharCode(codePoint);
|
||||||
} else if (codePoint <= 0x7ff) {
|
} 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) {
|
} else if (codePoint <= 0xffff) {
|
||||||
encoded += String.fromCharCode(
|
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) {
|
} else if (codePoint <= 0x1fffff) {
|
||||||
encoded += String.fromCharCode(
|
encoded += String.fromCharCode(
|
||||||
0xf0 | codePoint >>> 18, 0x80 | codePoint >>> 12 & 0x3f, 0x80 | codePoint >>> 6 & 0x3f,
|
((codePoint >> 18) & 0x07) | 0xf0, ((codePoint >> 12) & 0x3f) | 0x80,
|
||||||
0x80 | codePoint & 0x3f);
|
((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return encoded;
|
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 {
|
function add32(a: number, b: number): number {
|
||||||
return add32to64(a, b)[1];
|
return add32to64(a, b)[1];
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {
|
export function main(): void {
|
||||||
describe('digest', () => {
|
describe('digest', () => {
|
||||||
@ -100,7 +100,46 @@ export function main(): void {
|
|||||||
}
|
}
|
||||||
expect(computeMsgId(result, '')).toEqual('2122606631351252558');
|
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); });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,11 @@ export interface RequestArgs extends RequestOptionsArgs { url: string; }
|
|||||||
*
|
*
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export type ResponseOptionsArgs = {
|
export interface ResponseOptionsArgs {
|
||||||
body?: string | Object | FormData | ArrayBuffer | Blob; status?: number; statusText?: string;
|
body?: string|Object|FormData|ArrayBuffer|Blob;
|
||||||
|
status?: number;
|
||||||
|
statusText?: string;
|
||||||
headers?: Headers;
|
headers?: Headers;
|
||||||
type?: ResponseType;
|
type?: ResponseType;
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
}
|
||||||
|
@ -12,7 +12,6 @@ import {APP_INITIALIZER, NgZone, OpaqueToken} from '@angular/core';
|
|||||||
import {WebWorkerPlatformLocation} from './platform_location';
|
import {WebWorkerPlatformLocation} from './platform_location';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Those providers should be added when the router is used in a worker context in addition to the
|
* Those providers should be added when the router is used in a worker context in addition to the
|
||||||
* {@link ROUTER_PROVIDERS} and after them.
|
* {@link ROUTER_PROVIDERS} and after them.
|
||||||
|
@ -278,6 +278,7 @@ type NavigationParams = {
|
|||||||
source: NavigationSource,
|
source: NavigationSource,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -290,7 +291,6 @@ function defaultRouterHook(snapshot: RouterStateSnapshot): Observable<void> {
|
|||||||
return of (null);
|
return of (null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does not detach any subtrees. Reuses routes as long as their route config is the same.
|
* 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;
|
navigated: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Extracts and merges URLs. Used for Angular 1 to Angular 2 migrations.
|
||||||
* Used by RouterModule. This allows us to
|
* Used by RouterModule. This allows us to
|
||||||
* pause the navigation either before preactivation or after it.
|
* pause the navigation either before preactivation or after it.
|
||||||
* @internal
|
* @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();
|
urlHandlingStrategy: UrlHandlingStrategy = new DefaultUrlHandlingStrategy();
|
||||||
|
|
||||||
|
@ -44,10 +44,13 @@ export class RouterConfigLoader {
|
|||||||
if (typeof loadChildren === 'string') {
|
if (typeof loadChildren === 'string') {
|
||||||
return fromPromise(this.loader.load(loadChildren));
|
return fromPromise(this.loader.load(loadChildren));
|
||||||
} else {
|
} else {
|
||||||
const offlineMode = this.compiler instanceof Compiler;
|
return mergeMap.call(wrapIntoObservable(loadChildren()), (t: NgModuleFactory<any>| any) => {
|
||||||
return mergeMap.call(
|
if (t instanceof NgModuleFactory) {
|
||||||
wrapIntoObservable(loadChildren()),
|
return of (t);
|
||||||
(t: any) => offlineMode ? of (<any>t) : fromPromise(this.compiler.compileModuleAsync(t)));
|
} else {
|
||||||
|
return fromPromise(this.compiler.compileModuleAsync(t));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ export function routerNgProbeToken() {
|
|||||||
* In addition, we often want to split applications into multiple bundles and load them on demand.
|
* In addition, we often want to split applications into multiple bundles and load them on demand.
|
||||||
* Doing this transparently is not trivial.
|
* 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
|
* application states, manage state transitions while taking care of the URL, and load bundles on
|
||||||
* demand.
|
* 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.
|
* @whatItDoes Represents options to configure the router.
|
||||||
@ -230,7 +256,7 @@ export interface ExtraOptions {
|
|||||||
/**
|
/**
|
||||||
* Disables the initial navigation.
|
* Disables the initial navigation.
|
||||||
*/
|
*/
|
||||||
initialNavigation?: boolean;
|
initialNavigation?: InitialNavigation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom error handler.
|
* A custom error handler.
|
||||||
@ -293,7 +319,7 @@ export function rootRoute(router: Router): ActivatedRoute {
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RouterInitializer {
|
export class RouterInitializer {
|
||||||
private initNavigation: boolean;
|
private initNavigation: boolean = false;
|
||||||
private resultOfPreactivationDone = new Subject<void>();
|
private resultOfPreactivationDone = new Subject<void>();
|
||||||
|
|
||||||
constructor(private injector: Injector) {}
|
constructor(private injector: Injector) {}
|
||||||
@ -306,9 +332,14 @@ export class RouterInitializer {
|
|||||||
const router = this.injector.get(Router);
|
const router = this.injector.get(Router);
|
||||||
const opts = this.injector.get(ROUTER_CONFIGURATION);
|
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();
|
router.setUpLocationChangeListener();
|
||||||
} else {
|
resolve(true);
|
||||||
|
|
||||||
|
} else if (opts.initialNavigation === 'enabled') {
|
||||||
router.hooks.afterPreactivation = () => {
|
router.hooks.afterPreactivation = () => {
|
||||||
// only the initial navigation should be delayed
|
// only the initial navigation should be delayed
|
||||||
if (!this.initNavigation) {
|
if (!this.initNavigation) {
|
||||||
@ -322,6 +353,9 @@ export class RouterInitializer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
router.initialNavigation();
|
router.initialNavigation();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid initialNavigation options: '${opts.initialNavigation}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -329,20 +363,35 @@ export class RouterInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bootstrapListener(bootstrappedComponentRef: ComponentRef<any>): void {
|
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);
|
const ref = this.injector.get(ApplicationRef);
|
||||||
|
|
||||||
if (bootstrappedComponentRef !== ref.components[0]) {
|
if (bootstrappedComponentRef !== ref.components[0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const preloader = this.injector.get(RouterPreloader);
|
if (this.isLegacyEnabled(opts)) {
|
||||||
|
router.initialNavigation();
|
||||||
|
} else if (this.isLegacyDisabled(opts)) {
|
||||||
|
router.setUpLocationChangeListener();
|
||||||
|
}
|
||||||
|
|
||||||
preloader.setUpPreloading();
|
preloader.setUpPreloading();
|
||||||
|
|
||||||
const router = this.injector.get(Router);
|
|
||||||
router.resetRootComponentType(ref.componentTypes[0]);
|
router.resetRootComponentType(ref.componentTypes[0]);
|
||||||
|
|
||||||
this.resultOfPreactivationDone.next(null);
|
this.resultOfPreactivationDone.next(null);
|
||||||
this.resultOfPreactivationDone.complete();
|
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) {
|
export function getAppInitializer(r: RouterInitializer) {
|
||||||
|
@ -8,25 +8,26 @@
|
|||||||
|
|
||||||
import {APP_BASE_HREF} from '@angular/common';
|
import {APP_BASE_HREF} from '@angular/common';
|
||||||
import {ApplicationRef, CUSTOM_ELEMENTS_SCHEMA, Component, NgModule, destroyPlatform} from '@angular/core';
|
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 {BrowserModule, DOCUMENT} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {NavigationEnd, Resolve, Router, RouterModule} from '@angular/router';
|
||||||
import {Resolve, Router, RouterModule} from '@angular/router';
|
import {getDOM} from '../src/private_import_platform-browser';
|
||||||
|
|
||||||
|
|
||||||
describe('bootstrap', () => {
|
describe('bootstrap', () => {
|
||||||
|
let log: any[] = [];
|
||||||
|
let testProviders: any[] = null;
|
||||||
|
|
||||||
@Component({selector: 'test-app', template: 'root <router-outlet></router-outlet>'})
|
@Component({selector: 'test-app', template: 'root <router-outlet></router-outlet>'})
|
||||||
class RootCmp {
|
class RootCmp {
|
||||||
|
constructor() { log.push('RootCmp'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'test-app2', template: 'root <router-outlet></router-outlet>'})
|
@Component({selector: 'test-app2', template: 'root <router-outlet></router-outlet>'})
|
||||||
class SecondRootCmp {
|
class SecondRootCmp {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'test', template: 'test'})
|
|
||||||
class TestCmp {
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestResolver implements Resolve<any> {
|
class TestResolver implements Resolve<any> {
|
||||||
resolve() {
|
resolve() {
|
||||||
let resolve: any = null;
|
let resolve: any = null;
|
||||||
@ -36,38 +37,154 @@ describe('bootstrap', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let testProviders: any[] = null;
|
beforeEach(inject([DOCUMENT], (doc: any) => {
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
destroyPlatform();
|
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({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule, RouterModule.forRoot(
|
||||||
RouterModule.forRoot(
|
[{path: '**', component: TestCmpEnabled, resolve: {test: TestResolver}}],
|
||||||
[{path: '**', component: TestCmp, resolve: {test: TestResolver}}], {useHash: true})
|
{useHash: true, initialNavigation: 'enabled'})
|
||||||
],
|
],
|
||||||
declarations: [SecondRootCmp, RootCmp, TestCmp],
|
declarations: [RootCmp, TestCmpEnabled],
|
||||||
bootstrap: [RootCmp],
|
bootstrap: [RootCmp],
|
||||||
providers: [...testProviders, TestResolver],
|
providers: [...testProviders, TestResolver],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
})
|
})
|
||||||
class TestModule {
|
class TestModule {
|
||||||
|
constructor(router: Router) {
|
||||||
|
log.push('TestModule');
|
||||||
|
router.events.subscribe(e => log.push(e.constructor.name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
|
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
|
||||||
const router = res.injector.get(Router);
|
const router = res.injector.get(Router);
|
||||||
const data = router.routerState.snapshot.root.firstChild.data;
|
const data = router.routerState.snapshot.root.firstChild.data;
|
||||||
expect(data['test']).toEqual('test-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();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {APP_BOOTSTRAP_LISTENER, ComponentRef, OpaqueToken} from '@angular/core';
|
import {APP_BOOTSTRAP_LISTENER, ComponentRef, OpaqueToken} from '@angular/core';
|
||||||
import {Router} from '@angular/router';
|
import {Router} from '@angular/router';
|
||||||
import {UpgradeModule} from '@angular/upgrade/static';
|
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.
|
* router sets up the ngRoute integration.
|
||||||
*
|
*
|
||||||
* @howToUse
|
* @howToUse
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "angular-srcs",
|
"name": "angular-srcs",
|
||||||
"version": "2.4.8",
|
"version": "2.4.10",
|
||||||
"private": true,
|
"private": true,
|
||||||
"branchPattern": "2.0.*",
|
"branchPattern": "2.0.*",
|
||||||
"description": "Angular 2 - a web framework for modern web apps",
|
"description": "Angular 2 - a web framework for modern web apps",
|
||||||
|
6
tools/public_api_guard/http/index.d.ts
vendored
6
tools/public_api_guard/http/index.d.ts
vendored
@ -191,14 +191,14 @@ export declare class ResponseOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare type ResponseOptionsArgs = {
|
export interface ResponseOptionsArgs {
|
||||||
body?: string | Object | FormData | ArrayBuffer | Blob;
|
body?: string | Object | FormData | ArrayBuffer | Blob;
|
||||||
|
headers?: Headers;
|
||||||
status?: number;
|
status?: number;
|
||||||
statusText?: string;
|
statusText?: string;
|
||||||
headers?: Headers;
|
|
||||||
type?: ResponseType;
|
type?: ResponseType;
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** @experimental */
|
/** @experimental */
|
||||||
export declare enum ResponseType {
|
export declare enum ResponseType {
|
||||||
|
2
tools/public_api_guard/router/index.d.ts
vendored
2
tools/public_api_guard/router/index.d.ts
vendored
@ -76,7 +76,7 @@ export declare type Event = NavigationStart | NavigationEnd | NavigationCancel |
|
|||||||
export interface ExtraOptions {
|
export interface ExtraOptions {
|
||||||
enableTracing?: boolean;
|
enableTracing?: boolean;
|
||||||
errorHandler?: ErrorHandler;
|
errorHandler?: ErrorHandler;
|
||||||
initialNavigation?: boolean;
|
initialNavigation?: InitialNavigation;
|
||||||
preloadingStrategy?: any;
|
preloadingStrategy?: any;
|
||||||
useHash?: boolean;
|
useHash?: boolean;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user