Add internal logic for listening to event responders (#15168)
* Add the logic for listening to event responders
This commit is contained in:
parent
b1a56abd6a
commit
66f280c87b
|
@ -13,6 +13,8 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
|
|||
import warning from 'shared/warning';
|
||||
import {canUseDOM} from 'shared/ExecutionEnvironment';
|
||||
import warningWithoutStack from 'shared/warningWithoutStack';
|
||||
import type {ReactEventResponder} from 'shared/ReactTypes';
|
||||
import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
|
||||
|
||||
import {
|
||||
getValueForAttribute,
|
||||
|
@ -57,7 +59,12 @@ import {
|
|||
TOP_SUBMIT,
|
||||
TOP_TOGGLE,
|
||||
} 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 {
|
||||
createDangerousStringForStyles,
|
||||
|
@ -78,6 +85,8 @@ import {validateProperties as validateARIAProperties} from '../shared/ReactDOMIn
|
|||
import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
|
||||
import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
|
||||
|
||||
import {enableEventAPI} from 'shared/ReactFeatureFlags';
|
||||
|
||||
let didWarnInvalidHydration = false;
|
||||
let didWarnShadyDOM = false;
|
||||
|
||||
|
@ -1267,3 +1276,65 @@ export function restoreControlledState(
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
warnForDeletedHydratableText,
|
||||
warnForInsertedHydratedElement,
|
||||
warnForInsertedHydratedText,
|
||||
listenToEventResponderEvents,
|
||||
} from './ReactDOMComponent';
|
||||
import {getSelectionInformation, restoreSelection} from './ReactInputSelection';
|
||||
import setTextContent from './setTextContent';
|
||||
|
@ -860,15 +861,16 @@ export function handleEventComponent(
|
|||
eventResponder: ReactEventResponder,
|
||||
rootContainerInstance: Container,
|
||||
internalInstanceHandle: Object,
|
||||
) {
|
||||
// TODO: add handleEventComponent implementation
|
||||
): void {
|
||||
const rootElement = rootContainerInstance.ownerDocument;
|
||||
listenToEventResponderEvents(eventResponder, rootElement);
|
||||
}
|
||||
|
||||
export function handleEventTarget(
|
||||
type: Symbol | number,
|
||||
props: Props,
|
||||
internalInstanceHandle: Object,
|
||||
) {
|
||||
): void {
|
||||
// Touch target hit slop handling
|
||||
if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
|
||||
// Validates that there is a single element
|
||||
|
|
|
@ -90,12 +90,12 @@ const elementListeningSets:
|
|||
| WeakMap
|
||||
| Map<
|
||||
Document | Element | Node,
|
||||
Set<DOMTopLevelEventType>,
|
||||
Set<DOMTopLevelEventType | string>,
|
||||
> = new PossiblyWeakMap();
|
||||
|
||||
function getListeningSetForElement(
|
||||
export function getListeningSetForElement(
|
||||
element: Document | Element | Node,
|
||||
): Set<DOMTopLevelEventType> {
|
||||
): Set<DOMTopLevelEventType | string> {
|
||||
let listeningSet = elementListeningSets.get(element);
|
||||
if (listeningSet === undefined) {
|
||||
listeningSet = new Set();
|
||||
|
|
|
@ -60,15 +60,15 @@
|
|||
"filename": "react-dom.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 798048,
|
||||
"gzip": 181482
|
||||
"size": 813661,
|
||||
"gzip": 184364
|
||||
},
|
||||
{
|
||||
"filename": "react-dom.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 107733,
|
||||
"gzip": 34431
|
||||
"size": 108035,
|
||||
"gzip": 34515
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOM-dev.js",
|
||||
|
@ -102,15 +102,15 @@
|
|||
"filename": "react-dom-test-utils.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 47988,
|
||||
"gzip": 13245
|
||||
"size": 48334,
|
||||
"gzip": 13206
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-test-utils.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 10288,
|
||||
"gzip": 3812
|
||||
"size": 9954,
|
||||
"gzip": 3660
|
||||
},
|
||||
{
|
||||
"filename": "ReactTestUtils-dev.js",
|
||||
|
@ -137,15 +137,15 @@
|
|||
"filename": "react-dom-unstable-native-dependencies.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 61725,
|
||||
"gzip": 16151
|
||||
"size": 61643,
|
||||
"gzip": 16033
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-native-dependencies.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 11001,
|
||||
"gzip": 3783
|
||||
"size": 10669,
|
||||
"gzip": 3640
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOMUnstableNativeDependencies-dev.js",
|
||||
|
@ -179,15 +179,15 @@
|
|||
"filename": "react-dom-server.browser.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 129302,
|
||||
"gzip": 34571
|
||||
"size": 132758,
|
||||
"gzip": 35195
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-server.browser.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 19590,
|
||||
"gzip": 7447
|
||||
"size": 19756,
|
||||
"gzip": 7540
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOMServer-dev.js",
|
||||
|
@ -207,15 +207,15 @@
|
|||
"filename": "react-dom-server.node.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 131409,
|
||||
"gzip": 35129
|
||||
"size": 134747,
|
||||
"gzip": 35752
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-server.node.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 20483,
|
||||
"gzip": 7757
|
||||
"size": 20639,
|
||||
"gzip": 7850
|
||||
},
|
||||
{
|
||||
"filename": "react-art.development.js",
|
||||
|
@ -718,8 +718,8 @@
|
|||
"filename": "react-dom.profiling.min.js",
|
||||
"bundleType": "NODE_PROFILING",
|
||||
"packageName": "react-dom",
|
||||
"size": 110923,
|
||||
"gzip": 35060
|
||||
"size": 111211,
|
||||
"gzip": 35133
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-profiling.js",
|
||||
|
@ -1054,22 +1054,22 @@
|
|||
"filename": "react-dom-unstable-fire.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 798401,
|
||||
"gzip": 181622
|
||||
"size": 814014,
|
||||
"gzip": 184503
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fire.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 107747,
|
||||
"gzip": 34441
|
||||
"size": 108049,
|
||||
"gzip": 34524
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fire.profiling.min.js",
|
||||
"bundleType": "NODE_PROFILING",
|
||||
"packageName": "react-dom",
|
||||
"size": 110937,
|
||||
"gzip": 35069
|
||||
"size": 111225,
|
||||
"gzip": 35142
|
||||
},
|
||||
{
|
||||
"filename": "ReactFire-dev.js",
|
||||
|
|
Loading…
Reference in New Issue