fix(zone.js): handle MSPointer event correctly (#31722)
Close #31699 PR Close #31722
This commit is contained in:
parent
35a025fbca
commit
2c402d5c99
|
@ -39,6 +39,18 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) {
|
|||
const FUNCTION_WRAPPER = '[object FunctionWrapper]';
|
||||
const BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';
|
||||
|
||||
const pointerEventsMap: {[key: string]: string} = {
|
||||
'MSPointerCancel': 'pointercancel',
|
||||
'MSPointerDown': 'pointerdown',
|
||||
'MSPointerEnter': 'pointerenter',
|
||||
'MSPointerHover': 'pointerhover',
|
||||
'MSPointerLeave': 'pointerleave',
|
||||
'MSPointerMove': 'pointermove',
|
||||
'MSPointerOut': 'pointerout',
|
||||
'MSPointerOver': 'pointerover',
|
||||
'MSPointerUp': 'pointerup'
|
||||
};
|
||||
|
||||
// predefine all __zone_symbol__ + eventName + true/false string
|
||||
for (let i = 0; i < eventNames.length; i++) {
|
||||
const eventName = eventNames[i];
|
||||
|
@ -100,7 +112,13 @@ export function eventTargetLegacyPatch(_global: any, api: _ZonePrivate) {
|
|||
}
|
||||
// vh is validateHandler to check event handler
|
||||
// is valid or not(for security check)
|
||||
api.patchEventTarget(_global, apiTypes, {vh: checkIEAndCrossContext});
|
||||
api.patchEventTarget(_global, apiTypes, {
|
||||
vh: checkIEAndCrossContext,
|
||||
transferEventName: (eventName: string) => {
|
||||
const pointerEventName = pointerEventsMap[eventName];
|
||||
return pointerEventName || eventName;
|
||||
}
|
||||
});
|
||||
(Zone as any)[api.symbol('patchEventTarget')] = !!_global[EVENT_TARGET];
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ export interface PatchEventTargetOptions {
|
|||
supportPassive?: boolean;
|
||||
// get string from eventName (in nodejs, eventName maybe Symbol)
|
||||
eventNameToString?: (eventName: any) => string;
|
||||
// transfer eventName
|
||||
transferEventName?: (eventName: string) => string;
|
||||
}
|
||||
|
||||
export function patchEventTarget(
|
||||
|
@ -332,7 +334,10 @@ export function patchEventTarget(
|
|||
returnTarget = false, prepend = false) {
|
||||
return function(this: unknown) {
|
||||
const target = this || _global;
|
||||
const eventName = arguments[0];
|
||||
let eventName = arguments[0];
|
||||
if (patchOptions && patchOptions.transferEventName) {
|
||||
eventName = patchOptions.transferEventName(eventName);
|
||||
}
|
||||
let delegate = arguments[1];
|
||||
if (!delegate) {
|
||||
return nativeListener.apply(this, arguments);
|
||||
|
@ -498,7 +503,10 @@ export function patchEventTarget(
|
|||
|
||||
proto[REMOVE_EVENT_LISTENER] = function() {
|
||||
const target = this || _global;
|
||||
const eventName = arguments[0];
|
||||
let eventName = arguments[0];
|
||||
if (patchOptions && patchOptions.transferEventName) {
|
||||
eventName = patchOptions.transferEventName(eventName);
|
||||
}
|
||||
const options = arguments[2];
|
||||
|
||||
let capture;
|
||||
|
@ -565,7 +573,10 @@ export function patchEventTarget(
|
|||
|
||||
proto[LISTENERS_EVENT_LISTENER] = function() {
|
||||
const target = this || _global;
|
||||
const eventName = arguments[0];
|
||||
let eventName = arguments[0];
|
||||
if (patchOptions && patchOptions.transferEventName) {
|
||||
eventName = patchOptions.transferEventName(eventName);
|
||||
}
|
||||
|
||||
const listeners: any[] = [];
|
||||
const tasks =
|
||||
|
@ -582,7 +593,7 @@ export function patchEventTarget(
|
|||
proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function() {
|
||||
const target = this || _global;
|
||||
|
||||
const eventName = arguments[0];
|
||||
let eventName = arguments[0];
|
||||
if (!eventName) {
|
||||
const keys = Object.keys(target);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
|
@ -600,6 +611,9 @@ export function patchEventTarget(
|
|||
// remove removeListener listener finally
|
||||
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');
|
||||
} else {
|
||||
if (patchOptions && patchOptions.transferEventName) {
|
||||
eventName = patchOptions.transferEventName(eventName);
|
||||
}
|
||||
const symbolEventNames = zoneSymbolEventNames[eventName];
|
||||
if (symbolEventNames) {
|
||||
const symbolEventName = symbolEventNames[FALSE_STR];
|
||||
|
|
|
@ -2381,4 +2381,131 @@ describe('Zone', function() {
|
|||
}));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe(
|
||||
'pointer event in IE',
|
||||
ifEnvSupports(
|
||||
() => { return getIEVersion() === 11; },
|
||||
() => {
|
||||
const pointerEventsMap: {[key: string]: string} = {
|
||||
'MSPointerCancel': 'pointercancel',
|
||||
'MSPointerDown': 'pointerdown',
|
||||
'MSPointerEnter': 'pointerenter',
|
||||
'MSPointerHover': 'pointerhover',
|
||||
'MSPointerLeave': 'pointerleave',
|
||||
'MSPointerMove': 'pointermove',
|
||||
'MSPointerOut': 'pointerout',
|
||||
'MSPointerOver': 'pointerover',
|
||||
'MSPointerUp': 'pointerup'
|
||||
};
|
||||
|
||||
let div: HTMLDivElement;
|
||||
beforeEach(() => {
|
||||
div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
});
|
||||
afterEach(() => { document.body.removeChild(div); });
|
||||
Object.keys(pointerEventsMap).forEach(key => {
|
||||
it(`${key} and ${pointerEventsMap[key]} should both be triggered`, (done: DoneFn) => {
|
||||
const logs: string[] = [];
|
||||
div.addEventListener(key, (event: any) => {
|
||||
expect(event.type).toEqual(pointerEventsMap[key]);
|
||||
logs.push(`${key} triggered`);
|
||||
});
|
||||
div.addEventListener(pointerEventsMap[key], (event: any) => {
|
||||
expect(event.type).toEqual(pointerEventsMap[key]);
|
||||
logs.push(`${pointerEventsMap[key]} triggered`);
|
||||
});
|
||||
const evt1 = document.createEvent('Event');
|
||||
evt1.initEvent(key, true, true);
|
||||
div.dispatchEvent(evt1);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(logs).toEqual([`${key} triggered`, `${pointerEventsMap[key]} triggered`]);
|
||||
});
|
||||
|
||||
const evt2 = document.createEvent('Event');
|
||||
evt2.initEvent(pointerEventsMap[key], true, true);
|
||||
div.dispatchEvent(evt2);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(logs).toEqual([`${key} triggered`, `${pointerEventsMap[key]} triggered`]);
|
||||
});
|
||||
|
||||
setTimeout(done);
|
||||
});
|
||||
|
||||
it(`${key} and ${
|
||||
pointerEventsMap[key]} with same listener should not be triggered twice`,
|
||||
(done: DoneFn) => {
|
||||
const logs: string[] = [];
|
||||
const listener = function(event: any) {
|
||||
expect(event.type).toEqual(pointerEventsMap[key]);
|
||||
logs.push(`${key} triggered`);
|
||||
};
|
||||
div.addEventListener(key, listener);
|
||||
div.addEventListener(pointerEventsMap[key], listener);
|
||||
|
||||
const evt1 = document.createEvent('Event');
|
||||
evt1.initEvent(key, true, true);
|
||||
div.dispatchEvent(evt1);
|
||||
|
||||
setTimeout(() => { expect(logs).toEqual([`${key} triggered`]); });
|
||||
|
||||
const evt2 = document.createEvent('Event');
|
||||
evt2.initEvent(pointerEventsMap[key], true, true);
|
||||
div.dispatchEvent(evt2);
|
||||
|
||||
setTimeout(
|
||||
() => { expect(logs).toEqual([`${pointerEventsMap[key]} triggered`]); });
|
||||
|
||||
setTimeout(done);
|
||||
});
|
||||
|
||||
it(`${key} and ${
|
||||
pointerEventsMap
|
||||
[key]} should be able to be removed with removeEventListener`,
|
||||
(done: DoneFn) => {
|
||||
const logs: string[] = [];
|
||||
const listener1 = function(event: any) { logs.push(`${key} triggered`); };
|
||||
const listener2 = function(event: any) {
|
||||
logs.push(`${pointerEventsMap[key]} triggered`);
|
||||
};
|
||||
div.addEventListener(key, listener1);
|
||||
div.addEventListener(pointerEventsMap[key], listener2);
|
||||
|
||||
div.removeEventListener(key, listener1);
|
||||
div.removeEventListener(key, listener2);
|
||||
|
||||
const evt1 = document.createEvent('Event');
|
||||
evt1.initEvent(key, true, true);
|
||||
div.dispatchEvent(evt1);
|
||||
|
||||
setTimeout(() => { expect(logs).toEqual([]); });
|
||||
|
||||
const evt2 = document.createEvent('Event');
|
||||
evt2.initEvent(pointerEventsMap[key], true, true);
|
||||
div.dispatchEvent(evt2);
|
||||
|
||||
setTimeout(() => { expect(logs).toEqual([]); });
|
||||
|
||||
div.addEventListener(key, listener1);
|
||||
div.addEventListener(pointerEventsMap[key], listener2);
|
||||
|
||||
div.removeEventListener(pointerEventsMap[key], listener1);
|
||||
div.removeEventListener(pointerEventsMap[key], listener2);
|
||||
|
||||
div.dispatchEvent(evt1);
|
||||
|
||||
setTimeout(() => { expect(logs).toEqual([]); });
|
||||
|
||||
div.dispatchEvent(evt2);
|
||||
|
||||
setTimeout(() => { expect(logs).toEqual([]); });
|
||||
|
||||
setTimeout(done);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue