diff --git a/packages/react-interactions/accessibility/README.md b/packages/react-interactions/accessibility/README.md
index 582820eec122a..844af1957f141 100644
--- a/packages/react-interactions/accessibility/README.md
+++ b/packages/react-interactions/accessibility/README.md
@@ -14,74 +14,11 @@ can be found [here](./docs).
Note: React Scopes require the internal React flag `enableScopeAPI`.
-When creating a scope, a query function is required. The query function is used
-when collecting host nodes that match the criteria of the query function.
-
-```jsx
-// This query function only matches host nodes that have the type of "div"
-const queryFunction = (type: string, props: Object): boolean => {
- if (type === 'div') {
- return true;
- }
- return false;
-};
-
-// Create the scope with the queryFunction above
-const DivOnlyScope = React.unstable_createScope(queryFunction);
-
-// We can now use this in our components. We need to attach
-// a ref so we can get the matching host nodes.
-function MyComponent(props) {
- const divOnlyScope = useRef(null);
- return (
-
-
DIV 1
-
DIV 2
-
DIV 3
-
- );
-}
-
-// Using the ref, we can get the host nodes via getAllNodes()
-const divs = divOnlyScope.current.getAllNodes();
-
-// [
DIV 1
,
DIV 2
,
DIV 3
]
-console.log(divs);
-```
-
## React Scope Interface
Scopes require a `ref` to access the internal interface of a particular scope.
The internal interface (`ReactScopeInterface`) exposes the following scope API:
-### getChildren: () => null | Array
-
-Returns an array of all child `ReactScopeInterface` nodes that are
-of scopes of the same type. Returns `null` if there are no child scope nodes.
-
-### getChildrenFromRoot: () => null | Array
-
-Similar to `getChildren`, except this applies the same traversal from the root of the
-React internal tree instead of from the scope node position.
-
-### getParent: () => null | ReactScopeInterface
-
-Returns the parent `ReactScopeInterface` of the scope node or `null` if none exists.
-
-### getProps: () => Object
-
-Returns the current `props` object of the scope node.
-
-### getAllNodes: () => null | Array
-
-Returns an array of all child host nodes that successfully match when queried using the
-query function passed to the scope. Returns `null` if there are no matching host nodes.
-
-### getFirstNode: () => null | HTMLElement
-
-Returns the first child host node that successfully matches when queried using the
-query function passed to the scope. Returns `null` if there is no matching host node.
-
### containsNode: (node: HTMLElement) => boolean
Returns `true` or `false` depending on if the given `HTMLElement` is a descendant
diff --git a/packages/react-interactions/accessibility/docs/TabbableScopeQuery.md b/packages/react-interactions/accessibility/docs/TabbableScopeQuery.md
index 0c942ec4281bb..47fc5dff35503 100644
--- a/packages/react-interactions/accessibility/docs/TabbableScopeQuery.md
+++ b/packages/react-interactions/accessibility/docs/TabbableScopeQuery.md
@@ -15,7 +15,7 @@ function FocusableNodeCollector(props) {
const scope = scopeRef.current;
if (scope) {
- const tabFocusableNodes = scope.queryAllNodes(tabbableScopeQuery);
+ const tabFocusableNodes = scope.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
if (tabFocusableNodes && props.onFocusableNodes) {
props.onFocusableNodes(tabFocusableNodes);
}
diff --git a/packages/react-interactions/accessibility/src/FocusContain.js b/packages/react-interactions/accessibility/src/FocusContain.js
index 78316af93907d..21c0b3cc894f3 100644
--- a/packages/react-interactions/accessibility/src/FocusContain.js
+++ b/packages/react-interactions/accessibility/src/FocusContain.js
@@ -71,7 +71,7 @@ export default function FocusContain({
disabled !== true &&
!scope.containsNode(document.activeElement)
) {
- const fistElem = scope.queryFirstNode(scopeQuery);
+ const fistElem = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
if (fistElem !== null) {
fistElem.focus();
}
diff --git a/packages/react-interactions/accessibility/src/FocusGroup.js b/packages/react-interactions/accessibility/src/FocusGroup.js
index ad677b9d6a111..8ac102fc07d6a 100644
--- a/packages/react-interactions/accessibility/src/FocusGroup.js
+++ b/packages/react-interactions/accessibility/src/FocusGroup.js
@@ -35,7 +35,7 @@ function focusGroupItem(
cell: ReactScopeMethods,
event: KeyboardEvent,
): void {
- const firstScopedNode = cell.queryFirstNode(scopeQuery);
+ const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
if (firstScopedNode !== null) {
firstScopedNode.focus();
event.preventDefault();
@@ -46,7 +46,7 @@ function getPreviousGroupItem(
group: ReactScopeMethods,
currentItem: ReactScopeMethods,
): null | ReactScopeMethods {
- const items = group.getChildren();
+ const items = group.DO_NOT_USE_getChildren();
if (items !== null) {
const currentItemIndex = items.indexOf(currentItem);
const wrap = getGroupProps(currentItem).wrap;
@@ -63,7 +63,7 @@ function getNextGroupItem(
group: ReactScopeMethods,
currentItem: ReactScopeMethods,
): null | ReactScopeMethods {
- const items = group.getChildren();
+ const items = group.DO_NOT_USE_getChildren();
if (items !== null) {
const currentItemIndex = items.indexOf(currentItem);
const wrap = getGroupProps(currentItem).wrap;
@@ -78,9 +78,9 @@ function getNextGroupItem(
}
function getGroupProps(currentCell: ReactScopeMethods): Object {
- const group = currentCell.getParent();
+ const group = currentCell.DO_NOT_USE_getParent();
if (group !== null) {
- const groupProps = group.getProps();
+ const groupProps = group.DO_NOT_USE_getProps();
if (groupProps && groupProps.type === 'group') {
return groupProps;
}
@@ -125,8 +125,8 @@ export function createFocusGroup(
onKeyDown(event: KeyboardEvent): void {
const currentItem = scopeRef.current;
if (currentItem !== null) {
- const group = currentItem.getParent();
- const groupProps = group && group.getProps();
+ const group = currentItem.DO_NOT_USE_getParent();
+ const groupProps = group && group.DO_NOT_USE_getProps();
if (group !== null && groupProps.type === 'group') {
const portrait = groupProps.portrait;
const key = event.key;
@@ -134,10 +134,12 @@ export function createFocusGroup(
if (key === 'Tab') {
const tabScopeQuery = getGroupProps(currentItem).tabScopeQuery;
if (tabScopeQuery) {
- const groupScope = currentItem.getParent();
+ const groupScope = currentItem.DO_NOT_USE_getParent();
if (groupScope) {
const activeNode = document.activeElement;
- const nodes = groupScope.queryAllNodes(tabScopeQuery);
+ const nodes = groupScope.DO_NOT_USE_queryAllNodes(
+ tabScopeQuery,
+ );
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node !== activeNode) {
diff --git a/packages/react-interactions/accessibility/src/FocusManager.js b/packages/react-interactions/accessibility/src/FocusManager.js
index 861f91b594bf0..1fc4fd37e0360 100644
--- a/packages/react-interactions/accessibility/src/FocusManager.js
+++ b/packages/react-interactions/accessibility/src/FocusManager.js
@@ -16,7 +16,7 @@ export function focusFirst(
scopeQuery: (type: string | Object, props: Object) => boolean,
scope: ReactScopeMethods,
): void {
- const firstNode = scope.queryFirstNode(scopeQuery);
+ const firstNode = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
if (firstNode) {
focusElem(firstNode);
}
@@ -101,7 +101,7 @@ export function focusPrevious(
export function getNextScope(
scope: ReactScopeMethods,
): null | ReactScopeMethods {
- const allScopes = scope.getChildrenFromRoot();
+ const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
if (allScopes === null) {
return null;
}
@@ -115,7 +115,7 @@ export function getNextScope(
export function getPreviousScope(
scope: ReactScopeMethods,
): null | ReactScopeMethods {
- const allScopes = scope.getChildrenFromRoot();
+ const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
if (allScopes === null) {
return null;
}
diff --git a/packages/react-interactions/accessibility/src/FocusTable.js b/packages/react-interactions/accessibility/src/FocusTable.js
index aea24b80ed1ab..bd05855bc7526 100644
--- a/packages/react-interactions/accessibility/src/FocusTable.js
+++ b/packages/react-interactions/accessibility/src/FocusTable.js
@@ -42,7 +42,7 @@ function focusScope(
cell: ReactScopeMethods,
event?: KeyboardEvent,
): void {
- const firstScopedNode = cell.queryFirstNode(scopeQuery);
+ const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
if (firstScopedNode !== null) {
firstScopedNode.focus();
if (event) {
@@ -58,13 +58,13 @@ function focusCellByColumnIndex(
columnIndex: number,
event?: KeyboardEvent,
): void {
- const cells = row.getChildren();
+ const cells = row.DO_NOT_USE_getChildren();
if (cells !== null) {
let colSize = 0;
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
if (cell) {
- colSize += cell.getProps().colSpan || 1;
+ colSize += cell.DO_NOT_USE_getProps().colSpan || 1;
if (colSize > columnIndex) {
focusScope(scopeQuery, cell, event);
return;
@@ -84,7 +84,7 @@ function getCellIndexes(
if (cell === currentCell) {
return [i, i + totalColSpan];
}
- const colSpan = cell.getProps().colSpan;
+ const colSpan = cell.DO_NOT_USE_getProps().colSpan;
if (colSpan) {
totalColSpan += colSpan - 1;
}
@@ -93,9 +93,9 @@ function getCellIndexes(
}
function getRowCells(currentCell: ReactScopeMethods) {
- const row = currentCell.getParent();
- if (row !== null && row.getProps().type === 'row') {
- const cells = row.getChildren();
+ const row = currentCell.DO_NOT_USE_getParent();
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
+ const cells = row.DO_NOT_USE_getChildren();
if (cells !== null) {
const [rowIndex, rowIndexWithColSpan] = getCellIndexes(
cells,
@@ -108,11 +108,11 @@ function getRowCells(currentCell: ReactScopeMethods) {
}
function getRows(currentCell: ReactScopeMethods) {
- const row = currentCell.getParent();
- if (row !== null && row.getProps().type === 'row') {
- const table = row.getParent();
- if (table !== null && table.getProps().type === 'table') {
- const rows = table.getChildren();
+ const row = currentCell.DO_NOT_USE_getParent();
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
+ const table = row.DO_NOT_USE_getParent();
+ if (table !== null && table.DO_NOT_USE_getProps().type === 'table') {
+ const rows = table.DO_NOT_USE_getChildren();
if (rows !== null) {
const columnIndex = rows.indexOf(row);
return [rows, columnIndex];
@@ -127,11 +127,11 @@ function triggerNavigateOut(
direction: 'left' | 'right' | 'up' | 'down',
event,
): void {
- const row = currentCell.getParent();
- if (row !== null && row.getProps().type === 'row') {
- const table = row.getParent();
+ const row = currentCell.DO_NOT_USE_getParent();
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
+ const table = row.DO_NOT_USE_getParent();
if (table !== null) {
- const props = table.getProps();
+ const props = table.DO_NOT_USE_getProps();
const onKeyboardOut = props.onKeyboardOut;
if (props.type === 'table' && typeof onKeyboardOut === 'function') {
onKeyboardOut(direction, event);
@@ -143,11 +143,11 @@ function triggerNavigateOut(
}
function getTableProps(currentCell: ReactScopeMethods): Object {
- const row = currentCell.getParent();
- if (row !== null && row.getProps().type === 'row') {
- const table = row.getParent();
+ const row = currentCell.DO_NOT_USE_getParent();
+ if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
+ const table = row.DO_NOT_USE_getParent();
if (table !== null) {
- return table.getProps();
+ return table.DO_NOT_USE_getProps();
}
}
return {};
@@ -207,12 +207,14 @@ export function createFocusTable(
if (key === 'Tab') {
const tabScopeQuery = getTableProps(currentCell).tabScopeQuery;
if (tabScopeQuery) {
- const rowScope = currentCell.getParent();
+ const rowScope = currentCell.DO_NOT_USE_getParent();
if (rowScope) {
- const tableScope = rowScope.getParent();
+ const tableScope = rowScope.DO_NOT_USE_getParent();
if (tableScope) {
const activeNode = document.activeElement;
- const nodes = tableScope.queryAllNodes(tabScopeQuery);
+ const nodes = tableScope.DO_NOT_USE_queryAllNodes(
+ tabScopeQuery,
+ );
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node !== activeNode) {
diff --git a/packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js b/packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js
index 1a286330c775a..a3cd9b2ee6a16 100644
--- a/packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js
+++ b/packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js
@@ -35,7 +35,7 @@ describe('TabbableScopeQuery', () => {
container = null;
});
- it('queryAllNodes() works as intended', () => {
+ it('DO_NOT_USE_queryAllNodes() works as intended', () => {
const scopeRef = React.createRef();
const nodeRefA = React.createRef();
const nodeRefB = React.createRef();
@@ -60,7 +60,7 @@ describe('TabbableScopeQuery', () => {
}
ReactDOM.render(, container);
- let nodes = scopeRef.current.queryAllNodes(tabbableScopeQuery);
+ let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
expect(nodes).toEqual([
nodeRefA.current,
nodeRefB.current,
diff --git a/packages/react-interactions/accessibility/src/shared/getTabbableNodes.js b/packages/react-interactions/accessibility/src/shared/getTabbableNodes.js
index ed6ec67ba6233..7af8612e5f96f 100644
--- a/packages/react-interactions/accessibility/src/shared/getTabbableNodes.js
+++ b/packages/react-interactions/accessibility/src/shared/getTabbableNodes.js
@@ -19,7 +19,7 @@ export default function getTabbableNodes(
number,
null | HTMLElement,
] {
- const tabbableNodes = scope.queryAllNodes(scopeQuery);
+ const tabbableNodes = scope.DO_NOT_USE_queryAllNodes(scopeQuery);
if (tabbableNodes === null || tabbableNodes.length === 0) {
return [null, null, null, 0, null];
}
diff --git a/packages/react-reconciler/src/ReactFiberScope.js b/packages/react-reconciler/src/ReactFiberScope.js
index 72bbaa6af375b..a593ef22af416 100644
--- a/packages/react-reconciler/src/ReactFiberScope.js
+++ b/packages/react-reconciler/src/ReactFiberScope.js
@@ -12,6 +12,7 @@ import type {
ReactScope,
ReactScopeInstance,
ReactScopeMethods,
+ ReactContext,
} from 'shared/ReactTypes';
import {getPublicInstance, getInstanceFromNode} from './ReactFiberHostConfig';
@@ -20,6 +21,7 @@ import {
HostComponent,
SuspenseComponent,
ScopeComponent,
+ ContextProvider,
} from 'shared/ReactWorkTags';
import {enableScopeAPI} from 'shared/ReactFeatureFlags';
@@ -142,6 +144,38 @@ function collectNearestChildScopeMethods(
}
}
+function collectNearestContextValues(
+ node: Fiber,
+ context: ReactContext,
+ childContextValues: Array,
+): void {
+ if (node.tag === ContextProvider && node.type._context === context) {
+ const contextValue = node.memoizedProps.value;
+ childContextValues.push(contextValue);
+ } else {
+ let child = node.child;
+
+ if (isFiberSuspenseAndTimedOut(node)) {
+ child = getSuspenseFallbackChild(node);
+ }
+ if (child !== null) {
+ collectNearestChildContextValues(child, context, childContextValues);
+ }
+ }
+}
+
+function collectNearestChildContextValues(
+ startingChild: Fiber | null,
+ context: ReactContext,
+ childContextValues: Array,
+): void {
+ let child = startingChild;
+ while (child !== null) {
+ collectNearestContextValues(child, context, childContextValues);
+ child = child.sibling;
+ }
+}
+
function isValidScopeNode(node, scope) {
return (
node.tag === ScopeComponent &&
@@ -155,7 +189,7 @@ export function createScopeMethods(
instance: ReactScopeInstance,
): ReactScopeMethods {
return {
- getChildren(): null | Array {
+ DO_NOT_USE_getChildren(): null | Array {
const currentFiber = ((instance.fiber: any): Fiber);
const child = currentFiber.child;
const childrenScopes = [];
@@ -164,7 +198,7 @@ export function createScopeMethods(
}
return childrenScopes.length === 0 ? null : childrenScopes;
},
- getChildrenFromRoot(): null | Array {
+ DO_NOT_USE_getChildrenFromRoot(): null | Array {
const currentFiber = ((instance.fiber: any): Fiber);
let node = currentFiber;
while (node !== null) {
@@ -181,7 +215,7 @@ export function createScopeMethods(
collectNearestChildScopeMethods(node.child, scope, childrenScopes);
return childrenScopes.length === 0 ? null : childrenScopes;
},
- getParent(): null | ReactScopeMethods {
+ DO_NOT_USE_getParent(): null | ReactScopeMethods {
let node = ((instance.fiber: any): Fiber).return;
while (node !== null) {
if (node.tag === ScopeComponent && node.type === scope) {
@@ -191,11 +225,11 @@ export function createScopeMethods(
}
return null;
},
- getProps(): Object {
+ DO_NOT_USE_getProps(): Object {
const currentFiber = ((instance.fiber: any): Fiber);
return currentFiber.memoizedProps;
},
- queryAllNodes(
+ DO_NOT_USE_queryAllNodes(
fn: (type: string | Object, props: Object, instance: Object) => boolean,
): null | Array