From 425473f43fd95a564f07ffcf6dbd105cef9f78b9 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 7 Jun 2019 15:57:10 +0100 Subject: [PATCH] [Flare] Improve runtime performance of hit target intersection (#15836) --- .../src/events/DOMEventResponderSystem.js | 16 ++++++------ packages/react-events/README.md | 2 +- packages/react-events/src/Hover.js | 7 +++--- packages/react-events/src/Press.js | 3 +-- packages/react-events/src/utils.js | 25 ------------------- packages/shared/ReactTypes.js | 2 +- 6 files changed, 14 insertions(+), 41 deletions(-) delete mode 100644 packages/react-events/src/utils.js diff --git a/packages/react-dom/src/events/DOMEventResponderSystem.js b/packages/react-dom/src/events/DOMEventResponderSystem.js index 58faa75dc7..18aca524d5 100644 --- a/packages/react-dom/src/events/DOMEventResponderSystem.js +++ b/packages/react-dom/src/events/DOMEventResponderSystem.js @@ -189,15 +189,15 @@ const eventResponderContext: ReactResponderContext = { eventListeners.set(eventObject, listener); eventQueue.events.push(eventObject); }, - isPositionWithinTouchHitTarget(x: number, y: number): boolean { + isEventWithinTouchHitTarget(event: ReactResponderEvent): boolean { validateResponderContext(); - const doc = getActiveDocument(); - // This isn't available in some environments (JSDOM) - if (typeof doc.elementFromPoint !== 'function') { - return false; - } - const target = doc.elementFromPoint(x, y); - if (target === null) { + const target = event.target; + const nativeEvent = event.nativeEvent; + // We should always be dealing with a mouse event or touch event here. + // If we are not, these won't exist and we can early return. + const x = (nativeEvent: any).clientX; + const y = (nativeEvent: any).clientY; + if (x === undefined || y === undefined) { return false; } const childFiber = getClosestInstanceFromNode(target); diff --git a/packages/react-events/README.md b/packages/react-events/README.md index d7da96a7b7..3d345c4817 100644 --- a/packages/react-events/README.md +++ b/packages/react-events/README.md @@ -127,7 +127,7 @@ Component instance. Returns `true` if the instance has taken ownership of the responder. -### isPositionWithinTouchHitTarget(x: number, y: number): boolean +### isEventWithinTouchHitTarget(event: ResponderEvent): boolean Returns `true` if the global coordinates lie within the TouchHitTarget. diff --git a/packages/react-events/src/Hover.js b/packages/react-events/src/Hover.js index b47fa9d66c..77e977f824 100644 --- a/packages/react-events/src/Hover.js +++ b/packages/react-events/src/Hover.js @@ -13,7 +13,6 @@ import type { } from 'shared/ReactTypes'; import React from 'react'; -import {isEventPositionWithinTouchHitTarget} from './utils'; import {UserBlockingEvent} from 'shared/ReactTypes'; type HoverProps = { @@ -326,7 +325,7 @@ const HoverResponder = { return; } - if (isEventPositionWithinTouchHitTarget(event, context)) { + if (context.isEventWithinTouchHitTarget(event)) { state.isOverTouchHitTarget = true; return; } @@ -345,14 +344,14 @@ const HoverResponder = { if (state.isOverTouchHitTarget) { // If we were moving over the TouchHitTarget and have now moved // over the Responder target - if (!isEventPositionWithinTouchHitTarget(event, context)) { + if (!context.isEventWithinTouchHitTarget(event)) { dispatchHoverStartEvents(event, context, props, state); state.isOverTouchHitTarget = false; } } else { // If we were moving over the Responder target and have now moved // over the TouchHitTarget - if (isEventPositionWithinTouchHitTarget(event, context)) { + if (context.isEventWithinTouchHitTarget(event)) { dispatchHoverEndEvents(event, context, props, state); state.isOverTouchHitTarget = true; } else { diff --git a/packages/react-events/src/Press.js b/packages/react-events/src/Press.js index 9e89bc9be0..6781c562f9 100644 --- a/packages/react-events/src/Press.js +++ b/packages/react-events/src/Press.js @@ -14,7 +14,6 @@ import type { import type {EventPriority} from 'shared/ReactTypes'; import React from 'react'; -import {isEventPositionWithinTouchHitTarget} from './utils'; import {DiscreteEvent, UserBlockingEvent} from 'shared/ReactTypes'; type PressProps = { @@ -644,7 +643,7 @@ const PressResponder = { const isMouseType = pointerType === 'mouse'; if ( (isMouseType || pointerType === 'pen') && - isEventPositionWithinTouchHitTarget(event, context) + context.isEventWithinTouchHitTarget(event) ) { // We need to prevent the native event to block the focus nativeEvent.preventDefault(); diff --git a/packages/react-events/src/utils.js b/packages/react-events/src/utils.js deleted file mode 100644 index 904057e5c6..0000000000 --- a/packages/react-events/src/utils.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type { - ReactResponderEvent, - ReactResponderContext, -} from 'shared/ReactTypes'; - -export function isEventPositionWithinTouchHitTarget( - event: ReactResponderEvent, - context: ReactResponderContext, -) { - const nativeEvent: any = event.nativeEvent; - return context.isPositionWithinTouchHitTarget( - // x and y can be doubles, so ensure they are integers - parseInt(nativeEvent.clientX, 10), - parseInt(nativeEvent.clientY, 10), - ); -} diff --git a/packages/shared/ReactTypes.js b/packages/shared/ReactTypes.js index 3bfd77ea53..96ebdcb58b 100644 --- a/packages/shared/ReactTypes.js +++ b/packages/shared/ReactTypes.js @@ -176,7 +176,7 @@ export type ReactResponderContext = { ) => boolean, isTargetWithinEventComponent: (Element | Document) => boolean, isTargetWithinEventResponderScope: (Element | Document) => boolean, - isPositionWithinTouchHitTarget: (x: number, y: number) => boolean, + isEventWithinTouchHitTarget: (event: ReactResponderEvent) => boolean, addRootEventTypes: ( rootEventTypes: Array, ) => void,