@samitouri / QOS-React / commits / 90d212d326

Fix movementX/Y polyfill with capture events (#19672)

* Fix movementX/Y polyfill with capture events * Remove unnecesary call for better inlining

Dan Abramov committed Aug 21, 2020 at 16:55 UTC 90d212d326d8bb8f5ee414801db37e688d585712
2 files changed +86 -25
packages/react-dom/src/events/SyntheticEvent.js
+22 -25
@@ -152,11 +152,22 @@ export const UIEventInterface: EventInterfaceType = {
152 detail: 0,
153 };
154
155 -let previousScreenX = 0;
156 -let previousScreenY = 0;
157 -// Use flags to signal movementX/Y has already been set
158 -let isMovementXSet = false;
159 -let isMovementYSet = false;
155 +let lastMovementX;
156 +let lastMovementY;
157 +let lastMouseEvent;
158 +
159 +function updateMouseMovementPolyfillState(event) {
160 + if (event !== lastMouseEvent) {
161 + if (lastMouseEvent && event.type === 'mousemove') {
162 + lastMovementX = event.screenX - lastMouseEvent.screenX;
163 + lastMovementY = event.screenY - lastMouseEvent.screenY;
164 + } else {
165 + lastMovementX = 0;
166 + lastMovementY = 0;
167 + }
168 + lastMouseEvent = event;
169 + }
170 +}
171
172 /**
173 * @interface MouseEvent
@@ -189,31 +200,17 @@ export const MouseEventInterface: EventInterfaceType = {
200 if ('movementX' in event) {
201 return event.movementX;
202 }
192 -
193 - const screenX = previousScreenX;
194 - previousScreenX = event.screenX;
195 -
196 - if (!isMovementXSet) {
197 - isMovementXSet = true;
198 - return 0;
199 - }
200 -
201 - return event.type === 'mousemove' ? event.screenX - screenX : 0;
203 + updateMouseMovementPolyfillState(event);
204 + return lastMovementX;
205 },
206 movementY: function(event) {
207 if ('movementY' in event) {
208 return event.movementY;
209 }
207 -
208 - const screenY = previousScreenY;
209 - previousScreenY = event.screenY;
210 -
211 - if (!isMovementYSet) {
212 - isMovementYSet = true;
213 - return 0;
214 - }
215 -
216 - return event.type === 'mousemove' ? event.screenY - screenY : 0;
210 + // Don't need to call updateMouseMovementPolyfillState() here
211 + // because it's guaranteed to have already run when movementX
212 + // was copied.
213 + return lastMovementY;
214 },
215 };
216
packages/react-dom/src/events/__tests__/SyntheticMouseEvent-test.js
+64
@@ -16,6 +16,7 @@ describe('SyntheticMouseEvent', () => {
16 let container;
17
18 beforeEach(() => {
19 + jest.resetModules();
20 React = require('react');
21 ReactDOM = require('react-dom');
22
@@ -77,4 +78,67 @@ describe('SyntheticMouseEvent', () => {
78 expect(events[1]).toBe(6);
79 expect(events[2]).toBe(0); // mousedown event should have movementX at 0
80 });
81 +
82 + it('should correctly calculate movementX/Y for capture phase', () => {
83 + const events = [];
84 + const onMouseMove = event => {
85 + events.push(['move', false, event.movementX, event.movementY]);
86 + };
87 + const onMouseMoveCapture = event => {
88 + events.push(['move', true, event.movementX, event.movementY]);
89 + };
90 + const onMouseDown = event => {
91 + events.push(['down', false, event.movementX, event.movementY]);
92 + };
93 + const onMouseDownCapture = event => {
94 + events.push(['down', true, event.movementX, event.movementY]);
95 + };
96 +
97 + const node = ReactDOM.render(
98 + <div
99 + onMouseMove={onMouseMove}
100 + onMouseMoveCapture={onMouseMoveCapture}
101 + onMouseDown={onMouseDown}
102 + onMouseDownCapture={onMouseDownCapture}
103 + />,
104 + container,
105 + );
106 +
107 + let event = new MouseEvent('mousemove', {
108 + relatedTarget: null,
109 + bubbles: true,
110 + screenX: 2,
111 + screenY: 2,
112 + });
113 +
114 + node.dispatchEvent(event);
115 +
116 + event = new MouseEvent('mousemove', {
117 + relatedTarget: null,
118 + bubbles: true,
119 + screenX: 8,
120 + screenY: 9,
121 + });
122 +
123 + node.dispatchEvent(event);
124 +
125 + // Now trigger a mousedown event to see if movementX has changed back to 0
126 + event = new MouseEvent('mousedown', {
127 + relatedTarget: null,
128 + bubbles: true,
129 + screenX: 25,
130 + screenY: 65,
131 + });
132 +
133 + node.dispatchEvent(event);
134 +
135 + expect(events).toEqual([
136 + ['move', true, 0, 0],
137 + ['move', false, 0, 0],
138 + ['move', true, 6, 7],
139 + ['move', false, 6, 7],
140 + ['down', true, 0, 0],
141 + ['down', false, 0, 0],
142 + ]);
143 + });
144 });