From b22eddf1cb1b958ddf9c3a64236fc3f3c80b9b0b Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Tue, 10 Nov 2015 15:42:22 -0800 Subject: [PATCH] fix(core): Run component disposal before destroyRootHostView() to avoid crash if change detection is triggered. Closes #5226 --- .../core/linker/dynamic_component_loader.ts | 2 +- .../angular2/test/platform/bootstrap_spec.ts | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/modules/angular2/src/core/linker/dynamic_component_loader.ts b/modules/angular2/src/core/linker/dynamic_component_loader.ts index e9bf175abe..7613835930 100644 --- a/modules/angular2/src/core/linker/dynamic_component_loader.ts +++ b/modules/angular2/src/core/linker/dynamic_component_loader.ts @@ -249,10 +249,10 @@ export class DynamicComponentLoader_ extends DynamicComponentLoader { var component = this._viewManager.getComponent(newLocation); var dispose = () => { - this._viewManager.destroyRootHostView(hostViewRef); if (isPresent(onDispose)) { onDispose(); } + this._viewManager.destroyRootHostView(hostViewRef); }; return new ComponentRef_(newLocation, component, type, injector, dispose); }); diff --git a/modules/angular2/test/platform/bootstrap_spec.ts b/modules/angular2/test/platform/bootstrap_spec.ts index 09b01f2401..f751d15624 100644 --- a/modules/angular2/test/platform/bootstrap_spec.ts +++ b/modules/angular2/test/platform/bootstrap_spec.ts @@ -13,7 +13,7 @@ import { import {IS_DART, isPresent, stringify} from 'angular2/src/facade/lang'; import {bootstrap} from 'angular2/platform/browser'; import {ApplicationRef} from 'angular2/src/core/application_ref'; -import {Component, Directive, View, platform} from 'angular2/core'; +import {Component, Directive, View, OnDestroy, platform} from 'angular2/core'; import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from 'angular2/platform/browser'; import {DOM} from 'angular2/src/core/dom/dom_adapter'; import {DOCUMENT} from 'angular2/render'; @@ -67,6 +67,15 @@ class HelloRootMissingTemplate { class HelloRootDirectiveIsNotCmp { } +@Component({selector: 'hello-app'}) +@View({template: ''}) +class HelloOnDestroyTickCmp implements OnDestroy { + appRef: ApplicationRef; + constructor(@Inject(ApplicationRef) appRef) { this.appRef = appRef; } + + onDestroy(): void { this.appRef.tick(); } +} + class _ArrayLogger { res: any[] = []; log(s: any): void { this.res.push(s); } @@ -163,6 +172,15 @@ export function main() { }); })); + it('should not crash if change detection is invoked when the root component is disposed', + inject([AsyncTestCompleter], (async) => { + bootstrap(HelloOnDestroyTickCmp, testProviders) + .then((ref) => { + expect(() => ref.dispose()).not.toThrow(); + async.done(); + }); + })); + it('should unregister change detectors when components are disposed', inject([AsyncTestCompleter], (async) => { var app = platform(BROWSER_PROVIDERS).application([BROWSER_APP_PROVIDERS, testProviders]);