fix(ngUpgrade): make AoT ngUpgrade work with the testability API and resumeBootstrap() (#12910)
This commit is contained in:
parent
d6ba092a27
commit
42198cd7d5
|
@ -13,6 +13,9 @@ export const $INJECTOR = '$injector';
|
||||||
export const $PARSE = '$parse';
|
export const $PARSE = '$parse';
|
||||||
export const $ROOT_SCOPE = '$rootScope';
|
export const $ROOT_SCOPE = '$rootScope';
|
||||||
export const $SCOPE = '$scope';
|
export const $SCOPE = '$scope';
|
||||||
|
export const $PROVIDE = '$provide';
|
||||||
|
export const $DELEGATE = '$delegate';
|
||||||
|
export const $$TESTABILITY = '$$testability';
|
||||||
|
|
||||||
export const $COMPILE = '$compile';
|
export const $COMPILE = '$compile';
|
||||||
export const $TEMPLATE_CACHE = '$templateCache';
|
export const $TEMPLATE_CACHE = '$templateCache';
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injector, NgModule, NgZone} from '@angular/core';
|
import {Injector, NgModule, NgZone, Testability} from '@angular/core';
|
||||||
|
|
||||||
import * as angular from '../angular_js';
|
import * as angular from '../angular_js';
|
||||||
import {controllerKey} from '../util';
|
import {controllerKey} from '../util';
|
||||||
|
|
||||||
import {angular1Providers, setTempInjectorRef} from './angular1_providers';
|
import {angular1Providers, setTempInjectorRef} from './angular1_providers';
|
||||||
import {$INJECTOR, INJECTOR_KEY, UPGRADE_MODULE_NAME} from './constants';
|
import {$$TESTABILITY, $DELEGATE, $INJECTOR, $PROVIDE, $ROOT_SCOPE, INJECTOR_KEY, UPGRADE_MODULE_NAME} from './constants';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +41,37 @@ export class UpgradeModule {
|
||||||
|
|
||||||
.value(INJECTOR_KEY, this.injector)
|
.value(INJECTOR_KEY, this.injector)
|
||||||
|
|
||||||
|
.config([
|
||||||
|
$PROVIDE, $INJECTOR,
|
||||||
|
($provide: angular.IProvideService, $injector: angular.IInjectorService) => {
|
||||||
|
if ($injector.has($$TESTABILITY)) {
|
||||||
|
$provide.decorator($$TESTABILITY, [
|
||||||
|
$DELEGATE,
|
||||||
|
(testabilityDelegate: angular.ITestabilityService) => {
|
||||||
|
const originalWhenStable: Function = testabilityDelegate.whenStable;
|
||||||
|
const injector = this.injector;
|
||||||
|
// Cannot use arrow function below because we need to grab the context
|
||||||
|
const newWhenStable = function(callback: Function) {
|
||||||
|
const whenStableContext: any = this;
|
||||||
|
originalWhenStable.call(this, function() {
|
||||||
|
const ng2Testability: Testability = injector.get(Testability);
|
||||||
|
if (ng2Testability.isStable()) {
|
||||||
|
callback.apply(this, arguments);
|
||||||
|
} else {
|
||||||
|
ng2Testability.whenStable(
|
||||||
|
newWhenStable.bind(whenStableContext, callback));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
testabilityDelegate.whenStable = newWhenStable;
|
||||||
|
return testabilityDelegate;
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.run([
|
.run([
|
||||||
$INJECTOR,
|
$INJECTOR,
|
||||||
($injector: angular.IInjectorService) => {
|
($injector: angular.IInjectorService) => {
|
||||||
|
@ -59,7 +91,22 @@ export class UpgradeModule {
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
|
||||||
|
const windowAngular = (window as any /** TODO #???? */)['angular'];
|
||||||
|
windowAngular.resumeBootstrap = undefined;
|
||||||
|
|
||||||
// Bootstrap the angular 1 application inside our zone
|
// Bootstrap the angular 1 application inside our zone
|
||||||
this.ngZone.run(() => { angular.bootstrap(element, [upgradeModule.name], config); });
|
this.ngZone.run(() => { angular.bootstrap(element, [upgradeModule.name], config); });
|
||||||
|
|
||||||
|
// Patch resumeBootstrap() to run inside the ngZone
|
||||||
|
if (windowAngular.resumeBootstrap) {
|
||||||
|
const originalResumeBootstrap: () => void = windowAngular.resumeBootstrap;
|
||||||
|
const ngZone = this.ngZone;
|
||||||
|
windowAngular.resumeBootstrap = function() {
|
||||||
|
let args = arguments;
|
||||||
|
windowAngular.resumeBootstrap = originalResumeBootstrap;
|
||||||
|
ngZone.run(() => { windowAngular.resumeBootstrap.apply(this, args); });
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {NgModule, Testability, destroyPlatform} from '@angular/core';
|
import {NgModule, Testability, destroyPlatform} from '@angular/core';
|
||||||
|
import {NgZone} from '@angular/core/src/zone/ng_zone';
|
||||||
import {fakeAsync, tick} from '@angular/core/testing';
|
import {fakeAsync, tick} from '@angular/core/testing';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
|
@ -28,7 +29,11 @@ export function main() {
|
||||||
|
|
||||||
it('should handle deferred bootstrap', fakeAsync(() => {
|
it('should handle deferred bootstrap', fakeAsync(() => {
|
||||||
let applicationRunning = false;
|
let applicationRunning = false;
|
||||||
const ng1Module = angular.module('ng1', []).run(() => { applicationRunning = true; });
|
let stayedInTheZone: boolean;
|
||||||
|
const ng1Module = angular.module('ng1', []).run(() => {
|
||||||
|
applicationRunning = true;
|
||||||
|
stayedInTheZone = NgZone.isInAngularZone();
|
||||||
|
});
|
||||||
|
|
||||||
const element = html('<div></div>');
|
const element = html('<div></div>');
|
||||||
window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
|
window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
|
||||||
|
@ -40,6 +45,7 @@ export function main() {
|
||||||
expect(applicationRunning).toEqual(false);
|
expect(applicationRunning).toEqual(false);
|
||||||
tick(100);
|
tick(100);
|
||||||
expect(applicationRunning).toEqual(true);
|
expect(applicationRunning).toEqual(true);
|
||||||
|
expect(stayedInTheZone).toEqual(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should wait for ng2 testability', fakeAsync(() => {
|
it('should wait for ng2 testability', fakeAsync(() => {
|
||||||
|
|
Loading…
Reference in New Issue