Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit af88ff8

Browse files
Matthew Hillvicb
authored andcommitted
fix(utils): event listener patches break when passed an object implementing EventListener
1 parent da5f265 commit af88ff8

File tree

2 files changed

+67
-11
lines changed

2 files changed

+67
-11
lines changed

lib/utils.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,37 @@ function patchProperties(obj, properties) {
8686

8787
function patchEventTargetMethods(obj) {
8888
var addDelegate = obj.addEventListener;
89-
obj.addEventListener = function (eventName, fn) {
90-
fn._bound = fn._bound || {};
91-
arguments[1] = fn._bound[eventName] = zone.bind(fn);
89+
obj.addEventListener = function (eventName, handler) {
90+
var fn;
91+
92+
if (handler.handleEvent) {
93+
// Have to pass in 'handler' reference as an argument here, otherwise it gets clobbered in
94+
// IE9 by the arguments[1] assignment at end of this function.
95+
fn = (function(handler) {
96+
return function() {
97+
handler.handleEvent.apply(handler, arguments);
98+
};
99+
})(handler);
100+
} else {
101+
fn = handler;
102+
}
103+
104+
handler._fn = fn;
105+
handler._bound = handler._bound || {};
106+
arguments[1] = handler._bound[eventName] = zone.bind(fn);
92107
return addDelegate.apply(this, arguments);
93108
};
94109

95110
var removeDelegate = obj.removeEventListener;
96-
obj.removeEventListener = function (eventName, fn) {
97-
if(arguments[1]._bound && arguments[1]._bound[eventName]) {
98-
var _bound = arguments[1]._bound;
111+
obj.removeEventListener = function (eventName, handler) {
112+
if(handler._bound && handler._bound[eventName]) {
113+
var _bound = handler._bound;
114+
99115
arguments[1] = _bound[eventName];
100116
delete _bound[eventName];
101117
}
102118
var result = removeDelegate.apply(this, arguments);
103-
global.zone.dequeueTask(fn);
119+
global.zone.dequeueTask(handler._fn);
104120
return result;
105121
};
106122
};

test/patch/element.spec.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,43 @@ describe('element', function () {
1414
document.body.removeChild(button);
1515
});
1616

17-
it('should work with addEventListener', function () {
17+
it('should work with addEventListener when called with a function listener', function () {
18+
var clickEvent = document.createEvent('Event');
19+
clickEvent.initEvent('click', true, true);
20+
1821
testZone.run(function() {
19-
button.addEventListener('click', function () {
22+
button.addEventListener('click', function (event) {
2023
expect(zone).toBeDirectChildOf(testZone);
24+
expect(event).toBe(clickEvent)
2125
});
2226
});
2327

24-
button.click();
28+
button.dispatchEvent(clickEvent);
2529
});
2630

27-
it('should respect removeEventListener', function () {
31+
it('should work with addEventListener when called with an EventListener-implementing listener', function () {
32+
var eventListener = {
33+
x: 5,
34+
handleEvent: function(event) {
35+
// Test that context is preserved
36+
expect(this.x).toBe(5);
37+
38+
expect(event).toBe(clickEvent);
39+
expect(zone).toBeDirectChildOf(testZone);
40+
}
41+
};
42+
43+
var clickEvent = document.createEvent('Event');
44+
clickEvent.initEvent('click', true, true);
45+
46+
testZone.run(function() {
47+
button.addEventListener('click', eventListener);
48+
});
49+
50+
button.dispatchEvent(clickEvent);
51+
});
52+
53+
it('should respect removeEventListener when called with a function listener', function () {
2854
var log = '';
2955
var logFunction = function logFunction () {
3056
log += 'a';
@@ -44,6 +70,20 @@ describe('element', function () {
4470
expect(log).toEqual('aa');
4571
});
4672

73+
it('should respect removeEventListener with an EventListener-implementing listener', function () {
74+
var eventListener = {
75+
x: 5,
76+
handleEvent: jasmine.createSpy('handleEvent')
77+
};
78+
79+
button.addEventListener('click', eventListener);
80+
button.removeEventListener('click', eventListener);
81+
82+
button.click();
83+
84+
expect(eventListener.handleEvent).not.toHaveBeenCalled();
85+
});
86+
4787

4888
describe('onclick', function() {
4989

0 commit comments

Comments
 (0)