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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue