diff --git a/modules/@angular/common/test/forms-deprecated/integration_spec.ts b/modules/@angular/common/test/forms-deprecated/integration_spec.ts index 28c285635f..dee202fce2 100644 --- a/modules/@angular/common/test/forms-deprecated/integration_spec.ts +++ b/modules/@angular/common/test/forms-deprecated/integration_spec.ts @@ -129,55 +129,51 @@ export function main() { }))); it('should mark NgForm as submitted on submit event', - inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => { - var t = `
+ fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + var t = `
{{data}}
`; - var fixture: ComponentFixture; + var fixture: ComponentFixture; - tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { - fixture = root; - }); - tick(); + tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { fixture = root; }); + tick(); - fixture.debugElement.componentInstance.data = false; + fixture.debugElement.componentInstance.data = false; - tick(); + tick(); - var form = fixture.debugElement.query(By.css('form')); - dispatchEvent(form.nativeElement, 'submit'); + var form = fixture.debugElement.query(By.css('form')); + dispatchEvent(form.nativeElement, 'submit'); - tick(); - expect(fixture.debugElement.componentInstance.data).toEqual(true); - }))); + tick(); + expect(fixture.debugElement.componentInstance.data).toEqual(true); + }))); it('should mark NgFormModel as submitted on submit event', - inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => { - var t = `
+ fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + var t = `
{{data}}
`; - var fixture: ComponentFixture; + var fixture: ComponentFixture; - tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { - fixture = root; - }); - tick(); + tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { fixture = root; }); + tick(); - fixture.debugElement.componentInstance.form = new ControlGroup({}); - fixture.debugElement.componentInstance.data = false; + fixture.debugElement.componentInstance.form = new ControlGroup({}); + fixture.debugElement.componentInstance.data = false; - tick(); + tick(); - var form = fixture.debugElement.query(By.css('form')); - dispatchEvent(form.nativeElement, 'submit'); + var form = fixture.debugElement.query(By.css('form')); + dispatchEvent(form.nativeElement, 'submit'); - tick(); - expect(fixture.debugElement.componentInstance.data).toEqual(true); - }))); + tick(); + expect(fixture.debugElement.componentInstance.data).toEqual(true); + }))); it('should work with single controls', inject( diff --git a/modules/@angular/compiler/test/runtime_compiler_spec.ts b/modules/@angular/compiler/test/runtime_compiler_spec.ts index 3ffefafa62..c48ef70861 100644 --- a/modules/@angular/compiler/test/runtime_compiler_spec.ts +++ b/modules/@angular/compiler/test/runtime_compiler_spec.ts @@ -39,7 +39,7 @@ export function main() { beforeEach( () => { TestBed.configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); }); - beforeEach(inject( + beforeEach(fakeAsync(inject( [Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector], (_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR, _dirResolver: MockDirectiveResolver, _injector: Injector) => { @@ -48,7 +48,7 @@ export function main() { xhr = _xhr; dirResolver = _dirResolver; injector = _injector; - })); + }))); describe('clearCacheFor', () => { it('should support changing the content of a template referenced via templateUrl', diff --git a/modules/@angular/core/src/application_ref.ts b/modules/@angular/core/src/application_ref.ts index 1a4220d1b2..2db0c4dab3 100644 --- a/modules/@angular/core/src/application_ref.ts +++ b/modules/@angular/core/src/application_ref.ts @@ -137,11 +137,20 @@ export function assertPlatform(requiredToken: any): PlatformRef { /** * Dispose the existing platform. * - * @experimental APIs related to application bootstrap are currently under review. + * @deprecated Use `destroyPlatform` instead */ export function disposePlatform(): void { - if (isPresent(_platform) && !_platform.disposed) { - _platform.dispose(); + destroyPlatform(); +} + +/** + * Destroy the existing platform. + * + * @experimental APIs related to application bootstrap are currently under review. + */ +export function destroyPlatform(): void { + if (isPresent(_platform) && !_platform.destroyed) { + _platform.destroy(); } } @@ -238,9 +247,15 @@ export abstract class PlatformRef { /** * Register a listener to be called when the platform is disposed. + * @deprecated Use `OnDestroy` instead */ abstract registerDisposeListener(dispose: () => void): void; + /** + * Register a listener to be called when the platform is disposed. + */ + abstract onDestroy(callback: () => void): void; + /** * Retrieve the platform {@link Injector}, which is the parent injector for * every Angular application on the page and provides singleton providers. @@ -249,10 +264,20 @@ export abstract class PlatformRef { /** * Destroy the Angular platform and all Angular applications on the page. + * @deprecated Use `destroy` instead */ abstract dispose(): void; + /** + * Destroy the Angular platform and all Angular applications on the page. + */ + abstract destroy(): void; + + /** + * @deprecated Use `destroyd` instead + */ get disposed(): boolean { throw unimplemented(); } + get destroyed(): boolean { throw unimplemented(); } } function _callAndReportToExceptionHandler( @@ -277,29 +302,41 @@ function _callAndReportToExceptionHandler( @Injectable() export class PlatformRef_ extends PlatformRef { - /** @internal */ - _applications: ApplicationRef[] = []; - /** @internal */ - _disposeListeners: Function[] = []; + private _modules: NgModuleRef[] = []; + private _destroyListeners: Function[] = []; - private _disposed: boolean = false; + private _destroyed: boolean = false; constructor(private _injector: Injector) { super(); } - registerDisposeListener(dispose: () => void): void { this._disposeListeners.push(dispose); } + /** + * @deprecated + */ + registerDisposeListener(dispose: () => void): void { this.onDestroy(dispose); } + + onDestroy(callback: () => void): void { this._destroyListeners.push(callback); } get injector(): Injector { return this._injector; } - get disposed() { return this._disposed; } + /** + * @deprecated + */ + get disposed() { return this.destroyed; } + get destroyed() { return this._destroyed; } - dispose(): void { - ListWrapper.clone(this._applications).forEach((app) => app.dispose()); - this._disposeListeners.forEach((dispose) => dispose()); - this._disposed = true; + destroy() { + if (this._destroyed) { + throw new BaseException('The platform is already destroyed!'); + } + ListWrapper.clone(this._modules).forEach((app) => app.destroy()); + this._destroyListeners.forEach((dispose) => dispose()); + this._destroyed = true; } - /** @internal */ - _applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); } + /** + * @deprecated + */ + dispose(): void { this.destroy(); } bootstrapModuleFactory(moduleFactory: NgModuleFactory): Promise> { // Note: We need to create the NgZone _before_ we instantiate the module, @@ -317,6 +354,7 @@ export class PlatformRef_ extends PlatformRef { if (!exceptionHandler) { throw new Error('No ExceptionHandler. Is platform module (BrowserModule) included?'); } + moduleRef.onDestroy(() => ListWrapper.remove(this._modules, moduleRef)); ObservableWrapper.subscribe(ngZone.onError, (error: NgZoneError) => { exceptionHandler.call(error.error, error.stackTrace); }); @@ -367,6 +405,8 @@ export abstract class ApplicationRef { /** * Register a listener to be called when the application is disposed. + * + * @deprecated Use `ngOnDestroy` lifecycle hook or {@link NgModuleRef}.onDestroy. */ abstract registerDisposeListener(dispose: () => void): void; @@ -408,6 +448,9 @@ export abstract class ApplicationRef { /** * Dispose of this application and all of its components. + * + * @deprecated Destroy the module that was created during bootstrap instead by calling + * {@link NgModuleRef}.destroy. */ abstract dispose(): void; @@ -434,27 +477,23 @@ export class ApplicationRef_ extends ApplicationRef { /** @internal */ static _tickScope: WtfScopeFn = wtfCreateScope('ApplicationRef#tick()'); - /** @internal */ private _bootstrapListeners: Function[] = []; - /** @internal */ + /** + * @deprecated + */ private _disposeListeners: Function[] = []; - /** @internal */ private _rootComponents: ComponentRef[] = []; - /** @internal */ private _rootComponentTypes: Type[] = []; - /** @internal */ private _changeDetectorRefs: ChangeDetectorRef[] = []; - /** @internal */ private _runningTick: boolean = false; - /** @internal */ private _enforceNoNewChanges: boolean = false; /** @internal */ _asyncInitDonePromise: PromiseCompleter = PromiseWrapper.completer(); constructor( - private _platform: PlatformRef_, private _zone: NgZone, private _console: Console, - private _injector: Injector, private _exceptionHandler: ExceptionHandler, + private _zone: NgZone, private _console: Console, private _injector: Injector, + private _exceptionHandler: ExceptionHandler, private _componentFactoryResolver: ComponentFactoryResolver, @Optional() private _testabilityRegistry: TestabilityRegistry, @Optional() private _testability: Testability) { @@ -468,6 +507,9 @@ export class ApplicationRef_ extends ApplicationRef { this._bootstrapListeners.push(listener); } + /** + * @deprecated + */ registerDisposeListener(dispose: () => void): void { this._disposeListeners.push(dispose); } registerChangeDetector(changeDetector: ChangeDetectorRef): void { @@ -556,12 +598,16 @@ export class ApplicationRef_ extends ApplicationRef { } } - dispose(): void { + ngOnDestroy() { // TODO(alxhub): Dispose of the NgZone. ListWrapper.clone(this._rootComponents).forEach((ref) => ref.destroy()); this._disposeListeners.forEach((dispose) => dispose()); - this._platform._applicationDisposed(this); } + /** + * @deprecated + */ + dispose(): void { this.ngOnDestroy(); } + get componentTypes(): Type[] { return this._rootComponentTypes; } } diff --git a/modules/@angular/core/test/linker/change_detection_integration_spec.ts b/modules/@angular/core/test/linker/change_detection_integration_spec.ts index af4ad1af9e..f8742fb1ba 100644 --- a/modules/@angular/core/test/linker/change_detection_integration_spec.ts +++ b/modules/@angular/core/test/linker/change_detection_integration_spec.ts @@ -85,7 +85,7 @@ export function main() { }); }); - beforeEach(inject( + beforeEach(fakeAsync(inject( [TestComponentBuilder, ElementSchemaRegistry, RenderLog, DirectiveLog], (_tcb: TestComponentBuilder, _elSchema: MockSchemaRegistry, _renderLog: RenderLog, _directiveLog: DirectiveLog) => { @@ -94,7 +94,7 @@ export function main() { renderLog = _renderLog; directiveLog = _directiveLog; elSchema.existingProperties['someProp'] = true; - })); + }))); describe('expressions', () => { diff --git a/modules/@angular/core/test/linker/view_injector_integration_spec.ts b/modules/@angular/core/test/linker/view_injector_integration_spec.ts index 7c767a36ae..073a2c5bfb 100644 --- a/modules/@angular/core/test/linker/view_injector_integration_spec.ts +++ b/modules/@angular/core/test/linker/view_injector_integration_spec.ts @@ -268,7 +268,8 @@ export function main() { beforeEachProviders(() => [{provide: 'appService', useValue: 'appService'}]); - beforeEach(inject([TestComponentBuilder], (_tcb: TestComponentBuilder) => { tcb = _tcb; })); + beforeEach( + fakeAsync(inject([TestComponentBuilder], (_tcb: TestComponentBuilder) => { tcb = _tcb; }))); describe('injection', () => { it('should instantiate directives that have no dependencies', fakeAsync(() => { diff --git a/modules/@angular/forms/test/reactive_integration_spec.ts b/modules/@angular/forms/test/reactive_integration_spec.ts index 9d7048b678..4b63a473a6 100644 --- a/modules/@angular/forms/test/reactive_integration_spec.ts +++ b/modules/@angular/forms/test/reactive_integration_spec.ts @@ -116,30 +116,28 @@ export function main() { }))); it('should mark formGroup as submitted on submit event', - inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => { - const t = `
+ fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + const t = `
{{data}}
`; - var fixture: ComponentFixture; + var fixture: ComponentFixture; - tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { - fixture = root; - }); - tick(); + tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { fixture = root; }); + tick(); - fixture.debugElement.componentInstance.form = new FormGroup({}); - fixture.debugElement.componentInstance.data = false; + fixture.debugElement.componentInstance.form = new FormGroup({}); + fixture.debugElement.componentInstance.data = false; - tick(); + tick(); - var form = fixture.debugElement.query(By.css('form')); - dispatchEvent(form.nativeElement, 'submit'); + var form = fixture.debugElement.query(By.css('form')); + dispatchEvent(form.nativeElement, 'submit'); - tick(); - expect(fixture.debugElement.componentInstance.data).toEqual(true); - }))); + tick(); + expect(fixture.debugElement.componentInstance.data).toEqual(true); + }))); it('should work with single controls', inject( diff --git a/modules/@angular/forms/test/template_integration_spec.ts b/modules/@angular/forms/test/template_integration_spec.ts index 67cad045bc..a379cb6a2e 100644 --- a/modules/@angular/forms/test/template_integration_spec.ts +++ b/modules/@angular/forms/test/template_integration_spec.ts @@ -104,29 +104,27 @@ export function main() { }))); it('should mark NgForm as submitted on submit event', - inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => { - const t = `
+ fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + const t = `
{{data}}
`; - var fixture: ComponentFixture; + var fixture: ComponentFixture; - tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { - fixture = root; - }); - tick(); + tcb.overrideTemplate(MyComp8, t).createAsync(MyComp8).then((root) => { fixture = root; }); + tick(); - fixture.debugElement.componentInstance.data = false; + fixture.debugElement.componentInstance.data = false; - tick(); + tick(); - var form = fixture.debugElement.query(By.css('form')); - dispatchEvent(form.nativeElement, 'submit'); + var form = fixture.debugElement.query(By.css('form')); + dispatchEvent(form.nativeElement, 'submit'); - tick(); - expect(fixture.debugElement.componentInstance.data).toEqual(true); - }))); + tick(); + expect(fixture.debugElement.componentInstance.data).toEqual(true); + }))); it('should reset the form to empty when reset button is clicked', diff --git a/modules/@angular/router-deprecated/src/router.ts b/modules/@angular/router-deprecated/src/router.ts index 696e1f9003..fc0ce6750d 100644 --- a/modules/@angular/router-deprecated/src/router.ts +++ b/modules/@angular/router-deprecated/src/router.ts @@ -548,6 +548,11 @@ export class RootRouter extends Router { return promise; } + /** + * @internal + */ + ngOnDestroy() { this.dispose(); } + dispose(): void { if (isPresent(this._locationSub)) { ObservableWrapper.dispose(this._locationSub); diff --git a/modules/@angular/router-deprecated/src/router_providers_common.ts b/modules/@angular/router-deprecated/src/router_providers_common.ts index c99d8b63ce..03c0eb8aa7 100644 --- a/modules/@angular/router-deprecated/src/router_providers_common.ts +++ b/modules/@angular/router-deprecated/src/router_providers_common.ts @@ -23,7 +23,7 @@ export const ROUTER_PROVIDERS_COMMON: any[] = [ RouteRegistry, {provide: LocationStrategy, useClass: PathLocationStrategy}, Location, { provide: Router, useFactory: routerFactory, - deps: [RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef] + deps: [RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT] }, { provide: ROUTER_PRIMARY_COMPONENT, @@ -33,11 +33,8 @@ export const ROUTER_PROVIDERS_COMMON: any[] = [ ]; function routerFactory( - registry: RouteRegistry, location: Location, primaryComponent: Type, - appRef: ApplicationRef): RootRouter { - var rootRouter = new RootRouter(registry, location, primaryComponent); - appRef.registerDisposeListener(() => rootRouter.dispose()); - return rootRouter; + registry: RouteRegistry, location: Location, primaryComponent: Type): RootRouter { + return new RootRouter(registry, location, primaryComponent); } function routerPrimaryComponentFactory(app: ApplicationRef): Type { diff --git a/modules/@angular/router/src/common_router_providers.ts b/modules/@angular/router/src/common_router_providers.ts index cc7322372f..ba4e0068ec 100644 --- a/modules/@angular/router/src/common_router_providers.ts +++ b/modules/@angular/router/src/common_router_providers.ts @@ -36,7 +36,6 @@ export function setupRouter( const componentType = ref.componentTypes[0]; const r = new Router( componentType, resolver, urlSerializer, outletMap, location, injector, loader, config); - ref.registerDisposeListener(() => r.dispose()); if (opts.enableTracing) { r.events.subscribe(e => { diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index 634a8d801b..20d266d8cb 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -196,6 +196,11 @@ export class Router { this.config = config; } + /** + * @internal + */ + ngOnDestroy() { this.dispose(); } + /** * Disposes of the router. */ diff --git a/modules/@angular/upgrade/src/upgrade_adapter.ts b/modules/@angular/upgrade/src/upgrade_adapter.ts index fc2fc68200..df49f6c9fc 100644 --- a/modules/@angular/upgrade/src/upgrade_adapter.ts +++ b/modules/@angular/upgrade/src/upgrade_adapter.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ApplicationRef, Compiler, CompilerFactory, ComponentFactory, ComponentResolver, Injector, NgModule, NgModuleRef, NgZone, PlatformRef, Provider, ReflectiveInjector, Testability, Type, provide} from '@angular/core'; +import {Compiler, CompilerFactory, ComponentFactory, ComponentResolver, Injector, NgModule, NgModuleRef, NgZone, PlatformRef, Provider, ReflectiveInjector, Testability, Type, provide} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; @@ -299,8 +299,7 @@ export class UpgradeAdapter { config?: angular.IAngularBootstrapConfig): angular.IInjectorService { const boundCompiler: Compiler = moduleRef.injector.get(Compiler); var ng1Injector: angular.IInjectorService = null; - var applicationRef: ApplicationRef = moduleRef.injector.get(ApplicationRef); - var injector: Injector = applicationRef.injector; + var injector: Injector = moduleRef.injector; var ngZone: NgZone = injector.get(NgZone); var delayApplyExps: Function[] = []; var original$applyFn: Function; @@ -400,7 +399,7 @@ export class UpgradeAdapter { while (delayApplyExps.length) { rootScope.$apply(delayApplyExps.shift()); } - (upgrade)._bootstrapDone(applicationRef, ng1Injector); + (upgrade)._bootstrapDone(moduleRef, ng1Injector); rootScopePrototype = null; } }); @@ -583,13 +582,13 @@ export class UpgradeAdapterRef { public ng1RootScope: angular.IRootScopeService = null; public ng1Injector: angular.IInjectorService = null; - public ng2ApplicationRef: ApplicationRef = null; + public ng2ModuleRef: NgModuleRef = null; public ng2Injector: Injector = null; /* @internal */ - private _bootstrapDone(applicationRef: ApplicationRef, ng1Injector: angular.IInjectorService) { - this.ng2ApplicationRef = applicationRef; - this.ng2Injector = applicationRef.injector; + private _bootstrapDone(ngModuleRef: NgModuleRef, ng1Injector: angular.IInjectorService) { + this.ng2ModuleRef = ngModuleRef; + this.ng2Injector = ngModuleRef.injector; this.ng1Injector = ng1Injector; this.ng1RootScope = ng1Injector.get(NG1_ROOT_SCOPE); this._readyFn && this._readyFn(this); @@ -609,6 +608,6 @@ export class UpgradeAdapterRef { */ public dispose() { this.ng1Injector.get(NG1_ROOT_SCOPE).$destroy(); - this.ng2ApplicationRef.dispose(); + this.ng2ModuleRef.destroy(); } }