Add internal logic for listening to event responders (#15168)

* Add the logic for listening to event responders
This commit is contained in:
Dominic Gannaway 2019-03-21 12:32:40 +00:00 committed by GitHub
parent b1a56abd6a
commit 66f280c87b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 35 deletions

View File

@ -13,6 +13,8 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
import warning from 'shared/warning'; import warning from 'shared/warning';
import {canUseDOM} from 'shared/ExecutionEnvironment'; import {canUseDOM} from 'shared/ExecutionEnvironment';
import warningWithoutStack from 'shared/warningWithoutStack'; import warningWithoutStack from 'shared/warningWithoutStack';
import type {ReactEventResponder} from 'shared/ReactTypes';
import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
import { import {
getValueForAttribute, getValueForAttribute,
@ -57,7 +59,12 @@ import {
TOP_SUBMIT, TOP_SUBMIT,
TOP_TOGGLE, TOP_TOGGLE,
} from '../events/DOMTopLevelEventTypes'; } from '../events/DOMTopLevelEventTypes';
import {listenTo, trapBubbledEvent} from '../events/ReactBrowserEventEmitter'; import {
listenTo,
trapBubbledEvent,
getListeningSetForElement,
} from '../events/ReactBrowserEventEmitter';
import {trapEventForResponderEventSystem} from '../events/ReactDOMEventListener.js';
import {mediaEventTypes} from '../events/DOMTopLevelEventTypes'; import {mediaEventTypes} from '../events/DOMTopLevelEventTypes';
import { import {
createDangerousStringForStyles, createDangerousStringForStyles,
@ -78,6 +85,8 @@ import {validateProperties as validateARIAProperties} from '../shared/ReactDOMIn
import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook'; import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook'; import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
import {enableEventAPI} from 'shared/ReactFeatureFlags';
let didWarnInvalidHydration = false; let didWarnInvalidHydration = false;
let didWarnShadyDOM = false; let didWarnShadyDOM = false;
@ -1267,3 +1276,65 @@ export function restoreControlledState(
return; return;
} }
} }
export function listenToEventResponderEvents(
eventResponder: ReactEventResponder,
element: Element | Document,
): void {
if (enableEventAPI) {
const {targetEventTypes} = eventResponder;
// Get the listening Set for this element. We use this to track
// what events we're listening to.
const listeningSet = getListeningSetForElement(element);
// Go through each target event type of the event responder
for (let i = 0, length = targetEventTypes.length; i < length; ++i) {
const targetEventType = targetEventTypes[i];
let topLevelType;
let capture = false;
let passive = true;
// If no event config object is provided (i.e. - only a string),
// we default to enabling passive and not capture.
if (typeof targetEventType === 'string') {
topLevelType = targetEventType;
} else {
if (__DEV__) {
warning(
typeof targetEventType === 'object' && targetEventType !== null,
'Event Responder: invalid entry in targetEventTypes array. ' +
'Entry must be string or an object. Instead, got %s.',
targetEventType,
);
}
const targetEventConfigObject = ((targetEventType: any): {
name: string,
passive?: boolean,
capture?: boolean,
});
topLevelType = targetEventConfigObject.name;
if (targetEventConfigObject.passive !== undefined) {
passive = targetEventConfigObject.passive;
}
if (targetEventConfigObject.capture !== undefined) {
capture = targetEventConfigObject.capture;
}
}
// Create a unique name for this event, plus its properties. We'll
// use this to ensure we don't listen to the same event with the same
// properties again.
const passiveKey = passive ? '_passive' : '';
const captureKey = capture ? '_capture' : '';
const listeningName = `${topLevelType}${passiveKey}${captureKey}`;
if (!listeningSet.has(listeningName)) {
trapEventForResponderEventSystem(
element,
((topLevelType: any): DOMTopLevelEventType),
capture,
passive,
);
listeningSet.add(listeningName);
}
}
}
}

View File

@ -24,6 +24,7 @@ import {
warnForDeletedHydratableText, warnForDeletedHydratableText,
warnForInsertedHydratedElement, warnForInsertedHydratedElement,
warnForInsertedHydratedText, warnForInsertedHydratedText,
listenToEventResponderEvents,
} from './ReactDOMComponent'; } from './ReactDOMComponent';
import {getSelectionInformation, restoreSelection} from './ReactInputSelection'; import {getSelectionInformation, restoreSelection} from './ReactInputSelection';
import setTextContent from './setTextContent'; import setTextContent from './setTextContent';
@ -860,15 +861,16 @@ export function handleEventComponent(
eventResponder: ReactEventResponder, eventResponder: ReactEventResponder,
rootContainerInstance: Container, rootContainerInstance: Container,
internalInstanceHandle: Object, internalInstanceHandle: Object,
) { ): void {
// TODO: add handleEventComponent implementation const rootElement = rootContainerInstance.ownerDocument;
listenToEventResponderEvents(eventResponder, rootElement);
} }
export function handleEventTarget( export function handleEventTarget(
type: Symbol | number, type: Symbol | number,
props: Props, props: Props,
internalInstanceHandle: Object, internalInstanceHandle: Object,
) { ): void {
// Touch target hit slop handling // Touch target hit slop handling
if (type === REACT_EVENT_TARGET_TOUCH_HIT) { if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
// Validates that there is a single element // Validates that there is a single element

View File

@ -90,12 +90,12 @@ const elementListeningSets:
| WeakMap | WeakMap
| Map< | Map<
Document | Element | Node, Document | Element | Node,
Set<DOMTopLevelEventType>, Set<DOMTopLevelEventType | string>,
> = new PossiblyWeakMap(); > = new PossiblyWeakMap();
function getListeningSetForElement( export function getListeningSetForElement(
element: Document | Element | Node, element: Document | Element | Node,
): Set<DOMTopLevelEventType> { ): Set<DOMTopLevelEventType | string> {
let listeningSet = elementListeningSets.get(element); let listeningSet = elementListeningSets.get(element);
if (listeningSet === undefined) { if (listeningSet === undefined) {
listeningSet = new Set(); listeningSet = new Set();

View File

@ -60,15 +60,15 @@
"filename": "react-dom.development.js", "filename": "react-dom.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 798048, "size": 813661,
"gzip": 181482 "gzip": 184364
}, },
{ {
"filename": "react-dom.production.min.js", "filename": "react-dom.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 107733, "size": 108035,
"gzip": 34431 "gzip": 34515
}, },
{ {
"filename": "ReactDOM-dev.js", "filename": "ReactDOM-dev.js",
@ -102,15 +102,15 @@
"filename": "react-dom-test-utils.development.js", "filename": "react-dom-test-utils.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 47988, "size": 48334,
"gzip": 13245 "gzip": 13206
}, },
{ {
"filename": "react-dom-test-utils.production.min.js", "filename": "react-dom-test-utils.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 10288, "size": 9954,
"gzip": 3812 "gzip": 3660
}, },
{ {
"filename": "ReactTestUtils-dev.js", "filename": "ReactTestUtils-dev.js",
@ -137,15 +137,15 @@
"filename": "react-dom-unstable-native-dependencies.development.js", "filename": "react-dom-unstable-native-dependencies.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 61725, "size": 61643,
"gzip": 16151 "gzip": 16033
}, },
{ {
"filename": "react-dom-unstable-native-dependencies.production.min.js", "filename": "react-dom-unstable-native-dependencies.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 11001, "size": 10669,
"gzip": 3783 "gzip": 3640
}, },
{ {
"filename": "ReactDOMUnstableNativeDependencies-dev.js", "filename": "ReactDOMUnstableNativeDependencies-dev.js",
@ -179,15 +179,15 @@
"filename": "react-dom-server.browser.development.js", "filename": "react-dom-server.browser.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 129302, "size": 132758,
"gzip": 34571 "gzip": 35195
}, },
{ {
"filename": "react-dom-server.browser.production.min.js", "filename": "react-dom-server.browser.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 19590, "size": 19756,
"gzip": 7447 "gzip": 7540
}, },
{ {
"filename": "ReactDOMServer-dev.js", "filename": "ReactDOMServer-dev.js",
@ -207,15 +207,15 @@
"filename": "react-dom-server.node.development.js", "filename": "react-dom-server.node.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 131409, "size": 134747,
"gzip": 35129 "gzip": 35752
}, },
{ {
"filename": "react-dom-server.node.production.min.js", "filename": "react-dom-server.node.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 20483, "size": 20639,
"gzip": 7757 "gzip": 7850
}, },
{ {
"filename": "react-art.development.js", "filename": "react-art.development.js",
@ -718,8 +718,8 @@
"filename": "react-dom.profiling.min.js", "filename": "react-dom.profiling.min.js",
"bundleType": "NODE_PROFILING", "bundleType": "NODE_PROFILING",
"packageName": "react-dom", "packageName": "react-dom",
"size": 110923, "size": 111211,
"gzip": 35060 "gzip": 35133
}, },
{ {
"filename": "ReactNativeRenderer-profiling.js", "filename": "ReactNativeRenderer-profiling.js",
@ -1054,22 +1054,22 @@
"filename": "react-dom-unstable-fire.development.js", "filename": "react-dom-unstable-fire.development.js",
"bundleType": "NODE_DEV", "bundleType": "NODE_DEV",
"packageName": "react-dom", "packageName": "react-dom",
"size": 798401, "size": 814014,
"gzip": 181622 "gzip": 184503
}, },
{ {
"filename": "react-dom-unstable-fire.production.min.js", "filename": "react-dom-unstable-fire.production.min.js",
"bundleType": "NODE_PROD", "bundleType": "NODE_PROD",
"packageName": "react-dom", "packageName": "react-dom",
"size": 107747, "size": 108049,
"gzip": 34441 "gzip": 34524
}, },
{ {
"filename": "react-dom-unstable-fire.profiling.min.js", "filename": "react-dom-unstable-fire.profiling.min.js",
"bundleType": "NODE_PROFILING", "bundleType": "NODE_PROFILING",
"packageName": "react-dom", "packageName": "react-dom",
"size": 110937, "size": 111225,
"gzip": 35069 "gzip": 35142
}, },
{ {
"filename": "ReactFire-dev.js", "filename": "ReactFire-dev.js",