From 280b86ec553ec0a5bd6ca9b022c77eedbbba2640 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Wed, 17 Feb 2016 12:12:10 -0800 Subject: [PATCH] fix(change_detection): allow to destroy `OnPush` components inside of a host event. --- .../change_detection_jit_generator.ts | 2 +- .../dynamic_change_detector.ts | 4 ++- .../test/core/linker/integration_spec.ts | 34 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts index 80d1573c34..37a9dfa983 100644 --- a/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts +++ b/modules/angular2/src/core/change_detection/change_detection_jit_generator.ts @@ -174,7 +174,7 @@ export class ChangeDetectorJITGenerator { var evalRecord = this._logic.genEventBindingEvalValue(eb, r); var markPath = this._genMarkPathToRootAsCheckOnce(r); var prevDefault = this._genUpdatePreventDefault(eb, r); - return `${evalRecord}\n${markPath}\n${prevDefault}`; + return `${markPath}\n${evalRecord}\n${prevDefault}`; } else { return this._logic.genEventBindingEvalValue(eb, r); } diff --git a/modules/angular2/src/core/change_detection/dynamic_change_detector.ts b/modules/angular2/src/core/change_detection/dynamic_change_detector.ts index 078c51f20c..62be8b7df7 100644 --- a/modules/angular2/src/core/change_detection/dynamic_change_detector.ts +++ b/modules/angular2/src/core/change_detection/dynamic_change_detector.ts @@ -60,9 +60,11 @@ export class DynamicChangeDetector extends AbstractChangeDetector { if (proto.isSkipRecord()) { protoIdx += this._computeSkipLength(protoIdx, proto, values); } else { - var res = this._calculateCurrValue(proto, values, locals); if (proto.lastInBinding) { this._markPathAsCheckOnce(proto); + } + var res = this._calculateCurrValue(proto, values, locals); + if (proto.lastInBinding) { return res; } else { this._writeSelf(proto, res, values); diff --git a/modules/angular2/test/core/linker/integration_spec.ts b/modules/angular2/test/core/linker/integration_spec.ts index eb00f4b5dd..fb0f8e73f3 100644 --- a/modules/angular2/test/core/linker/integration_spec.ts +++ b/modules/angular2/test/core/linker/integration_spec.ts @@ -755,6 +755,30 @@ function declareTests() { async.done(); })})); + if (DOM.supportsDOMEvents()) { + it("should allow to destroy a component from within a host event handler", + inject([TestComponentBuilder], fakeAsync((tcb: TestComponentBuilder) => { + + var fixture: ComponentFixture; + tcb.overrideView( + MyComp, new ViewMetadata({ + template: '', + directives: [[[PushCmpWithHostEvent]]] + })) + + .createAsync(MyComp) + .then(root => { fixture = root; }); + tick(); + fixture.detectChanges(); + + var cmpEl = fixture.debugElement.children[0]; + var cmp: PushCmpWithHostEvent = cmpEl.inject(PushCmpWithHostEvent); + cmp.ctxCallback = (_) => fixture.destroy(); + + expect(() => cmpEl.triggerEventHandler('click', {})).not.toThrow(); + }))); + } + it('should not affect updating properties on the component', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { @@ -1953,6 +1977,16 @@ class PushCmpWithRef { propagate() { this.ref.markForCheck(); } } +@Component({ + selector: 'push-cmp-with-host-event', + host: {'(click)': 'ctxCallback($event)'}, + changeDetection: ChangeDetectionStrategy.OnPush, + template: '' +}) +class PushCmpWithHostEvent { + ctxCallback: Function = (_) => {}; +} + @Component({ selector: 'push-cmp-with-async', changeDetection: ChangeDetectionStrategy.OnPush,