diff --git a/src/jqLite.js b/src/jqLite.js index 218efe244be1..bffb047b46ab 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -631,7 +631,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 02a17df81679..5b73d0f4d99d 100644 --- a/test/jqLiteSpec.js +++ b/test/jqLiteSpec.js @@ -1099,6 +1099,28 @@ describe('jqLite', function() { }); + it('should deregister specific listener within the listener and call subsequent listeners', function() { + var aElem = jqLite(a), + clickOnceSpy = jasmine.createSpy('clickOnce'), + clickSpy = jasmine.createSpy('click'), + clickOnceListener = function () { + aElem.off('click', clickOnceListener); + return clickOnceSpy(); + }; + + aElem.on('click', clickOnceListener); + 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'),