@samitouri / QOS-React-2 / commits / b6173e643a

[react-interactions] Add DO_NOT_USE to Scope methods (#17835)

Dominic Gannaway committed Jan 15, 2020 at 09:50 UTC b6173e643a4311b9b1cf039824b2f3d7b974b8cf
11 files changed +170 -157
packages/react-interactions/accessibility/README.md
-63
@@ -14,74 +14,11 @@ can be found [here](./docs).
14
15 Note: React Scopes require the internal React flag `enableScopeAPI`.
16
17 -When creating a scope, a query function is required. The query function is used
18 -when collecting host nodes that match the criteria of the query function.
19 -
20 -```jsx
21 -// This query function only matches host nodes that have the type of "div"
22 -const queryFunction = (type: string, props: Object): boolean => {
23 - if (type === 'div') {
24 - return true;
25 - }
26 - return false;
27 -};
28 -
29 -// Create the scope with the queryFunction above
30 -const DivOnlyScope = React.unstable_createScope(queryFunction);
31 -
32 -// We can now use this in our components. We need to attach
33 -// a ref so we can get the matching host nodes.
34 -function MyComponent(props) {
35 - const divOnlyScope = useRef(null);
36 - return (
37 - <DivOnlyScope ref={divOnlyScope}>
38 - <div>DIV 1</div>
39 - <div>DIV 2</div>
40 - <div>DIV 3</div>
41 - </DivOnlyScope>
42 - );
43 -}
44 -
45 -// Using the ref, we can get the host nodes via getAllNodes()
46 -const divs = divOnlyScope.current.getAllNodes();
47 -
48 -// [<div>DIV 1</div>, <div>DIV 2</div>, <div>DIV 3</div>]
49 -console.log(divs);
50 -```
51 -
17 ## React Scope Interface
18
19 Scopes require a `ref` to access the internal interface of a particular scope.
20 The internal interface (`ReactScopeInterface`) exposes the following scope API:
21
57 -### getChildren: () => null | Array<ReactScopeInterface>
58 -
59 -Returns an array of all child `ReactScopeInterface` nodes that are
60 -of scopes of the same type. Returns `null` if there are no child scope nodes.
61 -
62 -### getChildrenFromRoot: () => null | Array<ReactScopeInterface>
63 -
64 -Similar to `getChildren`, except this applies the same traversal from the root of the
65 -React internal tree instead of from the scope node position.
66 -
67 -### getParent: () => null | ReactScopeInterface
68 -
69 -Returns the parent `ReactScopeInterface` of the scope node or `null` if none exists.
70 -
71 -### getProps: () => Object
72 -
73 -Returns the current `props` object of the scope node.
74 -
75 -### getAllNodes: () => null | Array<HTMLElement>
76 -
77 -Returns an array of all child host nodes that successfully match when queried using the
78 -query function passed to the scope. Returns `null` if there are no matching host nodes.
79 -
80 -### getFirstNode: () => null | HTMLElement
81 -
82 -Returns the first child host node that successfully matches when queried using the
83 -query function passed to the scope. Returns `null` if there is no matching host node.
84 -
22 ### containsNode: (node: HTMLElement) => boolean
23
24 Returns `true` or `false` depending on if the given `HTMLElement` is a descendant
packages/react-interactions/accessibility/docs/TabbableScopeQuery.md
+1 -1
@@ -15,7 +15,7 @@ function FocusableNodeCollector(props) {
15 const scope = scopeRef.current;
16
17 if (scope) {
18 - const tabFocusableNodes = scope.queryAllNodes(tabbableScopeQuery);
18 + const tabFocusableNodes = scope.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
19 if (tabFocusableNodes && props.onFocusableNodes) {
20 props.onFocusableNodes(tabFocusableNodes);
21 }
packages/react-interactions/accessibility/src/FocusContain.js
+1 -1
@@ -71,7 +71,7 @@ export default function FocusContain({
71 disabled !== true &&
72 !scope.containsNode(document.activeElement)
73 ) {
74 - const fistElem = scope.queryFirstNode(scopeQuery);
74 + const fistElem = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
75 if (fistElem !== null) {
76 fistElem.focus();
77 }
packages/react-interactions/accessibility/src/FocusGroup.js
+11 -9
@@ -35,7 +35,7 @@ function focusGroupItem(
35 cell: ReactScopeMethods,
36 event: KeyboardEvent,
37 ): void {
38 - const firstScopedNode = cell.queryFirstNode(scopeQuery);
38 + const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
39 if (firstScopedNode !== null) {
40 firstScopedNode.focus();
41 event.preventDefault();
@@ -46,7 +46,7 @@ function getPreviousGroupItem(
46 group: ReactScopeMethods,
47 currentItem: ReactScopeMethods,
48 ): null | ReactScopeMethods {
49 - const items = group.getChildren();
49 + const items = group.DO_NOT_USE_getChildren();
50 if (items !== null) {
51 const currentItemIndex = items.indexOf(currentItem);
52 const wrap = getGroupProps(currentItem).wrap;
@@ -63,7 +63,7 @@ function getNextGroupItem(
63 group: ReactScopeMethods,
64 currentItem: ReactScopeMethods,
65 ): null | ReactScopeMethods {
66 - const items = group.getChildren();
66 + const items = group.DO_NOT_USE_getChildren();
67 if (items !== null) {
68 const currentItemIndex = items.indexOf(currentItem);
69 const wrap = getGroupProps(currentItem).wrap;
@@ -78,9 +78,9 @@ function getNextGroupItem(
78 }
79
80 function getGroupProps(currentCell: ReactScopeMethods): Object {
81 - const group = currentCell.getParent();
81 + const group = currentCell.DO_NOT_USE_getParent();
82 if (group !== null) {
83 - const groupProps = group.getProps();
83 + const groupProps = group.DO_NOT_USE_getProps();
84 if (groupProps && groupProps.type === 'group') {
85 return groupProps;
86 }
@@ -125,8 +125,8 @@ export function createFocusGroup(
125 onKeyDown(event: KeyboardEvent): void {
126 const currentItem = scopeRef.current;
127 if (currentItem !== null) {
128 - const group = currentItem.getParent();
129 - const groupProps = group && group.getProps();
128 + const group = currentItem.DO_NOT_USE_getParent();
129 + const groupProps = group && group.DO_NOT_USE_getProps();
130 if (group !== null && groupProps.type === 'group') {
131 const portrait = groupProps.portrait;
132 const key = event.key;
@@ -134,10 +134,12 @@ export function createFocusGroup(
134 if (key === 'Tab') {
135 const tabScopeQuery = getGroupProps(currentItem).tabScopeQuery;
136 if (tabScopeQuery) {
137 - const groupScope = currentItem.getParent();
137 + const groupScope = currentItem.DO_NOT_USE_getParent();
138 if (groupScope) {
139 const activeNode = document.activeElement;
140 - const nodes = groupScope.queryAllNodes(tabScopeQuery);
140 + const nodes = groupScope.DO_NOT_USE_queryAllNodes(
141 + tabScopeQuery,
142 + );
143 for (let i = 0; i < nodes.length; i++) {
144 const node = nodes[i];
145 if (node !== activeNode) {
packages/react-interactions/accessibility/src/FocusManager.js
+3 -3
@@ -16,7 +16,7 @@ export function focusFirst(
16 scopeQuery: (type: string | Object, props: Object) => boolean,
17 scope: ReactScopeMethods,
18 ): void {
19 - const firstNode = scope.queryFirstNode(scopeQuery);
19 + const firstNode = scope.DO_NOT_USE_queryFirstNode(scopeQuery);
20 if (firstNode) {
21 focusElem(firstNode);
22 }
@@ -101,7 +101,7 @@ export function focusPrevious(
101 export function getNextScope(
102 scope: ReactScopeMethods,
103 ): null | ReactScopeMethods {
104 - const allScopes = scope.getChildrenFromRoot();
104 + const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
105 if (allScopes === null) {
106 return null;
107 }
@@ -115,7 +115,7 @@ export function getNextScope(
115 export function getPreviousScope(
116 scope: ReactScopeMethods,
117 ): null | ReactScopeMethods {
118 - const allScopes = scope.getChildrenFromRoot();
118 + const allScopes = scope.DO_NOT_USE_getChildrenFromRoot();
119 if (allScopes === null) {
120 return null;
121 }
packages/react-interactions/accessibility/src/FocusTable.js
+25 -23
@@ -42,7 +42,7 @@ function focusScope(
42 cell: ReactScopeMethods,
43 event?: KeyboardEvent,
44 ): void {
45 - const firstScopedNode = cell.queryFirstNode(scopeQuery);
45 + const firstScopedNode = cell.DO_NOT_USE_queryFirstNode(scopeQuery);
46 if (firstScopedNode !== null) {
47 firstScopedNode.focus();
48 if (event) {
@@ -58,13 +58,13 @@ function focusCellByColumnIndex(
58 columnIndex: number,
59 event?: KeyboardEvent,
60 ): void {
61 - const cells = row.getChildren();
61 + const cells = row.DO_NOT_USE_getChildren();
62 if (cells !== null) {
63 let colSize = 0;
64 for (let i = 0; i < cells.length; i++) {
65 const cell = cells[i];
66 if (cell) {
67 - colSize += cell.getProps().colSpan || 1;
67 + colSize += cell.DO_NOT_USE_getProps().colSpan || 1;
68 if (colSize > columnIndex) {
69 focusScope(scopeQuery, cell, event);
70 return;
@@ -84,7 +84,7 @@ function getCellIndexes(
84 if (cell === currentCell) {
85 return [i, i + totalColSpan];
86 }
87 - const colSpan = cell.getProps().colSpan;
87 + const colSpan = cell.DO_NOT_USE_getProps().colSpan;
88 if (colSpan) {
89 totalColSpan += colSpan - 1;
90 }
@@ -93,9 +93,9 @@ function getCellIndexes(
93 }
94
95 function getRowCells(currentCell: ReactScopeMethods) {
96 - const row = currentCell.getParent();
97 - if (row !== null && row.getProps().type === 'row') {
98 - const cells = row.getChildren();
96 + const row = currentCell.DO_NOT_USE_getParent();
97 + if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
98 + const cells = row.DO_NOT_USE_getChildren();
99 if (cells !== null) {
100 const [rowIndex, rowIndexWithColSpan] = getCellIndexes(
101 cells,
@@ -108,11 +108,11 @@ function getRowCells(currentCell: ReactScopeMethods) {
108 }
109
110 function getRows(currentCell: ReactScopeMethods) {
111 - const row = currentCell.getParent();
112 - if (row !== null && row.getProps().type === 'row') {
113 - const table = row.getParent();
114 - if (table !== null && table.getProps().type === 'table') {
115 - const rows = table.getChildren();
111 + const row = currentCell.DO_NOT_USE_getParent();
112 + if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
113 + const table = row.DO_NOT_USE_getParent();
114 + if (table !== null && table.DO_NOT_USE_getProps().type === 'table') {
115 + const rows = table.DO_NOT_USE_getChildren();
116 if (rows !== null) {
117 const columnIndex = rows.indexOf(row);
118 return [rows, columnIndex];
@@ -127,11 +127,11 @@ function triggerNavigateOut(
127 direction: 'left' | 'right' | 'up' | 'down',
128 event,
129 ): void {
130 - const row = currentCell.getParent();
131 - if (row !== null && row.getProps().type === 'row') {
132 - const table = row.getParent();
130 + const row = currentCell.DO_NOT_USE_getParent();
131 + if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
132 + const table = row.DO_NOT_USE_getParent();
133 if (table !== null) {
134 - const props = table.getProps();
134 + const props = table.DO_NOT_USE_getProps();
135 const onKeyboardOut = props.onKeyboardOut;
136 if (props.type === 'table' && typeof onKeyboardOut === 'function') {
137 onKeyboardOut(direction, event);
@@ -143,11 +143,11 @@ function triggerNavigateOut(
143 }
144
145 function getTableProps(currentCell: ReactScopeMethods): Object {
146 - const row = currentCell.getParent();
147 - if (row !== null && row.getProps().type === 'row') {
148 - const table = row.getParent();
146 + const row = currentCell.DO_NOT_USE_getParent();
147 + if (row !== null && row.DO_NOT_USE_getProps().type === 'row') {
148 + const table = row.DO_NOT_USE_getParent();
149 if (table !== null) {
150 - return table.getProps();
150 + return table.DO_NOT_USE_getProps();
151 }
152 }
153 return {};
@@ -207,12 +207,14 @@ export function createFocusTable(
207 if (key === 'Tab') {
208 const tabScopeQuery = getTableProps(currentCell).tabScopeQuery;
209 if (tabScopeQuery) {
210 - const rowScope = currentCell.getParent();
210 + const rowScope = currentCell.DO_NOT_USE_getParent();
211 if (rowScope) {
212 - const tableScope = rowScope.getParent();
212 + const tableScope = rowScope.DO_NOT_USE_getParent();
213 if (tableScope) {
214 const activeNode = document.activeElement;
215 - const nodes = tableScope.queryAllNodes(tabScopeQuery);
215 + const nodes = tableScope.DO_NOT_USE_queryAllNodes(
216 + tabScopeQuery,
217 + );
218 for (let i = 0; i < nodes.length; i++) {
219 const node = nodes[i];
220 if (node !== activeNode) {
packages/react-interactions/accessibility/src/__tests__/TabbableScopeQuery-test.internal.js
+2 -2
@@ -35,7 +35,7 @@ describe('TabbableScopeQuery', () => {
35 container = null;
36 });
37
38 - it('queryAllNodes() works as intended', () => {
38 + it('DO_NOT_USE_queryAllNodes() works as intended', () => {
39 const scopeRef = React.createRef();
40 const nodeRefA = React.createRef();
41 const nodeRefB = React.createRef();
@@ -60,7 +60,7 @@ describe('TabbableScopeQuery', () => {
60 }
61
62 ReactDOM.render(<Test />, container);
63 - let nodes = scopeRef.current.queryAllNodes(tabbableScopeQuery);
63 + let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(tabbableScopeQuery);
64 expect(nodes).toEqual([
65 nodeRefA.current,
66 nodeRefB.current,
packages/react-interactions/accessibility/src/shared/getTabbableNodes.js
+1 -1
@@ -19,7 +19,7 @@ export default function getTabbableNodes(
19 number,
20 null | HTMLElement,
21 ] {
22 - const tabbableNodes = scope.queryAllNodes(scopeQuery);
22 + const tabbableNodes = scope.DO_NOT_USE_queryAllNodes(scopeQuery);
23 if (tabbableNodes === null || tabbableNodes.length === 0) {
24 return [null, null, null, 0, null];
25 }
packages/react-reconciler/src/ReactFiberScope.js
+49 -6
@@ -12,6 +12,7 @@ import type {
12 ReactScope,
13 ReactScopeInstance,
14 ReactScopeMethods,
15 + ReactContext,
16 } from 'shared/ReactTypes';
17
18 import {getPublicInstance, getInstanceFromNode} from './ReactFiberHostConfig';
@@ -20,6 +21,7 @@ import {
21 HostComponent,
22 SuspenseComponent,
23 ScopeComponent,
24 + ContextProvider,
25 } from 'shared/ReactWorkTags';
26 import {enableScopeAPI} from 'shared/ReactFeatureFlags';
27
@@ -142,6 +144,38 @@ function collectNearestChildScopeMethods(
144 }
145 }
146
147 +function collectNearestContextValues<T>(
148 + node: Fiber,
149 + context: ReactContext<T>,
150 + childContextValues: Array<T>,
151 +): void {
152 + if (node.tag === ContextProvider && node.type._context === context) {
153 + const contextValue = node.memoizedProps.value;
154 + childContextValues.push(contextValue);
155 + } else {
156 + let child = node.child;
157 +
158 + if (isFiberSuspenseAndTimedOut(node)) {
159 + child = getSuspenseFallbackChild(node);
160 + }
161 + if (child !== null) {
162 + collectNearestChildContextValues(child, context, childContextValues);
163 + }
164 + }
165 +}
166 +
167 +function collectNearestChildContextValues<T>(
168 + startingChild: Fiber | null,
169 + context: ReactContext<T>,
170 + childContextValues: Array<T>,
171 +): void {
172 + let child = startingChild;
173 + while (child !== null) {
174 + collectNearestContextValues(child, context, childContextValues);
175 + child = child.sibling;
176 + }
177 +}
178 +
179 function isValidScopeNode(node, scope) {
180 return (
181 node.tag === ScopeComponent &&
@@ -155,7 +189,7 @@ export function createScopeMethods(
189 instance: ReactScopeInstance,
190 ): ReactScopeMethods {
191 return {
158 - getChildren(): null | Array<ReactScopeMethods> {
192 + DO_NOT_USE_getChildren(): null | Array<ReactScopeMethods> {
193 const currentFiber = ((instance.fiber: any): Fiber);
194 const child = currentFiber.child;
195 const childrenScopes = [];
@@ -164,7 +198,7 @@ export function createScopeMethods(
198 }
199 return childrenScopes.length === 0 ? null : childrenScopes;
200 },
167 - getChildrenFromRoot(): null | Array<ReactScopeMethods> {
201 + DO_NOT_USE_getChildrenFromRoot(): null | Array<ReactScopeMethods> {
202 const currentFiber = ((instance.fiber: any): Fiber);
203 let node = currentFiber;
204 while (node !== null) {
@@ -181,7 +215,7 @@ export function createScopeMethods(
215 collectNearestChildScopeMethods(node.child, scope, childrenScopes);
216 return childrenScopes.length === 0 ? null : childrenScopes;
217 },
184 - getParent(): null | ReactScopeMethods {
218 + DO_NOT_USE_getParent(): null | ReactScopeMethods {
219 let node = ((instance.fiber: any): Fiber).return;
220 while (node !== null) {
221 if (node.tag === ScopeComponent && node.type === scope) {
@@ -191,11 +225,11 @@ export function createScopeMethods(
225 }
226 return null;
227 },
194 - getProps(): Object {
228 + DO_NOT_USE_getProps(): Object {
229 const currentFiber = ((instance.fiber: any): Fiber);
230 return currentFiber.memoizedProps;
231 },
198 - queryAllNodes(
232 + DO_NOT_USE_queryAllNodes(
233 fn: (type: string | Object, props: Object, instance: Object) => boolean,
234 ): null | Array<Object> {
235 const currentFiber = ((instance.fiber: any): Fiber);
@@ -206,7 +240,7 @@ export function createScopeMethods(
240 }
241 return scopedNodes.length === 0 ? null : scopedNodes;
242 },
209 - queryFirstNode(
243 + DO_NOT_USE_queryFirstNode(
244 fn: (type: string | Object, props: Object, instance: Object) => boolean,
245 ): null | Object {
246 const currentFiber = ((instance.fiber: any): Fiber);
@@ -230,5 +264,14 @@ export function createScopeMethods(
264 }
265 return false;
266 },
267 + getChildContextValues<T>(context: ReactContext<T>): Array<T> {
268 + const currentFiber = ((instance.fiber: any): Fiber);
269 + const child = currentFiber.child;
270 + const childContextValues = [];
271 + if (child !== null) {
272 + collectNearestChildContextValues(child, context, childContextValues);
273 + }
274 + return childContextValues;
275 + },
276 };
277 }
packages/react-reconciler/src/__tests__/ReactScope-test.internal.js
+70 -42
@@ -38,7 +38,7 @@ describe('ReactScope', () => {
38 container = null;
39 });
40
41 - it('queryAllNodes() works as intended', () => {
41 + it('DO_NOT_USE_queryAllNodes() works as intended', () => {
42 const testScopeQuery = (type, props) => true;
43 const TestScope = React.unstable_createScope();
44 const scopeRef = React.createRef();
@@ -63,16 +63,16 @@ describe('ReactScope', () => {
63 }
64
65 ReactDOM.render(<Test toggle={true} />, container);
66 - let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
66 + let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
67 expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
68 ReactDOM.render(<Test toggle={false} />, container);
69 - nodes = scopeRef.current.queryAllNodes(testScopeQuery);
69 + nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
70 expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
71 ReactDOM.render(null, container);
72 expect(scopeRef.current).toBe(null);
73 });
74
75 - it('queryAllNodes() provides the correct host instance', () => {
75 + it('DO_NOT_USE_queryAllNodes() provides the correct host instance', () => {
76 const testScopeQuery = (type, props) => type === 'div';
77 const TestScope = React.unstable_createScope();
78 const scopeRef = React.createRef();
@@ -97,28 +97,28 @@ describe('ReactScope', () => {
97 }
98
99 ReactDOM.render(<Test toggle={true} />, container);
100 - let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
100 + let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
101 expect(nodes).toEqual([divRef.current]);
102 let filterQuery = (type, props, instance) =>
103 instance === spanRef.current || testScopeQuery(type, props);
104 - nodes = scopeRef.current.queryAllNodes(filterQuery);
104 + nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
105 expect(nodes).toEqual([divRef.current, spanRef.current]);
106 filterQuery = (type, props, instance) =>
107 [spanRef.current, aRef.current].includes(instance) ||
108 testScopeQuery(type, props);
109 - nodes = scopeRef.current.queryAllNodes(filterQuery);
109 + nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
110 expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
111 ReactDOM.render(<Test toggle={false} />, container);
112 filterQuery = (type, props, instance) =>
113 [spanRef.current, aRef.current].includes(instance) ||
114 testScopeQuery(type, props);
115 - nodes = scopeRef.current.queryAllNodes(filterQuery);
115 + nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(filterQuery);
116 expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
117 ReactDOM.render(null, container);
118 expect(scopeRef.current).toBe(null);
119 });
120
121 - it('queryFirstNode() works as intended', () => {
121 + it('DO_NOT_USE_queryFirstNode() works as intended', () => {
122 const testScopeQuery = (type, props) => true;
123 const TestScope = React.unstable_createScope();
124 const scopeRef = React.createRef();
@@ -143,10 +143,10 @@ describe('ReactScope', () => {
143 }
144
145 ReactDOM.render(<Test toggle={true} />, container);
146 - let node = scopeRef.current.queryFirstNode(testScopeQuery);
146 + let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
147 expect(node).toEqual(divRef.current);
148 ReactDOM.render(<Test toggle={false} />, container);
149 - node = scopeRef.current.queryFirstNode(testScopeQuery);
149 + node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
150 expect(node).toEqual(aRef.current);
151 ReactDOM.render(null, container);
152 expect(scopeRef.current).toBe(null);
@@ -201,7 +201,7 @@ describe('ReactScope', () => {
201 expect(scopeRef.current.containsNode(emRef.current)).toBe(false);
202 });
203
204 - it('mixed getParent() and queryAllNodes() works as intended', () => {
204 + it('mixed DO_NOT_USE_getParent() and queryAllNodes() works as intended', () => {
205 const testScopeQuery = (type, props) => true;
206 const TestScope = React.unstable_createScope();
207 const TestScope2 = React.unstable_createScope();
@@ -237,26 +237,26 @@ describe('ReactScope', () => {
237 }
238
239 ReactDOM.render(<Test />, container);
240 - const dParent = refD.current.getParent();
240 + const dParent = refD.current.DO_NOT_USE_getParent();
241 expect(dParent).not.toBe(null);
242 - expect(dParent.queryAllNodes(testScopeQuery)).toEqual([
242 + expect(dParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
243 divA.current,
244 spanB.current,
245 divB.current,
246 ]);
247 - const cParent = refC.current.getParent();
247 + const cParent = refC.current.DO_NOT_USE_getParent();
248 expect(cParent).not.toBe(null);
249 - expect(cParent.queryAllNodes(testScopeQuery)).toEqual([
249 + expect(cParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
250 spanA.current,
251 divA.current,
252 spanB.current,
253 divB.current,
254 ]);
255 - expect(refB.current.getParent()).toBe(null);
256 - expect(refA.current.getParent()).toBe(null);
255 + expect(refB.current.DO_NOT_USE_getParent()).toBe(null);
256 + expect(refA.current.DO_NOT_USE_getParent()).toBe(null);
257 });
258
259 - it('getChildren() works as intended', () => {
259 + it('DO_NOT_USE_getChildren() works as intended', () => {
260 const TestScope = React.unstable_createScope();
261 const TestScope2 = React.unstable_createScope();
262 const refA = React.createRef();
@@ -291,13 +291,13 @@ describe('ReactScope', () => {
291 }
292
293 ReactDOM.render(<Test />, container);
294 - const dChildren = refD.current.getChildren();
294 + const dChildren = refD.current.DO_NOT_USE_getChildren();
295 expect(dChildren).toBe(null);
296 - const cChildren = refC.current.getChildren();
296 + const cChildren = refC.current.DO_NOT_USE_getChildren();
297 expect(cChildren).toBe(null);
298 - const bChildren = refB.current.getChildren();
298 + const bChildren = refB.current.DO_NOT_USE_getChildren();
299 expect(bChildren).toEqual([refD.current]);
300 - const aChildren = refA.current.getChildren();
300 + const aChildren = refA.current.DO_NOT_USE_getChildren();
301 expect(aChildren).toEqual([refC.current]);
302 });
303
@@ -328,7 +328,7 @@ describe('ReactScope', () => {
328 container.innerHTML = html;
329 ReactDOM.hydrate(<Test />, container);
330 const testScopeQuery = (type, props) => true;
331 - const nodes = scopeRef.current.queryAllNodes(testScopeQuery);
331 + const nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
332 expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
333 });
334
@@ -373,6 +373,34 @@ describe('ReactScope', () => {
373 target.keydown({key: 'Q'});
374 expect(onKeyDown).toHaveBeenCalledTimes(1);
375 });
376 +
377 + it('getChildContextValues() works as intended', () => {
378 + const TestContext = React.createContext();
379 + const TestScope = React.unstable_createScope();
380 + const scopeRef = React.createRef();
381 +
382 + function Test({toggle}) {
383 + return toggle ? (
384 + <TestScope ref={scopeRef}>
385 + <TestContext.Provider value={1} />
386 + </TestScope>
387 + ) : (
388 + <TestScope ref={scopeRef}>
389 + <TestContext.Provider value={1} />
390 + <TestContext.Provider value={2} />
391 + </TestScope>
392 + );
393 + }
394 +
395 + ReactDOM.render(<Test toggle={true} />, container);
396 + let nodes = scopeRef.current.getChildContextValues(TestContext);
397 + expect(nodes).toEqual([1]);
398 + ReactDOM.render(<Test toggle={false} />, container);
399 + nodes = scopeRef.current.getChildContextValues(TestContext);
400 + expect(nodes).toEqual([1, 2]);
401 + ReactDOM.render(null, container);
402 + expect(scopeRef.current).toBe(null);
403 + });
404 });
405
406 describe('ReactTestRenderer', () => {
@@ -382,7 +410,7 @@ describe('ReactScope', () => {
410 ReactTestRenderer = require('react-test-renderer');
411 });
412
385 - it('queryAllNodes() works as intended', () => {
413 + it('DO_NOT_USE_queryAllNodes() works as intended', () => {
414 const testScopeQuery = (type, props) => true;
415 const TestScope = React.unstable_createScope();
416 const scopeRef = React.createRef();
@@ -411,14 +439,14 @@ describe('ReactScope', () => {
439 return element;
440 },
441 });
414 - let nodes = scopeRef.current.queryAllNodes(testScopeQuery);
442 + let nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
443 expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
444 renderer.update(<Test toggle={false} />);
417 - nodes = scopeRef.current.queryAllNodes(testScopeQuery);
445 + nodes = scopeRef.current.DO_NOT_USE_queryAllNodes(testScopeQuery);
446 expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
447 });
448
421 - it('queryFirstNode() works as intended', () => {
449 + it('DO_NOT_USE_queryFirstNode() works as intended', () => {
450 const testScopeQuery = (type, props) => true;
451 const TestScope = React.unstable_createScope();
452 const scopeRef = React.createRef();
@@ -447,10 +475,10 @@ describe('ReactScope', () => {
475 return element;
476 },
477 });
450 - let node = scopeRef.current.queryFirstNode(testScopeQuery);
478 + let node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
479 expect(node).toEqual(divRef.current);
480 renderer.update(<Test toggle={false} />);
453 - node = scopeRef.current.queryFirstNode(testScopeQuery);
481 + node = scopeRef.current.DO_NOT_USE_queryFirstNode(testScopeQuery);
482 expect(node).toEqual(aRef.current);
483 });
484
@@ -507,7 +535,7 @@ describe('ReactScope', () => {
535 expect(scopeRef.current.containsNode(emRef.current)).toBe(false);
536 });
537
510 - it('mixed getParent() and queryAllNodes() works as intended', () => {
538 + it('mixed DO_NOT_USE_getParent() and DO_NOT_USE_queryAllNodes() works as intended', () => {
539 const testScopeQuery = (type, props) => true;
540 const TestScope = React.unstable_createScope();
541 const TestScope2 = React.unstable_createScope();
@@ -547,26 +575,26 @@ describe('ReactScope', () => {
575 return element;
576 },
577 });
550 - const dParent = refD.current.getParent();
578 + const dParent = refD.current.DO_NOT_USE_getParent();
579 expect(dParent).not.toBe(null);
552 - expect(dParent.queryAllNodes(testScopeQuery)).toEqual([
580 + expect(dParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
581 divA.current,
582 spanB.current,
583 divB.current,
584 ]);
557 - const cParent = refC.current.getParent();
585 + const cParent = refC.current.DO_NOT_USE_getParent();
586 expect(cParent).not.toBe(null);
559 - expect(cParent.queryAllNodes(testScopeQuery)).toEqual([
587 + expect(cParent.DO_NOT_USE_queryAllNodes(testScopeQuery)).toEqual([
588 spanA.current,
589 divA.current,
590 spanB.current,
591 divB.current,
592 ]);
565 - expect(refB.current.getParent()).toBe(null);
566 - expect(refA.current.getParent()).toBe(null);
593 + expect(refB.current.DO_NOT_USE_getParent()).toBe(null);
594 + expect(refA.current.DO_NOT_USE_getParent()).toBe(null);
595 });
596
569 - it('getChildren() works as intended', () => {
597 + it('DO_NOT_USE_getChildren() works as intended', () => {
598 const TestScope = React.unstable_createScope();
599 const TestScope2 = React.unstable_createScope();
600 const refA = React.createRef();
@@ -605,13 +633,13 @@ describe('ReactScope', () => {
633 return element;
634 },
635 });
608 - const dChildren = refD.current.getChildren();
636 + const dChildren = refD.current.DO_NOT_USE_getChildren();
637 expect(dChildren).toBe(null);
610 - const cChildren = refC.current.getChildren();
638 + const cChildren = refC.current.DO_NOT_USE_getChildren();
639 expect(cChildren).toBe(null);
612 - const bChildren = refB.current.getChildren();
640 + const bChildren = refB.current.DO_NOT_USE_getChildren();
641 expect(bChildren).toEqual([refD.current]);
614 - const aChildren = refA.current.getChildren();
642 + const aChildren = refA.current.DO_NOT_USE_getChildren();
643 expect(aChildren).toEqual([refC.current]);
644 });
645 });
packages/shared/ReactTypes.js
+7 -6
@@ -171,17 +171,18 @@ export type ReactScope = {|
171 |};
172
173 export type ReactScopeMethods = {|
174 - getChildren(): null | Array<ReactScopeMethods>,
175 - getChildrenFromRoot(): null | Array<ReactScopeMethods>,
176 - getParent(): null | ReactScopeMethods,
177 - getProps(): Object,
178 - queryAllNodes(
174 + DO_NOT_USE_getChildren(): null | Array<ReactScopeMethods>,
175 + DO_NOT_USE_getChildrenFromRoot(): null | Array<ReactScopeMethods>,
176 + DO_NOT_USE_getParent(): null | ReactScopeMethods,
177 + DO_NOT_USE_getProps(): Object,
178 + DO_NOT_USE_queryAllNodes(
179 (type: string | Object, props: Object, instance: Object) => boolean,
180 ): null | Array<Object>,
181 - queryFirstNode(
181 + DO_NOT_USE_queryFirstNode(
182 (type: string | Object, props: Object, instance: Object) => boolean,
183 ): null | Object,
184 containsNode(Object): boolean,
185 + getChildContextValues: <T>(context: ReactContext<T>) => Array<T>,
186 |};
187
188 export type ReactScopeInstance = {|