Skip to content

Commit

Permalink
Event API: Add responder allowMultipleHostChildren flag (#15646)
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm authored May 16, 2019
1 parent 95e06ac commit 1160b37
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 243 deletions.
113 changes: 34 additions & 79 deletions packages/react-dom/src/events/DOMEventResponderSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
EventComponent,
EventTarget as EventTargetWorkTag,
HostComponent,
SuspenseComponent,
Fragment,
} from 'shared/ReactWorkTags';
import type {
ReactEventResponder,
Expand All @@ -34,6 +32,10 @@ import warning from 'shared/warning';
import {enableEventAPI} from 'shared/ReactFeatureFlags';
import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils';
import invariant from 'shared/invariant';
import {
isFiberSuspenseAndTimedOut,
getSuspenseFallbackChild,
} from 'react-reconciler/src/ReactFiberEvents';

import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';

Expand Down Expand Up @@ -351,50 +353,11 @@ const eventResponderContext: ReactResponderContext = {
validateResponderContext();
const focusableElements = [];
const eventComponentInstance = ((currentInstance: any): ReactEventComponentInstance);
let node = ((eventComponentInstance.currentFiber: any): Fiber).child;

while (node !== null) {
if (node.tag === SuspenseComponent) {
const suspendedChild = isFiberSuspenseAndTimedOut(node)
? getSuspenseFallbackChild(node)
: getSuspenseChild(node);
if (suspendedChild !== null) {
node = suspendedChild;
continue;
}
} else {
if (isFiberHostComponentFocusable(node)) {
focusableElements.push(node.stateNode);
} else {
const child = node.child;
const child = ((eventComponentInstance.currentFiber: any): Fiber).child;

if (child !== null) {
node = child;
continue;
}
}
}
const sibling = node.sibling;

if (sibling !== null) {
node = sibling;
continue;
}
let parent;
if (isFiberSuspenseChild(node)) {
parent = getSuspenseFiberFromChild(node);
} else {
parent = node.return;
if (parent === null) {
break;
}
}
if (parent.stateNode === currentInstance) {
break;
}
node = parent.sibling;
if (child !== null) {
collectFocusableElements(child, focusableElements);
}

return focusableElements;
},
getActiveDocument,
Expand Down Expand Up @@ -455,6 +418,33 @@ const eventResponderContext: ReactResponderContext = {
},
};

function collectFocusableElements(
node: Fiber,
focusableElements: Array<HTMLElement>,
): void {
if (isFiberSuspenseAndTimedOut(node)) {
const fallbackChild = getSuspenseFallbackChild(node);
if (fallbackChild !== null) {
collectFocusableElements(fallbackChild, focusableElements);
}
} else {
if (isFiberHostComponentFocusable(node)) {
focusableElements.push(node.stateNode);
} else {
const child = node.child;

if (child !== null) {
collectFocusableElements(child, focusableElements);
}
}
}
const sibling = node.sibling;

if (sibling !== null) {
collectFocusableElements(sibling, focusableElements);
}
}

function isTargetWithinEventComponent(target: Element | Document): boolean {
validateResponderContext();
if (target != null) {
Expand Down Expand Up @@ -605,41 +595,6 @@ export function processEventQueue(): void {
}
}

function isFiberSuspenseAndTimedOut(fiber: Fiber): boolean {
return fiber.tag === SuspenseComponent && fiber.memoizedState !== null;
}

function isFiberSuspenseChild(fiber: Fiber | null): boolean {
if (fiber === null) {
return false;
}
const parent = fiber.return;
if (parent !== null && parent.tag === Fragment) {
const grandParent = parent.return;

if (
grandParent !== null &&
grandParent.tag === SuspenseComponent &&
grandParent.stateNode !== null
) {
return true;
}
}
return false;
}

function getSuspenseFiberFromChild(fiber: Fiber): Fiber {
return ((((fiber.return: any): Fiber).return: any): Fiber);
}

function getSuspenseFallbackChild(fiber: Fiber): Fiber | null {
return ((((fiber.child: any): Fiber).sibling: any): Fiber).child;
}

function getSuspenseChild(fiber: Fiber): Fiber | null {
return (((fiber.child: any): Fiber): Fiber).child;
}

function getTargetEventTypesSet(
eventTypes: Array<ReactEventResponderEventType>,
): Set<string> {
Expand Down
Loading

0 comments on commit 1160b37

Please sign in to comment.