mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[Flare] Rework the responder dispatching/batching mechanism (#16334)
This commit is contained in:
@@ -11,6 +11,8 @@ import {
|
||||
} from './ReactControlledComponent';
|
||||
import {enableFlareAPI} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils';
|
||||
|
||||
// Used as a way to call batchedUpdates when we don't have a reference to
|
||||
// the renderer. Such as when we're dispatching events or if third party
|
||||
// libraries need to call batchedUpdates. Eventually, this API will go away when
|
||||
@@ -28,6 +30,7 @@ let flushDiscreteUpdatesImpl = function() {};
|
||||
let batchedEventUpdatesImpl = batchedUpdatesImpl;
|
||||
|
||||
let isInsideEventHandler = false;
|
||||
let isBatchingEventUpdates = false;
|
||||
|
||||
function finishEventHandler() {
|
||||
// Here we wait until all updates have propagated, which is important
|
||||
@@ -60,20 +63,31 @@ export function batchedUpdates(fn, bookkeeping) {
|
||||
}
|
||||
|
||||
export function batchedEventUpdates(fn, a, b) {
|
||||
if (isInsideEventHandler) {
|
||||
if (isBatchingEventUpdates) {
|
||||
// If we are currently inside another batch, we need to wait until it
|
||||
// fully completes before restoring state.
|
||||
return fn(a, b);
|
||||
}
|
||||
isInsideEventHandler = true;
|
||||
isBatchingEventUpdates = true;
|
||||
try {
|
||||
return batchedEventUpdatesImpl(fn, a, b);
|
||||
} finally {
|
||||
isInsideEventHandler = false;
|
||||
isBatchingEventUpdates = false;
|
||||
finishEventHandler();
|
||||
}
|
||||
}
|
||||
|
||||
export function executeUserEventHandler(fn: any => void, value: any) {
|
||||
const previouslyInEventHandler = isInsideEventHandler;
|
||||
try {
|
||||
isInsideEventHandler = true;
|
||||
const type = typeof value === 'object' && value !== null ? value.type : '';
|
||||
invokeGuardedCallbackAndCatchFirstError(type, fn, undefined, value);
|
||||
} finally {
|
||||
isInsideEventHandler = previouslyInEventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
export function discreteUpdates(fn, a, b, c) {
|
||||
const prevIsInsideEventHandler = isInsideEventHandler;
|
||||
isInsideEventHandler = true;
|
||||
|
||||
@@ -25,12 +25,12 @@ import {
|
||||
batchedEventUpdates,
|
||||
discreteUpdates,
|
||||
flushDiscreteUpdatesIfNeeded,
|
||||
executeUserEventHandler,
|
||||
} from 'legacy-events/ReactGenericBatching';
|
||||
import {enqueueStateRestore} from 'legacy-events/ReactControlledComponent';
|
||||
import type {Fiber} from 'react-reconciler/src/ReactFiber';
|
||||
import warning from 'shared/warning';
|
||||
import {enableFlareAPI} from 'shared/ReactFeatureFlags';
|
||||
import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils';
|
||||
import invariant from 'shared/invariant';
|
||||
import {
|
||||
isFiberSuspenseAndTimedOut,
|
||||
@@ -61,12 +61,6 @@ export function setListenToResponderEventTypes(
|
||||
listenToResponderEventTypesImpl = _listenToResponderEventTypesImpl;
|
||||
}
|
||||
|
||||
type EventQueueItem = {|
|
||||
listener: (val: any) => void,
|
||||
value: any,
|
||||
|};
|
||||
type EventQueue = Array<EventQueueItem>;
|
||||
|
||||
type ResponderTimeout = {|
|
||||
id: TimeoutID,
|
||||
timers: Map<number, ResponderTimer>,
|
||||
@@ -84,15 +78,10 @@ const rootEventTypesToEventResponderInstances: Map<
|
||||
DOMTopLevelEventType | string,
|
||||
Set<ReactDOMEventResponderInstance>,
|
||||
> = new Map();
|
||||
const ownershipChangeListeners: Set<ReactDOMEventResponderInstance> = new Set();
|
||||
|
||||
let globalOwner = null;
|
||||
|
||||
let currentTimeStamp = 0;
|
||||
let currentTimers = new Map();
|
||||
let currentInstance: null | ReactDOMEventResponderInstance = null;
|
||||
let currentEventQueue: null | EventQueue = null;
|
||||
let currentEventQueuePriority: EventPriority = ContinuousEvent;
|
||||
let currentTimerIDCounter = 0;
|
||||
let currentDocument: null | Document = null;
|
||||
|
||||
@@ -104,12 +93,29 @@ const eventResponderContext: ReactDOMResponderContext = {
|
||||
): void {
|
||||
validateResponderContext();
|
||||
validateEventValue(eventValue);
|
||||
if (eventPriority < currentEventQueuePriority) {
|
||||
currentEventQueuePriority = eventPriority;
|
||||
switch (eventPriority) {
|
||||
case DiscreteEvent: {
|
||||
flushDiscreteUpdatesIfNeeded(currentTimeStamp);
|
||||
discreteUpdates(() =>
|
||||
executeUserEventHandler(eventListener, eventValue),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case UserBlockingEvent: {
|
||||
if (enableUserBlockingEvents) {
|
||||
runWithPriority(UserBlockingPriority, () =>
|
||||
executeUserEventHandler(eventListener, eventValue),
|
||||
);
|
||||
} else {
|
||||
executeUserEventHandler(eventListener, eventValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContinuousEvent: {
|
||||
executeUserEventHandler(eventListener, eventValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
((currentEventQueue: any): EventQueue).push(
|
||||
createEventQueueItem(eventValue, eventListener),
|
||||
);
|
||||
},
|
||||
isTargetWithinResponder(target: Element | Document): boolean {
|
||||
validateResponderContext();
|
||||
@@ -196,25 +202,6 @@ const eventResponderContext: ReactDOMResponderContext = {
|
||||
}
|
||||
}
|
||||
},
|
||||
hasOwnership(): boolean {
|
||||
validateResponderContext();
|
||||
return globalOwner === currentInstance;
|
||||
},
|
||||
requestGlobalOwnership(): boolean {
|
||||
validateResponderContext();
|
||||
if (globalOwner !== null) {
|
||||
return false;
|
||||
}
|
||||
globalOwner = currentInstance;
|
||||
triggerOwnershipListeners();
|
||||
return true;
|
||||
},
|
||||
releaseOwnership(): boolean {
|
||||
validateResponderContext();
|
||||
return releaseOwnershipForEventResponderInstance(
|
||||
((currentInstance: any): ReactDOMEventResponderInstance),
|
||||
);
|
||||
},
|
||||
setTimeout(func: () => void, delay): number {
|
||||
validateResponderContext();
|
||||
if (currentTimers === null) {
|
||||
@@ -379,16 +366,6 @@ function collectFocusableElements(
|
||||
}
|
||||
}
|
||||
|
||||
function createEventQueueItem(
|
||||
value: any,
|
||||
listener: (val: any) => void,
|
||||
): EventQueueItem {
|
||||
return {
|
||||
value,
|
||||
listener,
|
||||
};
|
||||
}
|
||||
|
||||
function doesFiberHaveResponder(
|
||||
fiber: Fiber,
|
||||
responder: ReactDOMEventResponder,
|
||||
@@ -409,17 +386,6 @@ function getActiveDocument(): Document {
|
||||
return ((currentDocument: any): Document);
|
||||
}
|
||||
|
||||
function releaseOwnershipForEventResponderInstance(
|
||||
eventResponderInstance: ReactDOMEventResponderInstance,
|
||||
): boolean {
|
||||
if (globalOwner === eventResponderInstance) {
|
||||
globalOwner = null;
|
||||
triggerOwnershipListeners();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isFiberHostComponentFocusable(fiber: Fiber): boolean {
|
||||
if (fiber.tag !== HostComponent) {
|
||||
return false;
|
||||
@@ -452,24 +418,22 @@ function processTimers(
|
||||
delay: number,
|
||||
): void {
|
||||
const timersArr = Array.from(timers.values());
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
try {
|
||||
for (let i = 0; i < timersArr.length; i++) {
|
||||
const {instance, func, id, timeStamp} = timersArr[i];
|
||||
currentInstance = instance;
|
||||
currentEventQueue = [];
|
||||
currentTimeStamp = timeStamp + delay;
|
||||
try {
|
||||
func();
|
||||
} finally {
|
||||
activeTimeouts.delete(id);
|
||||
batchedEventUpdates(() => {
|
||||
for (let i = 0; i < timersArr.length; i++) {
|
||||
const {instance, func, id, timeStamp} = timersArr[i];
|
||||
currentInstance = instance;
|
||||
currentTimeStamp = timeStamp + delay;
|
||||
try {
|
||||
func();
|
||||
} finally {
|
||||
activeTimeouts.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
processEventQueue();
|
||||
});
|
||||
} finally {
|
||||
currentTimers = null;
|
||||
currentInstance = null;
|
||||
currentEventQueue = null;
|
||||
currentTimeStamp = 0;
|
||||
}
|
||||
}
|
||||
@@ -508,45 +472,6 @@ function createDOMResponderEvent(
|
||||
};
|
||||
}
|
||||
|
||||
function processEvents(eventQueue: EventQueue): void {
|
||||
for (let i = 0, length = eventQueue.length; i < length; i++) {
|
||||
const {value, listener} = eventQueue[i];
|
||||
const type = typeof value === 'object' && value !== null ? value.type : '';
|
||||
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, value);
|
||||
}
|
||||
}
|
||||
|
||||
function processEventQueue(): void {
|
||||
const eventQueue = ((currentEventQueue: any): EventQueue);
|
||||
if (eventQueue.length === 0) {
|
||||
return;
|
||||
}
|
||||
switch (currentEventQueuePriority) {
|
||||
case DiscreteEvent: {
|
||||
flushDiscreteUpdatesIfNeeded(currentTimeStamp);
|
||||
discreteUpdates(() => {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case UserBlockingEvent: {
|
||||
if (enableUserBlockingEvents) {
|
||||
runWithPriority(
|
||||
UserBlockingPriority,
|
||||
batchedEventUpdates.bind(null, processEvents, eventQueue),
|
||||
);
|
||||
} else {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContinuousEvent: {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function responderEventTypesContainType(
|
||||
eventTypes: Array<string>,
|
||||
type: string,
|
||||
@@ -571,12 +496,6 @@ function validateResponderTargetEventTypes(
|
||||
return false;
|
||||
}
|
||||
|
||||
function validateOwnership(
|
||||
responderInstance: ReactDOMEventResponderInstance,
|
||||
): boolean {
|
||||
return globalOwner === null || globalOwner === responderInstance;
|
||||
}
|
||||
|
||||
function traverseAndHandleEventResponderInstances(
|
||||
topLevelType: string,
|
||||
targetFiber: null | Fiber,
|
||||
@@ -610,22 +529,19 @@ function traverseAndHandleEventResponderInstances(
|
||||
const responderInstances = Array.from(respondersMap.values());
|
||||
for (let i = 0, length = responderInstances.length; i < length; i++) {
|
||||
const responderInstance = responderInstances[i];
|
||||
|
||||
if (validateOwnership(responderInstance)) {
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
if (
|
||||
!visitedResponders.has(responder) &&
|
||||
validateResponderTargetEventTypes(eventType, responder)
|
||||
) {
|
||||
visitedResponders.add(responder);
|
||||
const onEvent = responder.onEvent;
|
||||
if (onEvent !== null) {
|
||||
currentInstance = responderInstance;
|
||||
responderEvent.responderTarget = ((target: any):
|
||||
| Element
|
||||
| Document);
|
||||
onEvent(responderEvent, eventResponderContext, props, state);
|
||||
}
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
if (
|
||||
!visitedResponders.has(responder) &&
|
||||
validateResponderTargetEventTypes(eventType, responder)
|
||||
) {
|
||||
visitedResponders.add(responder);
|
||||
const onEvent = responder.onEvent;
|
||||
if (onEvent !== null) {
|
||||
currentInstance = responderInstance;
|
||||
responderEvent.responderTarget = ((target: any):
|
||||
| Element
|
||||
| Document);
|
||||
onEvent(responderEvent, eventResponderContext, props, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,9 +558,6 @@ function traverseAndHandleEventResponderInstances(
|
||||
|
||||
for (let i = 0; i < responderInstances.length; i++) {
|
||||
const responderInstance = responderInstances[i];
|
||||
if (!validateOwnership(responderInstance)) {
|
||||
continue;
|
||||
}
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
const onRootEvent = responder.onRootEvent;
|
||||
if (onRootEvent !== null) {
|
||||
@@ -656,51 +569,20 @@ function traverseAndHandleEventResponderInstances(
|
||||
}
|
||||
}
|
||||
|
||||
function triggerOwnershipListeners(): void {
|
||||
const listeningInstances = Array.from(ownershipChangeListeners);
|
||||
const previousInstance = currentInstance;
|
||||
const previousEventQueuePriority = currentEventQueuePriority;
|
||||
const previousEventQueue = currentEventQueue;
|
||||
try {
|
||||
for (let i = 0; i < listeningInstances.length; i++) {
|
||||
const instance = listeningInstances[i];
|
||||
const {props, responder, state} = instance;
|
||||
currentInstance = instance;
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentEventQueue = [];
|
||||
const onOwnershipChange = ((responder: any): ReactDOMEventResponder)
|
||||
.onOwnershipChange;
|
||||
if (onOwnershipChange !== null) {
|
||||
onOwnershipChange(eventResponderContext, props, state);
|
||||
}
|
||||
}
|
||||
processEventQueue();
|
||||
} finally {
|
||||
currentInstance = previousInstance;
|
||||
currentEventQueue = previousEventQueue;
|
||||
currentEventQueuePriority = previousEventQueuePriority;
|
||||
}
|
||||
}
|
||||
|
||||
export function mountEventResponder(
|
||||
responder: ReactDOMEventResponder,
|
||||
responderInstance: ReactDOMEventResponderInstance,
|
||||
props: Object,
|
||||
state: Object,
|
||||
) {
|
||||
if (responder.onOwnershipChange !== null) {
|
||||
ownershipChangeListeners.add(responderInstance);
|
||||
}
|
||||
const onMount = responder.onMount;
|
||||
if (onMount !== null) {
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentInstance = responderInstance;
|
||||
currentEventQueue = [];
|
||||
try {
|
||||
onMount(eventResponderContext, props, state);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
onMount(eventResponderContext, props, state);
|
||||
});
|
||||
} finally {
|
||||
currentEventQueue = null;
|
||||
currentInstance = null;
|
||||
currentTimers = null;
|
||||
}
|
||||
@@ -714,22 +596,16 @@ export function unmountEventResponder(
|
||||
const onUnmount = responder.onUnmount;
|
||||
if (onUnmount !== null) {
|
||||
let {props, state} = responderInstance;
|
||||
currentEventQueue = [];
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentInstance = responderInstance;
|
||||
try {
|
||||
onUnmount(eventResponderContext, props, state);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
onUnmount(eventResponderContext, props, state);
|
||||
});
|
||||
} finally {
|
||||
currentEventQueue = null;
|
||||
currentInstance = null;
|
||||
currentTimers = null;
|
||||
}
|
||||
}
|
||||
releaseOwnershipForEventResponderInstance(responderInstance);
|
||||
if (responder.onOwnershipChange !== null) {
|
||||
ownershipChangeListeners.delete(responderInstance);
|
||||
}
|
||||
const rootEventTypesSet = responderInstance.rootEventTypes;
|
||||
if (rootEventTypesSet !== null) {
|
||||
const rootEventTypes = Array.from(rootEventTypesSet);
|
||||
@@ -762,15 +638,11 @@ export function dispatchEventForResponderEventSystem(
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
): void {
|
||||
if (enableFlareAPI) {
|
||||
const previousEventQueue = currentEventQueue;
|
||||
const previousInstance = currentInstance;
|
||||
const previousTimers = currentTimers;
|
||||
const previousTimeStamp = currentTimeStamp;
|
||||
const previousDocument = currentDocument;
|
||||
const previousEventQueuePriority = currentEventQueuePriority;
|
||||
currentTimers = null;
|
||||
currentEventQueue = [];
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
// nodeType 9 is DOCUMENT_NODE
|
||||
currentDocument =
|
||||
(nativeEventTarget: any).nodeType === 9
|
||||
@@ -779,21 +651,20 @@ export function dispatchEventForResponderEventSystem(
|
||||
// We might want to control timeStamp another way here
|
||||
currentTimeStamp = (nativeEvent: any).timeStamp;
|
||||
try {
|
||||
traverseAndHandleEventResponderInstances(
|
||||
topLevelType,
|
||||
targetFiber,
|
||||
nativeEvent,
|
||||
nativeEventTarget,
|
||||
eventSystemFlags,
|
||||
);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
traverseAndHandleEventResponderInstances(
|
||||
topLevelType,
|
||||
targetFiber,
|
||||
nativeEvent,
|
||||
nativeEventTarget,
|
||||
eventSystemFlags,
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
currentTimers = previousTimers;
|
||||
currentInstance = previousInstance;
|
||||
currentEventQueue = previousEventQueue;
|
||||
currentTimeStamp = previousTimeStamp;
|
||||
currentDocument = previousDocument;
|
||||
currentEventQueuePriority = previousEventQueuePriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ function createEventResponder({
|
||||
targetEventTypes,
|
||||
onMount,
|
||||
onUnmount,
|
||||
onOwnershipChange,
|
||||
getInitialState,
|
||||
}) {
|
||||
return React.unstable_createResponder('TestEventResponder', {
|
||||
@@ -36,7 +35,6 @@ function createEventResponder({
|
||||
onRootEvent,
|
||||
onMount,
|
||||
onUnmount,
|
||||
onOwnershipChange,
|
||||
getInitialState,
|
||||
});
|
||||
}
|
||||
@@ -644,37 +642,6 @@ describe('DOMEventResponderSystem', () => {
|
||||
expect(counter).toEqual(5);
|
||||
});
|
||||
|
||||
it('the event responder onOwnershipChange() function should fire', () => {
|
||||
let onOwnershipChangeFired = 0;
|
||||
let ownershipGained = false;
|
||||
const buttonRef = React.createRef();
|
||||
|
||||
const TestResponder = createEventResponder({
|
||||
targetEventTypes: ['click'],
|
||||
onEvent: (event, context, props, state) => {
|
||||
ownershipGained = context.requestGlobalOwnership();
|
||||
},
|
||||
onOwnershipChange: () => {
|
||||
onOwnershipChangeFired++;
|
||||
},
|
||||
});
|
||||
|
||||
const Test = () => {
|
||||
const listener = React.unstable_useResponder(TestResponder, {});
|
||||
return <button ref={buttonRef} listeners={listener} />;
|
||||
};
|
||||
|
||||
ReactDOM.render(<Test />, container);
|
||||
|
||||
// Clicking the button should trigger the event responder onEvent()
|
||||
let buttonElement = buttonRef.current;
|
||||
dispatchClickEvent(buttonElement);
|
||||
jest.runAllTimers();
|
||||
|
||||
expect(ownershipGained).toEqual(true);
|
||||
expect(onOwnershipChangeFired).toEqual(1);
|
||||
});
|
||||
|
||||
it('the event responder root listeners should fire on a root click event', () => {
|
||||
let eventResponderFiredCount = 0;
|
||||
let eventLog = [];
|
||||
|
||||
@@ -50,10 +50,6 @@ elements within the Event Responder.
|
||||
|
||||
Called after an Event Responder in mounted.
|
||||
|
||||
### onOwnershipChange?: (context: ResponderContext, props, state)
|
||||
|
||||
Called when ownership is granted or terminated (either globally or for the responder) for an Event Responder instance.
|
||||
|
||||
### onRootEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
|
||||
|
||||
Called when any of the `rootEventTypes` are dispatched on the root of the app.
|
||||
@@ -101,10 +97,6 @@ context.dispatchEvent('onPress', event, DiscreteEvent);
|
||||
Returns every DOM element that can be focused within the scope of the Event
|
||||
Responder instance.
|
||||
|
||||
### hasOwnership(): boolean
|
||||
|
||||
Returns `true` if the instance has taken ownership of the responder.
|
||||
|
||||
### isTargetWithinNode(target: Element, element: Element): boolean
|
||||
|
||||
Returns `true` if `target` is a child of `element`.
|
||||
@@ -118,21 +110,10 @@ Returns `true` is the target element is within the subtree of the Event Responde
|
||||
Returns `true` is the target element is within the current Event Responder's scope. If the target element
|
||||
is within the scope of the same responder, but owned by another Event Responder instance, this will return `false`.
|
||||
|
||||
### releaseOwnership(): boolean
|
||||
|
||||
Returns `true` if the instance released ownership of the Event Responder instance.
|
||||
|
||||
### removeRootEventTypes(eventTypes: Array<ResponderEventType>)
|
||||
|
||||
Remove the root event types added with `addRootEventTypes`.
|
||||
|
||||
### requestGlobalOwnership(): boolean
|
||||
|
||||
The current Event Responder instance can request global ownership of the event system. When an Event Responder instance
|
||||
has global ownership, only that instance and its responder are active. To release ownership to other event responders,
|
||||
either `releaseOwnership()` must be called or the Event Responder instance that had global ownership must be
|
||||
unmounted. Calling `requestGlobalOwnership` also returns `true`/`false` if the request was successful.
|
||||
|
||||
### setTimeout(func: () => void, delay: number): Symbol
|
||||
|
||||
This can be used to dispatch async events, e.g., those that fire after a delay.
|
||||
|
||||
27
packages/react-events/src/dom/Drag.js
vendored
27
packages/react-events/src/dom/Drag.js
vendored
@@ -39,7 +39,6 @@ type DragState = {|
|
||||
startY: number,
|
||||
x: number,
|
||||
y: number,
|
||||
ownershipClaimed: boolean,
|
||||
|};
|
||||
|
||||
// In the case we don't have PointerEvents (Safari), we listen to touch events
|
||||
@@ -111,7 +110,6 @@ const dragResponderImpl = {
|
||||
startY: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
ownershipClaimed: false,
|
||||
};
|
||||
},
|
||||
onEvent(
|
||||
@@ -182,24 +180,10 @@ const dragResponderImpl = {
|
||||
return;
|
||||
}
|
||||
if (!state.isDragging) {
|
||||
let shouldEnableDragging = true;
|
||||
|
||||
if (props.shouldClaimOwnership && props.shouldClaimOwnership()) {
|
||||
shouldEnableDragging = context.requestGlobalOwnership();
|
||||
if (shouldEnableDragging) {
|
||||
state.ownershipClaimed = true;
|
||||
}
|
||||
}
|
||||
if (shouldEnableDragging) {
|
||||
state.isDragging = true;
|
||||
const onDragChange = props.onDragChange;
|
||||
if (isFunction(onDragChange)) {
|
||||
context.dispatchEvent(true, onDragChange, UserBlockingEvent);
|
||||
}
|
||||
} else {
|
||||
state.dragTarget = null;
|
||||
state.isPointerDown = false;
|
||||
context.removeRootEventTypes(rootEventTypes);
|
||||
state.isDragging = true;
|
||||
const onDragChange = props.onDragChange;
|
||||
if (isFunction(onDragChange)) {
|
||||
context.dispatchEvent(true, onDragChange, UserBlockingEvent);
|
||||
}
|
||||
} else {
|
||||
const onDragMove = props.onDragMove;
|
||||
@@ -228,9 +212,6 @@ const dragResponderImpl = {
|
||||
case 'mouseup':
|
||||
case 'pointerup': {
|
||||
if (state.isDragging) {
|
||||
if (state.ownershipClaimed) {
|
||||
context.releaseOwnership();
|
||||
}
|
||||
const onDragEnd = props.onDragEnd;
|
||||
if (isFunction(onDragEnd)) {
|
||||
dispatchDragEvent(
|
||||
|
||||
14
packages/react-events/src/dom/Focus.js
vendored
14
packages/react-events/src/dom/Focus.js
vendored
@@ -341,13 +341,6 @@ const focusResponderImpl = {
|
||||
) {
|
||||
unmountFocusResponder(context, props, state);
|
||||
},
|
||||
onOwnershipChange(
|
||||
context: ReactDOMResponderContext,
|
||||
props: FocusProps,
|
||||
state: FocusState,
|
||||
) {
|
||||
unmountFocusResponder(context, props, state);
|
||||
},
|
||||
};
|
||||
|
||||
export const FocusResponder = React.unstable_createResponder(
|
||||
@@ -485,13 +478,6 @@ const focusWithinResponderImpl = {
|
||||
) {
|
||||
unmountFocusWithinResponder(context, props, state);
|
||||
},
|
||||
onOwnershipChange(
|
||||
context: ReactDOMResponderContext,
|
||||
props: FocusWithinProps,
|
||||
state: FocusState,
|
||||
) {
|
||||
unmountFocusWithinResponder(context, props, state);
|
||||
},
|
||||
};
|
||||
|
||||
export const FocusWithinResponder = React.unstable_createResponder(
|
||||
|
||||
2
packages/react-events/src/dom/Hover.js
vendored
2
packages/react-events/src/dom/Hover.js
vendored
@@ -260,7 +260,6 @@ const hoverResponderImpl = {
|
||||
}
|
||||
},
|
||||
onUnmount: unmountResponder,
|
||||
onOwnershipChange: unmountResponder,
|
||||
};
|
||||
|
||||
const hoverResponderFallbackImpl = {
|
||||
@@ -335,7 +334,6 @@ const hoverResponderFallbackImpl = {
|
||||
}
|
||||
},
|
||||
onUnmount: unmountResponder,
|
||||
onOwnershipChange: unmountResponder,
|
||||
};
|
||||
|
||||
export const HoverResponder = React.unstable_createResponder(
|
||||
|
||||
7
packages/react-events/src/dom/Press.js
vendored
7
packages/react-events/src/dom/Press.js
vendored
@@ -841,13 +841,6 @@ const pressResponderImpl = {
|
||||
) {
|
||||
unmountResponder(context, props, state);
|
||||
},
|
||||
onOwnershipChange(
|
||||
context: ReactDOMResponderContext,
|
||||
props: PressProps,
|
||||
state: PressState,
|
||||
) {
|
||||
unmountResponder(context, props, state);
|
||||
},
|
||||
};
|
||||
|
||||
export const PressResponder = React.unstable_createResponder(
|
||||
|
||||
7
packages/react-events/src/dom/Scroll.js
vendored
7
packages/react-events/src/dom/Scroll.js
vendored
@@ -303,13 +303,6 @@ const scrollResponderImpl = {
|
||||
) {
|
||||
// TODO
|
||||
},
|
||||
onOwnershipChange(
|
||||
context: ReactDOMResponderContext,
|
||||
props: ScrollProps,
|
||||
state: ScrollState,
|
||||
) {
|
||||
// TODO
|
||||
},
|
||||
};
|
||||
|
||||
export const ScrollResponder = React.unstable_createResponder(
|
||||
|
||||
31
packages/react-events/src/dom/Swipe.js
vendored
31
packages/react-events/src/dom/Swipe.js
vendored
@@ -101,7 +101,6 @@ type SwipeState = {
|
||||
swipeTarget: null | Element | Document,
|
||||
x: number,
|
||||
y: number,
|
||||
ownershipClaimed: boolean,
|
||||
};
|
||||
|
||||
const swipeResponderImpl = {
|
||||
@@ -117,7 +116,6 @@ const swipeResponderImpl = {
|
||||
swipeTarget: null,
|
||||
x: 0,
|
||||
y: 0,
|
||||
ownershipClaimed: false,
|
||||
};
|
||||
},
|
||||
onEvent(
|
||||
@@ -141,25 +139,13 @@ const swipeResponderImpl = {
|
||||
const x = (obj: any).screenX;
|
||||
const y = (obj: any).screenY;
|
||||
|
||||
let shouldEnableSwiping = true;
|
||||
|
||||
if (props.shouldClaimOwnership && props.shouldClaimOwnership()) {
|
||||
shouldEnableSwiping = context.requestGlobalOwnership();
|
||||
if (shouldEnableSwiping) {
|
||||
state.ownershipClaimed = true;
|
||||
}
|
||||
}
|
||||
if (shouldEnableSwiping) {
|
||||
state.isSwiping = true;
|
||||
state.startX = x;
|
||||
state.startY = y;
|
||||
state.x = x;
|
||||
state.y = y;
|
||||
state.swipeTarget = target;
|
||||
context.addRootEventTypes(rootEventTypes);
|
||||
} else {
|
||||
state.touchId = null;
|
||||
}
|
||||
state.isSwiping = true;
|
||||
state.startX = x;
|
||||
state.startY = y;
|
||||
state.x = x;
|
||||
state.y = y;
|
||||
state.swipeTarget = target;
|
||||
context.addRootEventTypes(rootEventTypes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -238,9 +224,6 @@ const swipeResponderImpl = {
|
||||
if (state.x === state.startX && state.y === state.startY) {
|
||||
return;
|
||||
}
|
||||
if (state.ownershipClaimed) {
|
||||
context.releaseOwnership();
|
||||
}
|
||||
const direction = state.direction;
|
||||
const lastDirection = state.lastDirection;
|
||||
if (direction !== lastDirection) {
|
||||
|
||||
@@ -141,61 +141,6 @@ describe('Drag event responder', () => {
|
||||
expect(events).toEqual(['dragstart', 'dragend']);
|
||||
});
|
||||
|
||||
it('should support onDragStart and onDragEnd with ownership', () => {
|
||||
let divRef = React.createRef();
|
||||
let events = [];
|
||||
|
||||
function handleDragStart() {
|
||||
events.push('dragstart');
|
||||
}
|
||||
|
||||
function handleDragEnd() {
|
||||
events.push('dragend');
|
||||
}
|
||||
|
||||
function Component() {
|
||||
const listener = useDragResponder({
|
||||
onDragStart: handleDragStart,
|
||||
onDragEnd: handleDragEnd,
|
||||
shouldClaimOwnership: () => true,
|
||||
});
|
||||
return (
|
||||
<div ref={divRef} listeners={listener}>
|
||||
Drag me!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<Component />, container);
|
||||
|
||||
const mouseOverEvent = document.createEvent('MouseEvents');
|
||||
mouseOverEvent.initEvent('mousedown', true, true);
|
||||
divRef.current.dispatchEvent(mouseOverEvent);
|
||||
|
||||
const mouseMoveEvent = document.createEvent('MouseEvents');
|
||||
for (let index = 0; index <= 20; index++) {
|
||||
mouseMoveEvent.initMouseEvent(
|
||||
'mousemove',
|
||||
true,
|
||||
true,
|
||||
window,
|
||||
1,
|
||||
index,
|
||||
index,
|
||||
50,
|
||||
50,
|
||||
);
|
||||
divRef.current.dispatchEvent(mouseMoveEvent);
|
||||
}
|
||||
divRef.current.dispatchEvent(mouseMoveEvent);
|
||||
|
||||
const mouseUpEvent = document.createEvent('MouseEvents');
|
||||
mouseUpEvent.initEvent('mouseup', true, true);
|
||||
divRef.current.dispatchEvent(mouseUpEvent);
|
||||
|
||||
expect(events).toEqual(['dragstart', 'dragend']);
|
||||
});
|
||||
|
||||
it('should support onDragMove', () => {
|
||||
let divRef = React.createRef();
|
||||
let events = [];
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
batchedEventUpdates,
|
||||
discreteUpdates,
|
||||
flushDiscreteUpdatesIfNeeded,
|
||||
executeUserEventHandler,
|
||||
} from 'legacy-events/ReactGenericBatching';
|
||||
import type {
|
||||
ReactEventResponder,
|
||||
@@ -30,7 +31,6 @@ import {
|
||||
UserBlockingEvent,
|
||||
DiscreteEvent,
|
||||
} from './ReactNativeTypes';
|
||||
import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils';
|
||||
import {enableUserBlockingEvents} from 'shared/ReactFeatureFlags';
|
||||
import warning from 'shared/warning';
|
||||
import invariant from 'shared/invariant';
|
||||
@@ -43,12 +43,6 @@ const {
|
||||
unstable_runWithPriority: runWithPriority,
|
||||
} = Scheduler;
|
||||
|
||||
type EventQueueItem = {|
|
||||
listener: (val: any) => void,
|
||||
value: any,
|
||||
|};
|
||||
type EventQueue = Array<EventQueueItem>;
|
||||
|
||||
type ResponderTimeout = {|
|
||||
id: TimeoutID,
|
||||
timers: Map<number, ResponderTimer>,
|
||||
@@ -78,17 +72,10 @@ const rootEventTypesToEventResponderInstances: Map<
|
||||
string,
|
||||
Set<ReactNativeEventResponderInstance>,
|
||||
> = new Map();
|
||||
const ownershipChangeListeners: Set<
|
||||
ReactNativeEventResponderInstance,
|
||||
> = new Set();
|
||||
|
||||
let globalOwner = null;
|
||||
|
||||
let currentTimeStamp = 0;
|
||||
let currentTimers = new Map();
|
||||
let currentInstance: null | ReactNativeEventResponderInstance = null;
|
||||
let currentEventQueue: null | EventQueue = null;
|
||||
let currentEventQueuePriority: EventPriority = ContinuousEvent;
|
||||
let currentTimerIDCounter = 0;
|
||||
|
||||
const eventResponderContext: ReactNativeResponderContext = {
|
||||
@@ -99,12 +86,29 @@ const eventResponderContext: ReactNativeResponderContext = {
|
||||
): void {
|
||||
validateResponderContext();
|
||||
validateEventValue(eventValue);
|
||||
if (eventPriority < currentEventQueuePriority) {
|
||||
currentEventQueuePriority = eventPriority;
|
||||
switch (eventPriority) {
|
||||
case DiscreteEvent: {
|
||||
flushDiscreteUpdatesIfNeeded(currentTimeStamp);
|
||||
discreteUpdates(() =>
|
||||
executeUserEventHandler(eventListener, eventValue),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case UserBlockingEvent: {
|
||||
if (enableUserBlockingEvents) {
|
||||
runWithPriority(UserBlockingPriority, () =>
|
||||
executeUserEventHandler(eventListener, eventValue),
|
||||
);
|
||||
} else {
|
||||
executeUserEventHandler(eventListener, eventValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContinuousEvent: {
|
||||
executeUserEventHandler(eventListener, eventValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
((currentEventQueue: any): EventQueue).push(
|
||||
createEventQueueItem(eventValue, eventListener),
|
||||
);
|
||||
},
|
||||
isTargetWithinNode(
|
||||
childTarget: ReactNativeEventTarget,
|
||||
@@ -215,16 +219,6 @@ const eventResponderContext: ReactNativeResponderContext = {
|
||||
},
|
||||
};
|
||||
|
||||
function createEventQueueItem(
|
||||
value: any,
|
||||
listener: (val: any) => void,
|
||||
): EventQueueItem {
|
||||
return {
|
||||
value,
|
||||
listener,
|
||||
};
|
||||
}
|
||||
|
||||
function validateEventValue(eventValue: any): void {
|
||||
if (typeof eventValue === 'object' && eventValue !== null) {
|
||||
const {target, type, timeStamp} = eventValue;
|
||||
@@ -290,24 +284,22 @@ function processTimers(
|
||||
delay: number,
|
||||
): void {
|
||||
const timersArr = Array.from(timers.values());
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
try {
|
||||
for (let i = 0; i < timersArr.length; i++) {
|
||||
const {instance, func, id, timeStamp} = timersArr[i];
|
||||
currentInstance = instance;
|
||||
currentEventQueue = [];
|
||||
currentTimeStamp = timeStamp + delay;
|
||||
try {
|
||||
func();
|
||||
} finally {
|
||||
activeTimeouts.delete(id);
|
||||
batchedEventUpdates(() => {
|
||||
for (let i = 0; i < timersArr.length; i++) {
|
||||
const {instance, func, id, timeStamp} = timersArr[i];
|
||||
currentInstance = instance;
|
||||
currentTimeStamp = timeStamp + delay;
|
||||
try {
|
||||
func();
|
||||
} finally {
|
||||
activeTimeouts.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
processEventQueue();
|
||||
});
|
||||
} finally {
|
||||
currentTimers = null;
|
||||
currentInstance = null;
|
||||
currentEventQueue = null;
|
||||
currentTimeStamp = 0;
|
||||
}
|
||||
}
|
||||
@@ -327,68 +319,12 @@ function createFabricResponderEvent(
|
||||
|
||||
function validateResponderContext(): void {
|
||||
invariant(
|
||||
currentEventQueue && currentInstance,
|
||||
currentInstance,
|
||||
'An event responder context was used outside of an event cycle. ' +
|
||||
'Use context.setTimeout() to use asynchronous responder context outside of event cycle .',
|
||||
);
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function processEventQueue(): void {
|
||||
const eventQueue = ((currentEventQueue: any): EventQueue);
|
||||
if (eventQueue.length === 0) {
|
||||
return;
|
||||
}
|
||||
switch (currentEventQueuePriority) {
|
||||
case DiscreteEvent: {
|
||||
flushDiscreteUpdatesIfNeeded(currentTimeStamp);
|
||||
discreteUpdates(() => {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case UserBlockingEvent: {
|
||||
if (enableUserBlockingEvents) {
|
||||
runWithPriority(
|
||||
UserBlockingPriority,
|
||||
batchedEventUpdates.bind(null, processEvents, eventQueue),
|
||||
);
|
||||
} else {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ContinuousEvent: {
|
||||
batchedEventUpdates(processEvents, eventQueue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function releaseOwnershipForEventResponderInstance(
|
||||
eventResponderInstance: ReactNativeEventResponderInstance,
|
||||
): boolean {
|
||||
if (globalOwner === eventResponderInstance) {
|
||||
globalOwner = null;
|
||||
triggerOwnershipListeners();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function processEvents(eventQueue: EventQueue): void {
|
||||
for (let i = 0, length = eventQueue.length; i < length; i++) {
|
||||
const {value, listener} = eventQueue[i];
|
||||
const type = typeof value === 'object' && value !== null ? value.type : '';
|
||||
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, value);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function responderEventTypesContainType(
|
||||
@@ -415,12 +351,6 @@ function validateResponderTargetEventTypes(
|
||||
return false;
|
||||
}
|
||||
|
||||
function validateOwnership(
|
||||
responderInstance: ReactNativeEventResponderInstance,
|
||||
): boolean {
|
||||
return globalOwner === null || globalOwner === responderInstance;
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function traverseAndHandleEventResponderInstances(
|
||||
@@ -449,20 +379,17 @@ function traverseAndHandleEventResponderInstances(
|
||||
const responderInstances = Array.from(respondersMap.values());
|
||||
for (let i = 0, length = responderInstances.length; i < length; i++) {
|
||||
const responderInstance = responderInstances[i];
|
||||
|
||||
if (validateOwnership(responderInstance)) {
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
if (
|
||||
!visitedResponders.has(responder) &&
|
||||
validateResponderTargetEventTypes(eventType, responder)
|
||||
) {
|
||||
const onEvent = responder.onEvent;
|
||||
visitedResponders.add(responder);
|
||||
if (onEvent !== null) {
|
||||
currentInstance = responderInstance;
|
||||
responderEvent.responderTarget = ((target: any): ReactNativeEventTarget);
|
||||
onEvent(responderEvent, eventResponderContext, props, state);
|
||||
}
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
if (
|
||||
!visitedResponders.has(responder) &&
|
||||
validateResponderTargetEventTypes(eventType, responder)
|
||||
) {
|
||||
const onEvent = responder.onEvent;
|
||||
visitedResponders.add(responder);
|
||||
if (onEvent !== null) {
|
||||
currentInstance = responderInstance;
|
||||
responderEvent.responderTarget = ((target: any): ReactNativeEventTarget);
|
||||
onEvent(responderEvent, eventResponderContext, props, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,9 +406,6 @@ function traverseAndHandleEventResponderInstances(
|
||||
|
||||
for (let i = 0; i < responderInstances.length; i++) {
|
||||
const responderInstance = responderInstances[i];
|
||||
if (!validateOwnership(responderInstance)) {
|
||||
continue;
|
||||
}
|
||||
const {props, responder, state, target} = responderInstance;
|
||||
const onRootEvent = responder.onRootEvent;
|
||||
if (onRootEvent !== null) {
|
||||
@@ -500,57 +424,24 @@ export function dispatchEventForResponderEventSystem(
|
||||
targetFiber: null | Fiber,
|
||||
nativeEvent: ReactFaricEvent,
|
||||
): void {
|
||||
const previousEventQueue = currentEventQueue;
|
||||
const previousInstance = currentInstance;
|
||||
const previousTimers = currentTimers;
|
||||
const previousTimeStamp = currentTimeStamp;
|
||||
const previousEventQueuePriority = currentEventQueuePriority;
|
||||
currentTimers = null;
|
||||
currentEventQueue = [];
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
// We might want to control timeStamp another way here
|
||||
currentTimeStamp = Date.now();
|
||||
try {
|
||||
traverseAndHandleEventResponderInstances(
|
||||
topLevelType,
|
||||
targetFiber,
|
||||
nativeEvent,
|
||||
);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
traverseAndHandleEventResponderInstances(
|
||||
topLevelType,
|
||||
targetFiber,
|
||||
nativeEvent,
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
currentTimers = previousTimers;
|
||||
currentInstance = previousInstance;
|
||||
currentEventQueue = previousEventQueue;
|
||||
currentTimeStamp = previousTimeStamp;
|
||||
currentEventQueuePriority = previousEventQueuePriority;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this function is almost an exact copy of the DOM version, we should
|
||||
// somehow share the logic
|
||||
function triggerOwnershipListeners(): void {
|
||||
const listeningInstances = Array.from(ownershipChangeListeners);
|
||||
const previousInstance = currentInstance;
|
||||
const previousEventQueuePriority = currentEventQueuePriority;
|
||||
const previousEventQueue = currentEventQueue;
|
||||
try {
|
||||
for (let i = 0; i < listeningInstances.length; i++) {
|
||||
const instance = listeningInstances[i];
|
||||
const {props, responder, state} = instance;
|
||||
currentInstance = instance;
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentEventQueue = [];
|
||||
const onOwnershipChange = ((responder: any): ReactNativeEventResponder)
|
||||
.onOwnershipChange;
|
||||
if (onOwnershipChange !== null) {
|
||||
onOwnershipChange(eventResponderContext, props, state);
|
||||
}
|
||||
}
|
||||
processEventQueue();
|
||||
} finally {
|
||||
currentInstance = previousInstance;
|
||||
currentEventQueue = previousEventQueue;
|
||||
currentEventQueuePriority = previousEventQueuePriority;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,19 +453,14 @@ export function mountEventResponder(
|
||||
props: Object,
|
||||
state: Object,
|
||||
) {
|
||||
if (responder.onOwnershipChange !== null) {
|
||||
ownershipChangeListeners.add(responderInstance);
|
||||
}
|
||||
const onMount = responder.onMount;
|
||||
if (onMount !== null) {
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentInstance = responderInstance;
|
||||
currentEventQueue = [];
|
||||
try {
|
||||
onMount(eventResponderContext, props, state);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
onMount(eventResponderContext, props, state);
|
||||
});
|
||||
} finally {
|
||||
currentEventQueue = null;
|
||||
currentInstance = null;
|
||||
currentTimers = null;
|
||||
}
|
||||
@@ -590,22 +476,16 @@ export function unmountEventResponder(
|
||||
const onUnmount = responder.onUnmount;
|
||||
if (onUnmount !== null) {
|
||||
let {props, state} = responderInstance;
|
||||
currentEventQueue = [];
|
||||
currentEventQueuePriority = ContinuousEvent;
|
||||
currentInstance = responderInstance;
|
||||
try {
|
||||
onUnmount(eventResponderContext, props, state);
|
||||
processEventQueue();
|
||||
batchedEventUpdates(() => {
|
||||
onUnmount(eventResponderContext, props, state);
|
||||
});
|
||||
} finally {
|
||||
currentEventQueue = null;
|
||||
currentInstance = null;
|
||||
currentTimers = null;
|
||||
}
|
||||
}
|
||||
releaseOwnershipForEventResponderInstance(responderInstance);
|
||||
if (responder.onOwnershipChange !== null) {
|
||||
ownershipChangeListeners.delete(responderInstance);
|
||||
}
|
||||
const rootEventTypesSet = responderInstance.rootEventTypes;
|
||||
if (rootEventTypesSet !== null) {
|
||||
const rootEventTypes = Array.from(rootEventTypesSet);
|
||||
|
||||
@@ -64,9 +64,6 @@ export type ReactDOMResponderContext = {
|
||||
isTargetWithinResponderScope: (Element | Document) => boolean,
|
||||
addRootEventTypes: (rootEventTypes: Array<string>) => void,
|
||||
removeRootEventTypes: (rootEventTypes: Array<string>) => void,
|
||||
hasOwnership: () => boolean,
|
||||
requestGlobalOwnership: () => boolean,
|
||||
releaseOwnership: () => boolean,
|
||||
setTimeout: (func: () => void, timeout: number) => number,
|
||||
clearTimeout: (timerId: number) => void,
|
||||
getFocusableElementsInScope(deep: boolean): Array<HTMLElement>,
|
||||
|
||||
@@ -107,9 +107,6 @@ export type ReactEventResponder<E, C> = {
|
||||
| ((event: E, context: C, props: Object, state: Object) => void),
|
||||
onMount: null | ((context: C, props: Object, state: Object) => void),
|
||||
onUnmount: null | ((context: C, props: Object, state: Object) => void),
|
||||
onOwnershipChange:
|
||||
| null
|
||||
| ((context: C, props: Object, state: Object) => void),
|
||||
};
|
||||
|
||||
export type EventPriority = 0 | 1 | 2;
|
||||
|
||||
@@ -19,7 +19,6 @@ export default function createEventResponder<E, C>(
|
||||
onEvent,
|
||||
onMount,
|
||||
onUnmount,
|
||||
onOwnershipChange,
|
||||
onRootEvent,
|
||||
rootEventTypes,
|
||||
targetEventTypes,
|
||||
@@ -30,7 +29,6 @@ export default function createEventResponder<E, C>(
|
||||
getInitialState: getInitialState || null,
|
||||
onEvent: onEvent || null,
|
||||
onMount: onMount || null,
|
||||
onOwnershipChange: onOwnershipChange || null,
|
||||
onRootEvent: onRootEvent || null,
|
||||
onUnmount: onUnmount || null,
|
||||
rootEventTypes: rootEventTypes || null,
|
||||
|
||||
Reference in New Issue
Block a user