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

Commit 8718e07

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(event): EventTarget of SourceBuffer in samsung tv will have null context (#904)
* fix: EventTarget when using Samusung TV and SourceBuffer * fix(event): add test cases for EventTarget patch for Samsung tv * ignore null context test in ie9
1 parent 5c8828e commit 8718e07

File tree

4 files changed

+94
-7
lines changed

4 files changed

+94
-7
lines changed

lib/common/events.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,12 @@ export function patchEventTarget(
9393

9494
// global shared zoneAwareCallback to handle all event callback with capture = false
9595
const globalZoneAwareCallback = function(event: Event) {
96-
const target = this || _global;
97-
96+
if (!event) {
97+
return;
98+
}
99+
// event.target is needed for Samusung TV and SourceBuffer
100+
// || global is needed https://github.com/angular/zone.js/issues/190
101+
const target: any = this || event.target || _global;
98102
const tasks = target[zoneSymbolEventNames[event.type][FALSE_STR]];
99103
if (tasks) {
100104
// invoke all tasks which attached to current target with given event.type and capture = false
@@ -118,8 +122,12 @@ export function patchEventTarget(
118122

119123
// global shared zoneAwareCallback to handle all event callback with capture = true
120124
const globalZoneAwareCaptureCallback = function(event: Event) {
121-
const target = this || _global;
122-
125+
if (!event) {
126+
return;
127+
}
128+
// event.target is needed for Samusung TV and SourceBuffer
129+
// || global is needed https://github.com/angular/zone.js/issues/190
130+
const target: any = this || event.target || _global;
123131
const tasks = target[zoneSymbolEventNames[event.type][TRUE_STR]];
124132
if (tasks) {
125133
// invoke all tasks which attached to current target with given event.type and capture = false

lib/common/utils.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,14 @@ export const isMix: boolean = typeof _global.process !== 'undefined' &&
8989

9090
const ON_PROPERTY_HANDLER_SYMBOL = zoneSymbol('onPropertyHandler');
9191
const zoneSymbolEventNames: {[eventName: string]: string} = {};
92+
9293
const wrapFn = function(event: Event) {
9394
let eventNameSymbol = zoneSymbolEventNames[event.type];
9495
if (!eventNameSymbol) {
9596
eventNameSymbol = zoneSymbolEventNames[event.type] = zoneSymbol('ON_PROPERTY' + event.type);
9697
}
97-
const listener = this[eventNameSymbol];
98+
const target = this || event && event.target || _global;
99+
const listener = target[eventNameSymbol];
98100
let result = listener && listener.apply(this, arguments);
99101

100102
if (result != undefined && !result) {

test/browser/browser.spec.ts

+70-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
*/
88

99
import {patchFilteredProperties} from '../../lib/browser/property-descriptor';
10+
import {patchEventTarget} from '../../lib/common/events';
1011
import {isBrowser, isIEOrEdge, isMix, zoneSymbol} from '../../lib/common/utils';
11-
import {ifEnvSupports, ifEnvSupportsWithDone} from '../test-util';
12+
import {getIEVersion, ifEnvSupports, ifEnvSupportsWithDone} from '../test-util';
1213

1314
import Spy = jasmine.Spy;
1415
declare const global: any;
@@ -243,6 +244,74 @@ describe('Zone', function() {
243244
document.removeEventListener('mousedown', eventListenerSpy);
244245
}));
245246

247+
it('event handler with null context should use event.target',
248+
ifEnvSupports(canPatchOnProperty(Document.prototype, 'onmousedown'), function() {
249+
const ieVer = getIEVersion();
250+
if (ieVer && ieVer === 9) {
251+
// in ie9, this is window object even we call func.apply(undefined)
252+
return;
253+
}
254+
const logs: string[] = [];
255+
const EventTarget = (window as any)['EventTarget'];
256+
let oriAddEventListener = EventTarget && EventTarget.prototype ?
257+
(EventTarget.prototype as any)['__zone_symbol__addEventListener'] :
258+
(HTMLSpanElement.prototype as any)['__zone_symbol__addEventListener'];
259+
260+
if (!oriAddEventListener) {
261+
// no patched addEventListener found
262+
return;
263+
}
264+
let handler1: Function;
265+
let handler2: Function;
266+
267+
const listener = function() {
268+
logs.push('listener1');
269+
};
270+
271+
const listener1 = function() {
272+
logs.push('listener2');
273+
};
274+
275+
HTMLSpanElement.prototype.addEventListener = function(
276+
eventName: string, callback: any) {
277+
if (eventName === 'click') {
278+
handler1 = callback;
279+
} else if (eventName === 'mousedown') {
280+
handler2 = callback;
281+
}
282+
return oriAddEventListener.apply(this, arguments);
283+
};
284+
285+
(HTMLSpanElement.prototype as any)['__zone_symbol__addEventListener'] = null;
286+
287+
patchEventTarget(window, [HTMLSpanElement.prototype]);
288+
289+
const span = document.createElement('span');
290+
document.body.appendChild(span);
291+
292+
zone.run(function() {
293+
span.addEventListener('click', listener);
294+
span.onmousedown = listener1;
295+
});
296+
297+
expect(handler1).toBe(handler2);
298+
299+
handler1.apply(undefined, [{type: 'click', target: span}]);
300+
301+
handler2.apply(undefined, [{type: 'mousedown', target: span}]);
302+
303+
expect(hookSpy).toHaveBeenCalled();
304+
expect(logs).toEqual(['listener1', 'listener2']);
305+
document.body.removeChild(span);
306+
if (EventTarget) {
307+
(EventTarget.prototype as any)['__zone_symbol__addEventListener'] =
308+
oriAddEventListener;
309+
} else {
310+
(HTMLSpanElement.prototype as any)['__zone_symbol__addEventListener'] =
311+
oriAddEventListener;
312+
}
313+
}));
314+
246315
it('SVGElement onclick should be in zone',
247316
ifEnvSupports(
248317
canPatchOnProperty(SVGElement && SVGElement.prototype, 'onmousedown'), function() {

test/test-util.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,12 @@ export function asyncTest(testFn: Function, zone: Zone = Zone.current) {
9595
}, 'asyncTest'));
9696
asyncTestZone.run(testFn, this, [done]);
9797
};
98-
}
98+
}
99+
100+
export function getIEVersion() {
101+
const userAgent = navigator.userAgent.toLowerCase();
102+
if (userAgent.indexOf('msie') != -1) {
103+
return parseInt(userAgent.split('msie')[1]);
104+
}
105+
return null;
106+
}

0 commit comments

Comments
 (0)