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

Commit d7f8e6d

Browse files
committed
update duplicate check and remove logic
1 parent ce76a20 commit d7f8e6d

File tree

2 files changed

+148
-38
lines changed

2 files changed

+148
-38
lines changed

lib/common/events.ts

+54-19
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* @suppress {missingRequire}
1111
*/
1212

13-
import {ADD_EVENT_LISTENER_STR, attachOriginToPatched, FALSE_STR, isIEOrEdge, ObjectGetPrototypeOf, REMOVE_EVENT_LISTENER_STR, TRUE_STR, ZONE_SYMBOL_PREFIX, zoneSymbol} from './utils';
13+
import {ADD_EVENT_LISTENER_STR, attachOriginToPatched, FALSE_STR, isIE, isIEOrEdge, ObjectGetPrototypeOf, REMOVE_EVENT_LISTENER_STR, TRUE_STR, ZONE_SYMBOL_PREFIX, zoneSymbol} from './utils';
1414

1515
/** @internal **/
1616
interface EventTaskData extends TaskData {
@@ -19,15 +19,15 @@ interface EventTaskData extends TaskData {
1919
}
2020

2121
const pointerEventsMap: {[key: string]: string} = {
22-
'pointercancel': 'MSPointerCancel',
23-
'pointerdown': 'MSPointerDown',
24-
'pointerenter': 'MSPointerEnter',
25-
'pointerhover': 'MSPointerHover',
26-
'pointerleave': 'MSPointerLeave',
27-
'pointermove': 'MSPointerMove',
28-
'pointerout': 'MSPointerOut',
29-
'pointerover': 'MSPointerOver',
30-
'pointerup': 'MSPointerUp'
22+
'MSPointerCancel': 'pointercancel',
23+
'MSPointerDown': 'pointerdown',
24+
'MSPointerEnter': 'pointerenter',
25+
'MSPointerHover': 'pointerhover',
26+
'MSPointerLeave': 'pointerleave',
27+
'MSPointerMove': 'pointermove',
28+
'MSPointerOut': 'pointerout',
29+
'MSPointerOver': 'pointerover',
30+
'MSPointerUp': 'pointerup'
3131
};
3232

3333
let passiveSupported = false;
@@ -99,6 +99,16 @@ export function patchEventTarget(
9999
const PREPEND_EVENT_LISTENER = 'prependListener';
100100
const PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':';
101101

102+
Object.keys(pointerEventsMap).forEach(msEventName => {
103+
const eventName = pointerEventsMap[msEventName];
104+
zoneSymbolEventNames[eventName] = {};
105+
zoneSymbolEventNames[eventName][FALSE_STR] = ZONE_SYMBOL_PREFIX + eventName + FALSE_STR;
106+
zoneSymbolEventNames[eventName][TRUE_STR] = ZONE_SYMBOL_PREFIX + eventName + TRUE_STR;
107+
zoneSymbolEventNames[msEventName] = {};
108+
zoneSymbolEventNames[msEventName][FALSE_STR] = ZONE_SYMBOL_PREFIX + msEventName + FALSE_STR;
109+
zoneSymbolEventNames[msEventName][TRUE_STR] = ZONE_SYMBOL_PREFIX + msEventName + TRUE_STR;
110+
});
111+
102112
const invokeTask = function(task: any, target: any, event: Event) {
103113
// for better performance, check isRemoved which is set
104114
// by removeEventListener
@@ -135,10 +145,13 @@ export function patchEventTarget(
135145
// || global is needed https://github.com/angular/zone.js/issues/190
136146
const target: any = this || event.target || _global;
137147
let tasks = target[zoneSymbolEventNames[event.type][FALSE_STR]];
138-
if (!tasks && isIEOrEdge) {
148+
if (isIEOrEdge) {
139149
const pointerMappedEvent = pointerEventsMap[event.type];
140-
tasks =
141-
pointerMappedEvent ? target[zoneSymbolEventNames[pointerMappedEvent]][FALSE_STR] : tasks;
150+
const msTasks =
151+
pointerMappedEvent && target[zoneSymbolEventNames[pointerMappedEvent]][FALSE_STR];
152+
if (msTasks) {
153+
tasks = tasks.concat(msTasks);
154+
}
142155
}
143156
if (tasks) {
144157
// invoke all tasks which attached to current target with given event.type and capture = false
@@ -172,10 +185,13 @@ export function patchEventTarget(
172185
// || global is needed https://github.com/angular/zone.js/issues/190
173186
const target: any = this || event.target || _global;
174187
let tasks = target[zoneSymbolEventNames[event.type][TRUE_STR]];
175-
if (!tasks && isIEOrEdge) {
188+
if (isIEOrEdge) {
176189
const pointerMappedEvent = pointerEventsMap[event.type];
177-
tasks =
178-
pointerMappedEvent ? target[zoneSymbolEventNames[pointerMappedEvent]][TRUE_STR] : tasks;
190+
const msTasks =
191+
pointerMappedEvent && target[zoneSymbolEventNames[pointerMappedEvent]][FALSE_STR];
192+
if (msTasks) {
193+
tasks = tasks.concat(msTasks);
194+
}
179195
}
180196
if (tasks) {
181197
// invoke all tasks which attached to current target with given event.type and capture = false
@@ -372,7 +388,11 @@ export function patchEventTarget(
372388
return;
373389
}
374390

375-
const eventName = arguments[0];
391+
let eventName = arguments[0];
392+
if (isIEOrEdge) {
393+
const msEventName = pointerEventsMap[eventName];
394+
eventName = msEventName ? msEventName : eventName;
395+
}
376396
const options = arguments[2];
377397

378398
if (blackListedEvents) {
@@ -415,6 +435,13 @@ export function patchEventTarget(
415435
}
416436
let existingTasks = target[symbolEventName];
417437
let isExisting = false;
438+
if (isIEOrEdge && !existingTasks) {
439+
const msEventName = pointerEventsMap[eventName];
440+
if (msEventName) {
441+
existingTasks =
442+
target[zoneSymbolEventNames[msEventName][capture ? TRUE_STR : FALSE_STR]];
443+
}
444+
}
418445
if (existingTasks) {
419446
// already have task registered
420447
isExisting = true;
@@ -449,7 +476,8 @@ export function patchEventTarget(
449476
}
450477
taskData.target = target;
451478
taskData.capture = capture;
452-
taskData.eventName = eventName;
479+
// in pointer event, we need to use original event name here.
480+
taskData.eventName = arguments[0];
453481
taskData.isExisting = isExisting;
454482

455483
const data = useGlobalCallback ? OPTIMIZED_ZONE_EVENT_TASK_DATA : undefined;
@@ -511,7 +539,11 @@ export function patchEventTarget(
511539

512540
proto[REMOVE_EVENT_LISTENER] = function() {
513541
const target = this || _global;
514-
const eventName = arguments[0];
542+
let eventName = arguments[0];
543+
if (isIEOrEdge) {
544+
const msEventName = pointerEventsMap[eventName];
545+
eventName = msEventName ? msEventName : eventName;
546+
}
515547
const options = arguments[2];
516548

517549
let capture;
@@ -553,6 +585,9 @@ export function patchEventTarget(
553585
// remove globalZoneAwareCallback and remove the task cache from target
554586
(existingTask as any).allRemoved = true;
555587
target[symbolEventName] = null;
588+
if (isIEOrEdge) {
589+
existingTask.eventName = arguments[0];
590+
}
556591
}
557592
existingTask.zone.cancelTask(existingTask);
558593
if (returnTarget) {

test/browser/browser.spec.ts

+94-19
Original file line numberDiff line numberDiff line change
@@ -2671,16 +2671,17 @@ describe('Zone', function() {
26712671
},
26722672
() => {
26732673
const pointerEventsMap: {[key: string]: string} = {
2674-
'pointercancel': 'MSPointerCancel',
2675-
'pointerdown': 'MSPointerDown',
2676-
'pointerenter': 'MSPointerEnter',
2677-
'pointerhover': 'MSPointerHover',
2678-
'pointerleave': 'MSPointerLeave',
2679-
'pointermove': 'MSPointerMove',
2680-
'pointerout': 'MSPointerOut',
2681-
'pointerover': 'MSPointerOver',
2682-
'pointerup': 'MSPointerUp'
2674+
'MSPointerCancel': 'pointercancel',
2675+
'MSPointerDown': 'pointerdown',
2676+
'MSPointerEnter': 'pointerenter',
2677+
'MSPointerHover': 'pointerhover',
2678+
'MSPointerLeave': 'pointerleave',
2679+
'MSPointerMove': 'pointermove',
2680+
'MSPointerOut': 'pointerout',
2681+
'MSPointerOver': 'pointerover',
2682+
'MSPointerUp': 'pointerup'
26832683
};
2684+
26842685
let div: HTMLDivElement;
26852686
beforeEach(() => {
26862687
div = document.createElement('div');
@@ -2690,16 +2691,6 @@ describe('Zone', function() {
26902691
document.body.removeChild(div);
26912692
});
26922693
Object.keys(pointerEventsMap).forEach(key => {
2693-
it(`${key} should be registered as ${pointerEventsMap[key]}`, (done: DoneFn) => {
2694-
div.addEventListener(key, (event: any) => {
2695-
expect(event.type).toEqual(pointerEventsMap[key]);
2696-
done();
2697-
});
2698-
const evt = document.createEvent('Event');
2699-
evt.initEvent(key, true, true);
2700-
div.dispatchEvent(evt);
2701-
});
2702-
27032694
it(`${key} and ${pointerEventsMap[key]} should both be triggered`,
27042695
(done: DoneFn) => {
27052696
const logs: string[] = [];
@@ -2729,6 +2720,90 @@ describe('Zone', function() {
27292720
[`${key} triggered`, `${pointerEventsMap[key]} triggered`]);
27302721
});
27312722

2723+
setTimeout(done);
2724+
});
2725+
2726+
it(`${key} and ${
2727+
pointerEventsMap[key]} with same listener should not be triggered twice`,
2728+
(done: DoneFn) => {
2729+
const logs: string[] = [];
2730+
const listener = function(event: any) {
2731+
expect(event.type).toEqual(pointerEventsMap[key]);
2732+
logs.push(`${key} triggered`);
2733+
};
2734+
div.addEventListener(key, listener);
2735+
div.addEventListener(pointerEventsMap[key], listener);
2736+
2737+
const evt1 = document.createEvent('Event');
2738+
evt1.initEvent(key, true, true);
2739+
div.dispatchEvent(evt1);
2740+
2741+
setTimeout(() => {
2742+
expect(logs).toEqual([`${key} triggered`]);
2743+
});
2744+
2745+
const evt2 = document.createEvent('Event');
2746+
evt2.initEvent(pointerEventsMap[key], true, true);
2747+
div.dispatchEvent(evt2);
2748+
2749+
setTimeout(() => {
2750+
expect(logs).toEqual([`${pointerEventsMap[key]} triggered`]);
2751+
});
2752+
2753+
setTimeout(done);
2754+
});
2755+
2756+
it(`${key} and ${
2757+
pointerEventsMap
2758+
[key]} should be able to be removed with removeEventListener`,
2759+
(done: DoneFn) => {
2760+
const logs: string[] = [];
2761+
const listener1 = function(event: any) {
2762+
logs.push(`${key} triggered`);
2763+
};
2764+
const listener2 = function(event: any) {
2765+
logs.push(`${pointerEventsMap[key]} triggered`);
2766+
};
2767+
div.addEventListener(key, listener1);
2768+
div.addEventListener(pointerEventsMap[key], listener2);
2769+
2770+
div.removeEventListener(key, listener1);
2771+
div.removeEventListener(key, listener2);
2772+
2773+
const evt1 = document.createEvent('Event');
2774+
evt1.initEvent(key, true, true);
2775+
div.dispatchEvent(evt1);
2776+
2777+
setTimeout(() => {
2778+
expect(logs).toEqual([]);
2779+
});
2780+
2781+
const evt2 = document.createEvent('Event');
2782+
evt2.initEvent(pointerEventsMap[key], true, true);
2783+
div.dispatchEvent(evt2);
2784+
2785+
setTimeout(() => {
2786+
expect(logs).toEqual([]);
2787+
});
2788+
2789+
div.addEventListener(key, listener1);
2790+
div.addEventListener(pointerEventsMap[key], listener2);
2791+
2792+
div.removeEventListener(pointerEventsMap[key], listener1);
2793+
div.removeEventListener(pointerEventsMap[key], listener2);
2794+
2795+
div.dispatchEvent(evt1);
2796+
2797+
setTimeout(() => {
2798+
expect(logs).toEqual([]);
2799+
});
2800+
2801+
div.dispatchEvent(evt2);
2802+
2803+
setTimeout(() => {
2804+
expect(logs).toEqual([]);
2805+
});
2806+
27322807
setTimeout(done);
27332808
});
27342809
});

0 commit comments

Comments
 (0)