diff --git a/src/jqLite.js b/src/jqLite.js index 8a45f9663d4e..c1b5b36ec444 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -645,7 +645,10 @@ function createEventHandler(element, events) { return event.defaultPrevented || event.returnValue === false; }; - forEach(events[type || event.type], function(fn) { + // Copy event handlers in case event handlers array is modified during execution. + var eventHandlersCopy = shallowCopy(events[type || event.type] || []); + + forEach(eventHandlersCopy, function(fn) { fn.call(element, event); }); diff --git a/test/jqLiteSpec.js b/test/jqLiteSpec.js index c4f47dcd2f55..3a8fd4045c5b 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -1120,6 +1120,26 @@ describe('jqLite', function() { }); + it('should deregister specific listener within the listener and call subsequent listeners', function() { + var aElem = jqLite(a), + clickSpy = jasmine.createSpy('click'), + clickOnceSpy = jasmine.createSpy('clickOnce').andCallFake(function() { + aElem.off('click', clickOnceSpy); + }); + + aElem.on('click', clickOnceSpy); + aElem.on('click', clickSpy); + + browserTrigger(a, 'click'); + expect(clickOnceSpy).toHaveBeenCalledOnce(); + expect(clickSpy).toHaveBeenCalledOnce(); + + browserTrigger(a, 'click'); + expect(clickOnceSpy).toHaveBeenCalledOnce(); + expect(clickSpy.callCount).toBe(2); + }); + + it('should deregister specific listener for multiple types separated by spaces', function() { var aElem = jqLite(a), masterSpy = jasmine.createSpy('master'),