diff --git a/modules/core/src/compiler/view.js b/modules/core/src/compiler/view.js index 7052b20a7e..5e51da7d44 100644 --- a/modules/core/src/compiler/view.js +++ b/modules/core/src/compiler/view.js @@ -381,10 +381,14 @@ export class ProtoView { MapWrapper.forEach(binder.events, (expr, eventName) => { DOM.on(element, eventName, (event) => { if (event.target === element) { + // Most of the time the event will be fired only when the view is + // in the live document. However, in a rare circumstance the + // view might get dehydrated, in between the event queuing up and + // firing. // TODO(rado): replace with // expr.eval(new ContextWithVariableBindings(view.context, {'$event': event})); // when eval with variable bindinds works. - expr.eval(view.context); + if (view.hydrated()) expr.eval(view.context); } }); }); diff --git a/modules/core/test/compiler/view_spec.js b/modules/core/test/compiler/view_spec.js index d0bddb215b..20e69a65b1 100644 --- a/modules/core/test/compiler/view_spec.js +++ b/modules/core/test/compiler/view_spec.js @@ -403,6 +403,54 @@ export function main() { }); }); + describe('event handlers', () => { + var view, ctx, called; + + function createViewAndContext(protoView) { + view = createView(protoView); + ctx = view.context; + called = 0; + ctx.callMe = () => called += 1; + } + + function dispatchClick(el) { + DOM.dispatchEvent(el, DOM.createMouseEvent('click')); + } + + function createProtoView() { + var pv = new ProtoView(el('
'), + new ProtoRecordRange()); + pv.bindElement(new TestProtoElementInjector(null, 0, [])); + pv.bindEvent('click', parser.parseBinding('callMe()', null)); + return pv; + } + + it('should fire on non-bubbling native events', () => { + createViewAndContext(createProtoView()); + + dispatchClick(view.nodes[0]); + + expect(called).toEqual(1); + }); + + it('should not fire on a bubbled native events', () => { + createViewAndContext(createProtoView()); + + dispatchClick(view.nodes[0].firstChild); + + // This test passes trivially on webkit browsers due to + // https://bugs.webkit.org/show_bug.cgi?id=122755 + expect(called).toEqual(0); + }); + + it('should not throw if the view is dehydrated', () => { + createViewAndContext(createProtoView()); + + view.dehydrate(); + dispatchClick(view.nodes[0]); + }); + }); + describe('react to record changes', () => { var view, cd, ctx; @@ -583,6 +631,7 @@ class MyEvaluationContext { foo:string; a; b; + callMe; constructor() { this.foo = 'bar'; };