Skip to content

Commit 7fe8733

Browse files
fix: jQuery event types contain excessive props but lack originalEvent (DevExpress#30818)
1 parent a0e4064 commit 7fe8733

File tree

6 files changed

+201
-51
lines changed

6 files changed

+201
-51
lines changed

e2e/compilation-cases/T1282141.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { CutEvent } from 'devextreme/js/ui/color_box';
2+
import { EVENT_PROPERTIES } from 'devextreme/js/__internal/events/core/m_consts';
3+
4+
type NATIVE_EVENT_ARGS = KeyboardEvent
5+
& PointerEvent
6+
& TouchEvent
7+
& FocusEvent
8+
& WheelEvent
9+
& ClipboardEvent;
10+
11+
type NATIVE_EVENT_ARG_NON_PROPS = Pick<KeyboardEvent,
12+
'getModifierState'
13+
| 'initKeyboardEvent'
14+
| 'DOM_KEY_LOCATION_STANDARD'
15+
| 'DOM_KEY_LOCATION_LEFT'
16+
| 'DOM_KEY_LOCATION_RIGHT'
17+
| 'DOM_KEY_LOCATION_NUMPAD'>
18+
& Pick<UIEvent, 'initUIEvent'>
19+
& Pick<Event,
20+
'composedPath'
21+
| 'initEvent'
22+
| 'preventDefault'
23+
| 'stopImmediatePropagation'
24+
| 'stopPropagation'
25+
| 'NONE'
26+
| 'CAPTURING_PHASE'
27+
| 'AT_TARGET'
28+
| 'BUBBLING_PHASE'>
29+
& Pick<PointerEvent, 'getCoalescedEvents' | 'getPredictedEvents'>
30+
& Pick<MouseEvent, 'initMouseEvent'>
31+
& Pick<WheelEvent, 'DOM_DELTA_PIXEL' | 'DOM_DELTA_LINE' | 'DOM_DELTA_PAGE'>;
32+
33+
type PROPS_ASSIGNED_ELSEWHERE = {
34+
type: string;
35+
isTrusted: boolean;
36+
timeStamp: number;
37+
which: number;
38+
currentTarget: EventTarget | null;
39+
40+
// touch hooks
41+
clientX: number;
42+
clientY: number;
43+
pageX: number;
44+
pageY: number;
45+
screenX: number;
46+
screenY: number;
47+
}
48+
49+
type IGNORED_MEMBERS = NATIVE_EVENT_ARG_NON_PROPS & PROPS_ASSIGNED_ELSEWHERE;
50+
51+
type ASSIGNED_EVENT_ARG_GETTERS = {
52+
[Property in typeof EVENT_PROPERTIES[number]]
53+
};
54+
55+
function fn(): void {
56+
let e: CutEvent = undefined as unknown as CutEvent;
57+
58+
e.event?.originalEvent.clipboardData?.clearData();
59+
60+
let dxGetters = undefined as unknown as ASSIGNED_EVENT_ARG_GETTERS & IGNORED_MEMBERS;
61+
let nativeArgs = undefined as unknown as NATIVE_EVENT_ARGS;
62+
63+
nativeArgs = dxGetters;
64+
}
65+
66+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* eslint-disable spellcheck/spell-checker */
2+
export const EMPTY_EVENT_NAME = 'dxEmptyEventType';
3+
export const NATIVE_EVENTS_TO_SUBSCRIBE = {
4+
mouseenter: 'mouseover',
5+
mouseleave: 'mouseout',
6+
pointerenter: 'pointerover',
7+
pointerleave: 'pointerout',
8+
};
9+
export const NATIVE_EVENTS_TO_TRIGGER = {
10+
focusin: 'focus',
11+
focusout: 'blur',
12+
};
13+
export const NO_BUBBLE_EVENTS = ['blur', 'focus', 'load'];
14+
15+
export const forcePassiveFalseEventNames = ['touchmove', 'wheel', 'mousewheel', 'touchstart'];
16+
17+
export const EVENT_PROPERTIES = [
18+
'altKey',
19+
'altitudeAngle',
20+
'azimuthAngle',
21+
'bubbles',
22+
'button',
23+
'buttons',
24+
'cancelable',
25+
'cancelBubble',
26+
'changedTouches',
27+
'char',
28+
'charCode',
29+
'clipboardData',
30+
'code',
31+
'composed',
32+
'ctrlKey',
33+
'defaultPrevented',
34+
'delegateTarget',
35+
'deltaMode',
36+
'deltaX',
37+
'deltaY',
38+
'deltaZ',
39+
'detail',
40+
'eventPhase',
41+
'height',
42+
'isComposing',
43+
'isPrimary',
44+
'key',
45+
'keyCode',
46+
'layerX',
47+
'layerY',
48+
'location',
49+
'metaKey',
50+
'movementX',
51+
'movementY',
52+
'offsetX',
53+
'offsetY',
54+
'pointerId',
55+
'pointerType',
56+
'pressure',
57+
'relatedTarget',
58+
'repeat',
59+
'returnValue',
60+
'srcElement',
61+
'shiftKey',
62+
'tangentialPressure',
63+
'target',
64+
'targetTouches',
65+
'tiltX',
66+
'tiltY',
67+
'toElement',
68+
'touches',
69+
'twist',
70+
'view',
71+
'width',
72+
'x',
73+
'y',
74+
] as const;

packages/devextreme/js/__internal/events/core/m_events_engine.ts

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,55 +11,17 @@ import {
1111
isFunction, isObject, isString, isWindow,
1212
} from '@js/core/utils/type';
1313
import { getWindow, hasWindow } from '@js/core/utils/window';
14+
import {
15+
EMPTY_EVENT_NAME,
16+
EVENT_PROPERTIES,
17+
forcePassiveFalseEventNames,
18+
NATIVE_EVENTS_TO_SUBSCRIBE,
19+
NATIVE_EVENTS_TO_TRIGGER,
20+
NO_BUBBLE_EVENTS,
21+
} from '@ts/events/core/m_consts';
1422

1523
const window = getWindow();
1624

17-
/* eslint-disable spellcheck/spell-checker */
18-
const EMPTY_EVENT_NAME = 'dxEmptyEventType';
19-
const NATIVE_EVENTS_TO_SUBSCRIBE = {
20-
mouseenter: 'mouseover',
21-
mouseleave: 'mouseout',
22-
pointerenter: 'pointerover',
23-
pointerleave: 'pointerout',
24-
};
25-
const NATIVE_EVENTS_TO_TRIGGER = {
26-
focusin: 'focus',
27-
focusout: 'blur',
28-
};
29-
const NO_BUBBLE_EVENTS = ['blur', 'focus', 'load'];
30-
31-
const forcePassiveFalseEventNames = ['touchmove', 'wheel', 'mousewheel', 'touchstart'];
32-
33-
const EVENT_PROPERTIES = [
34-
'target',
35-
'relatedTarget',
36-
'delegateTarget',
37-
'altKey',
38-
'bubbles',
39-
'cancelable',
40-
'changedTouches',
41-
'ctrlKey',
42-
'detail',
43-
'eventPhase',
44-
'metaKey',
45-
'shiftKey',
46-
'view',
47-
'char',
48-
'code',
49-
'charCode',
50-
'key',
51-
'keyCode',
52-
'button',
53-
'buttons',
54-
'offsetX',
55-
'offsetY',
56-
'pointerId',
57-
'pointerType',
58-
'targetTouches',
59-
'toElement',
60-
'touches',
61-
];
62-
6325
function matchesSafe(target, selector) {
6426
return !isWindow(target) && target.nodeName !== '#document' && domAdapter.elementMatches(target, selector);
6527
}

packages/devextreme/js/events/events.types.d.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @namespace DevExpress.events
33
*/
4-
export type EventObject = {
4+
export type EventObject<TNativeEvent = Event> = {
55
/**
66
* @docid
77
* @public
@@ -20,6 +20,13 @@ export type EventObject = {
2020
*/
2121
delegateTarget: Element;
2222

23+
/**
24+
* @docid
25+
* @public
26+
* @type event
27+
*/
28+
originalEvent: TNativeEvent;
29+
2330
/**
2431
* @docid
2532
* @public
@@ -81,7 +88,16 @@ export interface EventType { }
8188
* @type EventObject|jQuery.Event
8289
* @hidden
8390
*/
84-
export type DxEvent<TNativeEvent = Event> = {} extends EventType ? (EventObject & TNativeEvent) : EventType;
91+
export type DxEvent<TNativeEvent = Event> = {} extends EventType
92+
? (EventObject<TNativeEvent> & TNativeEvent)
93+
: (Omit<EventType, 'originalEvent'> & {
94+
/**
95+
* @docid
96+
* @public
97+
* @type event
98+
*/
99+
originalEvent: TNativeEvent;
100+
});
85101

86102
/** @deprecated EventObject */
87103
export type dxEvent = EventObject;

packages/devextreme/testing/tests/DevExpress.ui.events/eventsEngine.tests.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import eventsEngine from 'common/core/events/core/events_engine';
33
import keyboardMock from '../../helpers/keyboardMock.js';
44
import registerEvent from 'common/core/events/core/event_registrator';
55
import { compare as compareVersion } from 'core/utils/version';
6+
import { EVENT_PROPERTIES } from '__internal/events/core/m_consts';
7+
import config from 'core/config';
68

79
QUnit.module('base');
810

@@ -258,6 +260,26 @@ QUnit.test('Simulate clicks, check which property', function(assert) {
258260
}
259261
});
260262

263+
QUnit.test('Check getters attached to event wrappers', function(assert) {
264+
const done = assert.async();
265+
const useJQuery = config().useJQuery;
266+
const div = document.createElement('div');
267+
const handler = function(e) {
268+
if(e instanceof eventsEngine.Event && !useJQuery) {
269+
EVENT_PROPERTIES.forEach(prop => { assert.ok(prop in e, `getter for the '${prop}' prop found in the event arg`); });
270+
} else {
271+
assert.ok(true);
272+
}
273+
done();
274+
};
275+
276+
document.body.appendChild(div);
277+
eventsEngine.on(div, 'click', handler);
278+
const event = div.ownerDocument.createEvent('MouseEvents');
279+
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
280+
div.dispatchEvent(event);
281+
});
282+
261283
QUnit.test('Simulate tab press, check key property', function(assert) {
262284
const done = assert.async();
263285
const input = document.createElement('input');

packages/devextreme/ts/dx.all.d.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7594,8 +7594,13 @@ declare module DevExpress.events {
75947594
* @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution.
75957595
*/
75967596
export type DxEvent<TNativeEvent = Event> = {} extends EventType
7597-
? EventObject & TNativeEvent
7598-
: EventType;
7597+
? EventObject<TNativeEvent> & TNativeEvent
7598+
: Omit<EventType, 'originalEvent'> & {
7599+
/**
7600+
* [descr:DxEvent.originalEvent]
7601+
*/
7602+
originalEvent: TNativeEvent;
7603+
};
75997604
/**
76007605
* [descr:event]
76017606
* @deprecated [depNote:event]
@@ -7605,7 +7610,7 @@ declare module DevExpress.events {
76057610
/**
76067611
* @deprecated Attention! This type is for internal purposes only. If you used it previously, please submit a ticket to our {@link https://supportcenter.devexpress.com/ticket/create Support Center}. We will check if there is an alternative solution.
76077612
*/
7608-
export type EventObject = {
7613+
export type EventObject<TNativeEvent = Event> = {
76097614
/**
76107615
* [descr:EventObject.currentTarget]
76117616
*/
@@ -7621,6 +7626,11 @@ declare module DevExpress.events {
76217626
*/
76227627
delegateTarget: Element;
76237628

7629+
/**
7630+
* [descr:EventObject.originalEvent]
7631+
*/
7632+
originalEvent: TNativeEvent;
7633+
76247634
/**
76257635
* [descr:EventObject.target]
76267636
*/

0 commit comments

Comments
 (0)