[Flare] Improve runtime performance of hit target intersection (#15836)
Dominic Gannaway committed
Jun 7, 2019 at 15:57 UTC
425473f43fd95a564f07ffcf6dbd105cef9f78b9
6 files changed
+14
-41
packages/react-dom/src/events/DOMEventResponderSystem.js
+8
-8
@@ -189,15 +189,15 @@ const eventResponderContext: ReactResponderContext = {
189
eventListeners.set(eventObject, listener);
190
eventQueue.events.push(eventObject);
191
},
192
- isPositionWithinTouchHitTarget(x: number, y: number): boolean {
192
+ isEventWithinTouchHitTarget(event: ReactResponderEvent): boolean {
193
validateResponderContext();
194
- const doc = getActiveDocument();
195
- // This isn't available in some environments (JSDOM)
196
- if (typeof doc.elementFromPoint !== 'function') {
197
- return false;
198
- }
199
- const target = doc.elementFromPoint(x, y);
200
- if (target === null) {
194
+ const target = event.target;
195
+ const nativeEvent = event.nativeEvent;
196
+ // We should always be dealing with a mouse event or touch event here.
197
+ // If we are not, these won't exist and we can early return.
198
+ const x = (nativeEvent: any).clientX;
199
+ const y = (nativeEvent: any).clientY;
200
+ if (x === undefined || y === undefined) {
201
return false;
202
}
203
const childFiber = getClosestInstanceFromNode(target);
packages/react-events/README.md
+1
-1
@@ -127,7 +127,7 @@ Component instance.
127
128
Returns `true` if the instance has taken ownership of the responder.
129
130
-### isPositionWithinTouchHitTarget(x: number, y: number): boolean
130
+### isEventWithinTouchHitTarget(event: ResponderEvent): boolean
131
132
Returns `true` if the global coordinates lie within the TouchHitTarget.
133
packages/react-events/src/Hover.js
+3
-4
@@ -13,7 +13,6 @@ import type {
13
} from 'shared/ReactTypes';
14
15
import React from 'react';
16
-import {isEventPositionWithinTouchHitTarget} from './utils';
16
import {UserBlockingEvent} from 'shared/ReactTypes';
17
18
type HoverProps = {
@@ -326,7 +325,7 @@ const HoverResponder = {
325
return;
326
}
327
329
- if (isEventPositionWithinTouchHitTarget(event, context)) {
328
+ if (context.isEventWithinTouchHitTarget(event)) {
329
state.isOverTouchHitTarget = true;
330
return;
331
}
@@ -345,14 +344,14 @@ const HoverResponder = {
344
if (state.isOverTouchHitTarget) {
345
// If we were moving over the TouchHitTarget and have now moved
346
// over the Responder target
348
- if (!isEventPositionWithinTouchHitTarget(event, context)) {
347
+ if (!context.isEventWithinTouchHitTarget(event)) {
348
dispatchHoverStartEvents(event, context, props, state);
349
state.isOverTouchHitTarget = false;
350
}
351
} else {
352
// If we were moving over the Responder target and have now moved
353
// over the TouchHitTarget
355
- if (isEventPositionWithinTouchHitTarget(event, context)) {
354
+ if (context.isEventWithinTouchHitTarget(event)) {
355
dispatchHoverEndEvents(event, context, props, state);
356
state.isOverTouchHitTarget = true;
357
} else {
packages/react-events/src/Press.js
+1
-2
@@ -14,7 +14,6 @@ import type {
14
import type {EventPriority} from 'shared/ReactTypes';
15
16
import React from 'react';
17
-import {isEventPositionWithinTouchHitTarget} from './utils';
17
import {DiscreteEvent, UserBlockingEvent} from 'shared/ReactTypes';
18
19
type PressProps = {
@@ -644,7 +643,7 @@ const PressResponder = {
643
const isMouseType = pointerType === 'mouse';
644
if (
645
(isMouseType || pointerType === 'pen') &&
647
- isEventPositionWithinTouchHitTarget(event, context)
646
+ context.isEventWithinTouchHitTarget(event)
647
) {
648
// We need to prevent the native event to block the focus
649
nativeEvent.preventDefault();
packages/react-events/src/utils.js
deleted
-25
@@ -1,25 +0,0 @@
1
-/**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {
11
- ReactResponderEvent,
12
- ReactResponderContext,
13
-} from 'shared/ReactTypes';
14
-
15
-export function isEventPositionWithinTouchHitTarget(
16
- event: ReactResponderEvent,
17
- context: ReactResponderContext,
18
-) {
19
- const nativeEvent: any = event.nativeEvent;
20
- return context.isPositionWithinTouchHitTarget(
21
- // x and y can be doubles, so ensure they are integers
22
- parseInt(nativeEvent.clientX, 10),
23
- parseInt(nativeEvent.clientY, 10),
24
- );
25
-}
packages/shared/ReactTypes.js
+1
-1
@@ -176,7 +176,7 @@ export type ReactResponderContext = {
176
) => boolean,
177
isTargetWithinEventComponent: (Element | Document) => boolean,
178
isTargetWithinEventResponderScope: (Element | Document) => boolean,
179
- isPositionWithinTouchHitTarget: (x: number, y: number) => boolean,
179
+ isEventWithinTouchHitTarget: (event: ReactResponderEvent) => boolean,
180
addRootEventTypes: (
181
rootEventTypes: Array<ReactEventResponderEventType>,
182
) => void,