Refine experimental Scopes API (#18778)
* Refine experimental Scopes API
Dominic Gannaway committed
May 1, 2020 at 19:01 UTC
aa88589d0b56521512e864243744513ee1f93a81
18 files changed
+240
-144
packages/react-art/src/ReactARTHostConfig.js
+1
@@ -243,6 +243,7 @@ function applyTextProps(instance, props, prevProps = {}) {
243
244
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoPersistence';
245
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoHydration';
246
+export * from 'react-reconciler/src/ReactFiberHostConfigWithNoScopes';
247
248
export function appendInitialChild(parentInstance, child) {
249
if (typeof child === 'string') {
packages/react-dom/src/client/ReactDOMComponentTree.js
+14
-2
@@ -8,6 +8,7 @@
8
*/
9
10
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
11
+import type {ReactScopeInstance} from 'shared/ReactTypes';
12
import type {
13
Container,
14
TextInstance,
@@ -23,10 +24,12 @@ import {
24
HostRoot,
25
SuspenseComponent,
26
} from 'react-reconciler/src/ReactWorkTags';
26
-import invariant from 'shared/invariant';
27
28
import {getParentSuspenseInstance} from './ReactDOMHostConfig';
29
30
+import invariant from 'shared/invariant';
31
+import {enableScopeAPI} from 'shared/ReactFeatureFlags';
32
+
33
const randomKey = Math.random()
34
.toString(36)
35
.slice(2);
@@ -47,7 +50,7 @@ export type ElementListenerMapEntry = {
50
51
export function precacheFiberNode(
52
hostInst: Fiber,
50
- node: Instance | TextInstance | SuspenseInstance,
53
+ node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
54
): void {
55
(node: any)[internalInstanceKey] = hostInst;
56
}
@@ -205,3 +208,12 @@ export function getEventListenerMap(node: EventTarget): ElementListenerMap {
208
}
209
return elementListenerMap;
210
}
211
+
212
+export function getFiberFromScopeInstance(
213
+ scope: ReactScopeInstance,
214
+): null | Fiber {
215
+ if (enableScopeAPI) {
216
+ return (scope: any)[internalInstanceKey] || null;
217
+ }
218
+ return null;
219
+}
packages/react-dom/src/client/ReactDOMHostConfig.js
+25
@@ -9,6 +9,7 @@
9
10
import type {TopLevelType} from 'legacy-events/TopLevelEventTypes';
11
import type {RootType} from './ReactDOMRoot';
12
+import type {ReactScopeInstance} from 'shared/ReactTypes';
13
import type {
14
ReactDOMEventResponder,
15
ReactDOMEventResponderInstance,
@@ -19,6 +20,7 @@ import {
20
precacheFiberNode,
21
updateFiberProps,
22
getClosestInstanceFromNode,
23
+ getFiberFromScopeInstance,
24
} from './ReactDOMComponentTree';
25
import {
26
createElement,
@@ -65,6 +67,7 @@ import {
67
enableDeprecatedFlareAPI,
68
enableFundamentalAPI,
69
enableModernEventSystem,
70
+ enableScopeAPI,
71
} from 'shared/ReactFeatureFlags';
72
import {TOP_BEFORE_BLUR, TOP_AFTER_BLUR} from '../events/DOMTopLevelEventTypes';
73
import {listenToEvent} from '../events/DOMModernPluginEventSystem';
@@ -1117,3 +1120,25 @@ export function preparePortalMount(portalInstance: Instance): void {
1120
listenToEvent('onMouseEnter', portalInstance);
1121
}
1122
}
1123
+
1124
+export function prepareScopeUpdate(
1125
+ scopeInstance: ReactScopeInstance,
1126
+ internalInstanceHandle: Object,
1127
+): void {
1128
+ if (enableScopeAPI) {
1129
+ precacheFiberNode(internalInstanceHandle, scopeInstance);
1130
+ }
1131
+}
1132
+
1133
+export function prepareScopeUnmount(scopeInstance: Object): void {
1134
+ // TODO when we add createEventHandle
1135
+}
1136
+
1137
+export function getInstanceFromScope(
1138
+ scopeInstance: ReactScopeInstance,
1139
+): null | Object {
1140
+ if (enableScopeAPI) {
1141
+ return getFiberFromScopeInstance(scopeInstance);
1142
+ }
1143
+ return null;
1144
+}
packages/react-dom/src/events/DOMModernPluginEventSystem.js
+1
-17
@@ -14,7 +14,7 @@ import type {
14
ElementListenerMapEntry,
15
} from '../client/ReactDOMComponentTree';
16
import type {EventSystemFlags} from './EventSystemFlags';
17
-import type {EventPriority, ReactScopeMethods} from 'shared/ReactTypes';
17
+import type {EventPriority} from 'shared/ReactTypes';
18
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
19
import type {PluginModule} from 'legacy-events/PluginModuleType';
20
import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
@@ -381,22 +381,6 @@ function isMatchingRootContainer(
381
);
382
}
383
384
-export function isManagedDOMElement(
385
- target: EventTarget | ReactScopeMethods,
386
-): boolean {
387
- return getClosestInstanceFromNode(((target: any): Node)) !== null;
388
-}
389
-
390
-export function isValidEventTarget(
391
- target: EventTarget | ReactScopeMethods,
392
-): boolean {
393
- return typeof (target: Object).addEventListener === 'function';
394
-}
395
-
396
-export function isReactScope(target: EventTarget | ReactScopeMethods): boolean {
397
- return typeof (target: Object).getChildContextValues === 'function';
398
-}
399
-
384
export function dispatchEventForPluginEventSystem(
385
topLevelType: DOMTopLevelEventType,
386
eventSystemFlags: EventSystemFlags,
packages/react-native-renderer/src/ReactFabricHostConfig.js
+1
@@ -183,6 +183,7 @@ class ReactFabricHostComponent {
183
184
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoMutation';
185
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoHydration';
186
+export * from 'react-reconciler/src/ReactFiberHostConfigWithNoScopes';
187
188
export function appendInitialChild(
189
parentInstance: Instance,
packages/react-native-renderer/src/ReactNativeHostConfig.js
+1
@@ -87,6 +87,7 @@ function recursivelyUncacheFiberNode(node: Instance | TextInstance) {
87
88
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoPersistence';
89
export * from 'react-reconciler/src/ReactFiberHostConfigWithNoHydration';
90
+export * from 'react-reconciler/src/ReactFiberHostConfigWithNoScopes';
91
92
export function appendInitialChild(
93
parentInstance: Instance,
packages/react-noop-renderer/src/createReactNoop.js
+8
@@ -457,6 +457,14 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
457
preparePortalMount() {
458
// NO-OP
459
},
460
+
461
+ prepareScopeUpdate() {},
462
+
463
+ prepareScopeUnmount() {},
464
+
465
+ getInstanceFromScope() {
466
+ throw new Error('Not yet implemented.');
467
+ },
468
};
469
470
const hostConfig = useMutation
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+9
-5
@@ -115,6 +115,8 @@ import {
115
commitHydratedSuspenseInstance,
116
beforeRemoveInstance,
117
clearContainer,
118
+ prepareScopeUpdate,
119
+ prepareScopeUnmount,
120
} from './ReactFiberHostConfig';
121
import {
122
captureCommitPhaseError,
@@ -890,7 +892,7 @@ function commitAttachRef(finishedWork: Fiber) {
892
}
893
// Moved outside to ensure DCE works with this flag
894
if (enableScopeAPI && finishedWork.tag === ScopeComponent) {
893
- instanceToUse = instance.methods;
895
+ instanceToUse = instance;
896
}
897
if (typeof ref === 'function') {
898
ref(instanceToUse);
@@ -1065,10 +1067,12 @@ function commitUnmount(
1067
return;
1068
}
1069
case ScopeComponent: {
1068
- if (enableDeprecatedFlareAPI) {
1069
- unmountDeprecatedResponderListeners(current);
1070
- }
1070
if (enableScopeAPI) {
1071
+ if (enableDeprecatedFlareAPI) {
1072
+ unmountDeprecatedResponderListeners(current);
1073
+ }
1074
+ const scopeInstance = current.stateNode;
1075
+ prepareScopeUnmount(scopeInstance);
1076
safelyDetachRef(current);
1077
}
1078
return;
@@ -1721,7 +1725,6 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1725
case ScopeComponent: {
1726
if (enableScopeAPI) {
1727
const scopeInstance = finishedWork.stateNode;
1724
- scopeInstance.fiber = finishedWork;
1728
if (enableDeprecatedFlareAPI) {
1729
const newProps = finishedWork.memoizedProps;
1730
const oldProps = current !== null ? current.memoizedProps : newProps;
@@ -1731,6 +1734,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1734
updateDeprecatedEventListeners(nextListeners, finishedWork, null);
1735
}
1736
}
1737
+ prepareScopeUpdate(scopeInstance, finishedWork);
1738
return;
1739
}
1740
break;
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+9
-5
@@ -112,6 +112,8 @@ import {
112
commitHydratedSuspenseInstance,
113
beforeRemoveInstance,
114
clearContainer,
115
+ prepareScopeUpdate,
116
+ prepareScopeUnmount,
117
} from './ReactFiberHostConfig';
118
import {
119
captureCommitPhaseError,
@@ -888,7 +890,7 @@ function commitAttachRef(finishedWork: Fiber) {
890
}
891
// Moved outside to ensure DCE works with this flag
892
if (enableScopeAPI && finishedWork.tag === ScopeComponent) {
891
- instanceToUse = instance.methods;
893
+ instanceToUse = instance;
894
}
895
if (typeof ref === 'function') {
896
ref(instanceToUse);
@@ -1063,10 +1065,12 @@ function commitUnmount(
1065
return;
1066
}
1067
case ScopeComponent: {
1066
- if (enableDeprecatedFlareAPI) {
1067
- unmountDeprecatedResponderListeners(current);
1068
- }
1068
if (enableScopeAPI) {
1069
+ if (enableDeprecatedFlareAPI) {
1070
+ unmountDeprecatedResponderListeners(current);
1071
+ }
1072
+ const scopeInstance = current.stateNode;
1073
+ prepareScopeUnmount(scopeInstance);
1074
safelyDetachRef(current);
1075
}
1076
return;
@@ -1715,7 +1719,6 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1719
case ScopeComponent: {
1720
if (enableScopeAPI) {
1721
const scopeInstance = finishedWork.stateNode;
1718
- scopeInstance.fiber = finishedWork;
1722
if (enableDeprecatedFlareAPI) {
1723
const newProps = finishedWork.memoizedProps;
1724
const oldProps = current !== null ? current.memoizedProps : newProps;
@@ -1725,6 +1728,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1728
updateDeprecatedEventListeners(nextListeners, finishedWork, null);
1729
}
1730
}
1731
+ prepareScopeUpdate(scopeInstance, finishedWork);
1732
return;
1733
}
1734
break;
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+4
-7
@@ -87,6 +87,7 @@ import {
87
cloneFundamentalInstance,
88
shouldUpdateFundamentalComponent,
89
preparePortalMount,
90
+ prepareScopeUpdate,
91
} from './ReactFiberHostConfig';
92
import {
93
getRootHostContainer,
@@ -138,7 +139,7 @@ import {createFundamentalStateInstance} from './ReactFiberFundamental.new';
139
import {Never, isSameOrHigherPriority} from './ReactFiberExpirationTime.new';
140
import {resetChildFibers} from './ReactChildFiber.new';
141
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.new';
141
-import {createScopeMethods} from './ReactFiberScope.new';
142
+import {createScopeInstance} from './ReactFiberScope.new';
143
144
function markUpdate(workInProgress: Fiber) {
145
// Tag the fiber with an update effect. This turns a Placement into
@@ -1247,13 +1248,8 @@ function completeWork(
1248
case ScopeComponent: {
1249
if (enableScopeAPI) {
1250
if (current === null) {
1250
- const type = workInProgress.type;
1251
- const scopeInstance: ReactScopeInstance = {
1252
- fiber: workInProgress,
1253
- methods: null,
1254
- };
1251
+ const scopeInstance: ReactScopeInstance = createScopeInstance();
1252
workInProgress.stateNode = scopeInstance;
1256
- scopeInstance.methods = createScopeMethods(type, scopeInstance);
1253
if (enableDeprecatedFlareAPI) {
1254
const listeners = newProps.DEPRECATED_flareListeners;
1255
if (listeners != null) {
@@ -1265,6 +1261,7 @@ function completeWork(
1261
);
1262
}
1263
}
1264
+ prepareScopeUpdate(scopeInstance, workInProgress);
1265
if (workInProgress.ref !== null) {
1266
markRef(workInProgress);
1267
markUpdate(workInProgress);
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+4
-7
@@ -84,6 +84,7 @@ import {
84
cloneFundamentalInstance,
85
shouldUpdateFundamentalComponent,
86
preparePortalMount,
87
+ prepareScopeUpdate,
88
} from './ReactFiberHostConfig';
89
import {
90
getRootHostContainer,
@@ -134,7 +135,7 @@ import {createFundamentalStateInstance} from './ReactFiberFundamental.old';
135
import {Never} from './ReactFiberExpirationTime.old';
136
import {resetChildFibers} from './ReactChildFiber.old';
137
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.old';
137
-import {createScopeMethods} from './ReactFiberScope.old';
138
+import {createScopeInstance} from './ReactFiberScope.old';
139
140
function markUpdate(workInProgress: Fiber) {
141
// Tag the fiber with an update effect. This turns a Placement into
@@ -1262,13 +1263,8 @@ function completeWork(
1263
case ScopeComponent: {
1264
if (enableScopeAPI) {
1265
if (current === null) {
1265
- const type = workInProgress.type;
1266
- const scopeInstance: ReactScopeInstance = {
1267
- fiber: workInProgress,
1268
- methods: null,
1269
- };
1266
+ const scopeInstance: ReactScopeInstance = createScopeInstance();
1267
workInProgress.stateNode = scopeInstance;
1271
- scopeInstance.methods = createScopeMethods(type, scopeInstance);
1268
if (enableDeprecatedFlareAPI) {
1269
const listeners = newProps.DEPRECATED_flareListeners;
1270
if (listeners != null) {
@@ -1280,6 +1276,7 @@ function completeWork(
1276
);
1277
}
1278
}
1279
+ prepareScopeUpdate(scopeInstance, workInProgress);
1280
if (workInProgress.ref !== null) {
1281
markRef(workInProgress);
1282
markUpdate(workInProgress);
packages/react-reconciler/src/ReactFiberHostConfigWithNoScopes.js
new
+27
@@ -0,0 +1,27 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import invariant from 'shared/invariant';
11
+
12
+// Renderers that don't support React Scopes
13
+// can re-export everything from this module.
14
+
15
+function shim(...args: any) {
16
+ invariant(
17
+ false,
18
+ 'The current renderer does not support React Scopes. ' +
19
+ 'This error is likely caused by a bug in React. ' +
20
+ 'Please file an issue.',
21
+ );
22
+}
23
+
24
+// React Scopes (when unsupported)
25
+export const prepareScopeUpdate = shim;
26
+export const prepareScopeUnmount = shim;
27
+export const getInstanceFromScope = shim;
packages/react-reconciler/src/ReactFiberScope.new.js
+59
-47
@@ -9,14 +9,16 @@
9
10
import type {Fiber} from './ReactInternalTypes';
11
import type {
12
- ReactScope,
12
ReactScopeInstance,
14
- ReactScopeMethods,
13
ReactContext,
14
ReactScopeQuery,
15
} from 'shared/ReactTypes';
16
19
-import {getPublicInstance, getInstanceFromNode} from './ReactFiberHostConfig';
17
+import {
18
+ getPublicInstance,
19
+ getInstanceFromNode,
20
+ getInstanceFromScope,
21
+} from './ReactFiberHostConfig';
22
import {isFiberSuspenseAndTimedOut} from './ReactFiberTreeReflection';
23
24
import {HostComponent, ScopeComponent, ContextProvider} from './ReactWorkTags';
@@ -138,50 +140,60 @@ function collectNearestChildContextValues<T>(
140
}
141
}
142
141
-export function createScopeMethods(
142
- scope: ReactScope,
143
- instance: ReactScopeInstance,
144
-): ReactScopeMethods {
143
+function DO_NOT_USE_queryAllNodes(fn: ReactScopeQuery): null | Array<Object> {
144
+ const currentFiber = getInstanceFromScope(this);
145
+ if (currentFiber === null) {
146
+ return null;
147
+ }
148
+ const child = currentFiber.child;
149
+ const scopedNodes = [];
150
+ if (child !== null) {
151
+ collectScopedNodesFromChildren(child, fn, scopedNodes);
152
+ }
153
+ return scopedNodes.length === 0 ? null : scopedNodes;
154
+}
155
+
156
+function DO_NOT_USE_queryFirstNode(fn: ReactScopeQuery): null | Object {
157
+ const currentFiber = getInstanceFromScope(this);
158
+ if (currentFiber === null) {
159
+ return null;
160
+ }
161
+ const child = currentFiber.child;
162
+ if (child !== null) {
163
+ return collectFirstScopedNodeFromChildren(child, fn);
164
+ }
165
+ return null;
166
+}
167
+
168
+function containsNode(node: Object): boolean {
169
+ let fiber = getInstanceFromNode(node);
170
+ while (fiber !== null) {
171
+ if (fiber.tag === ScopeComponent && fiber.stateNode === this) {
172
+ return true;
173
+ }
174
+ fiber = fiber.return;
175
+ }
176
+ return false;
177
+}
178
+
179
+function getChildContextValues<T>(context: ReactContext<T>): Array<T> {
180
+ const currentFiber = getInstanceFromScope(this);
181
+ if (currentFiber === null) {
182
+ return [];
183
+ }
184
+ const child = currentFiber.child;
185
+ const childContextValues = [];
186
+ if (child !== null) {
187
+ collectNearestChildContextValues(child, context, childContextValues);
188
+ }
189
+ return childContextValues;
190
+}
191
+
192
+export function createScopeInstance(): ReactScopeInstance {
193
return {
146
- DO_NOT_USE_queryAllNodes(fn: ReactScopeQuery): null | Array<Object> {
147
- const currentFiber = ((instance.fiber: any): Fiber);
148
- const child = currentFiber.child;
149
- const scopedNodes = [];
150
- if (child !== null) {
151
- collectScopedNodesFromChildren(child, fn, scopedNodes);
152
- }
153
- return scopedNodes.length === 0 ? null : scopedNodes;
154
- },
155
- DO_NOT_USE_queryFirstNode(fn: ReactScopeQuery): null | Object {
156
- const currentFiber = ((instance.fiber: any): Fiber);
157
- const child = currentFiber.child;
158
- if (child !== null) {
159
- return collectFirstScopedNodeFromChildren(child, fn);
160
- }
161
- return null;
162
- },
163
- containsNode(node: Object): boolean {
164
- let fiber = getInstanceFromNode(node);
165
- while (fiber !== null) {
166
- if (
167
- fiber.tag === ScopeComponent &&
168
- fiber.type === scope &&
169
- fiber.stateNode === instance
170
- ) {
171
- return true;
172
- }
173
- fiber = fiber.return;
174
- }
175
- return false;
176
- },
177
- getChildContextValues<T>(context: ReactContext<T>): Array<T> {
178
- const currentFiber = ((instance.fiber: any): Fiber);
179
- const child = currentFiber.child;
180
- const childContextValues = [];
181
- if (child !== null) {
182
- collectNearestChildContextValues(child, context, childContextValues);
183
- }
184
- return childContextValues;
185
- },
194
+ DO_NOT_USE_queryAllNodes,
195
+ DO_NOT_USE_queryFirstNode,
196
+ containsNode,
197
+ getChildContextValues,
198
};
199
}
packages/react-reconciler/src/ReactFiberScope.old.js
+59
-47
@@ -9,14 +9,16 @@
9
10
import type {Fiber} from './ReactInternalTypes';
11
import type {
12
- ReactScope,
12
ReactScopeInstance,
14
- ReactScopeMethods,
13
ReactContext,
14
ReactScopeQuery,
15
} from 'shared/ReactTypes';
16
19
-import {getPublicInstance, getInstanceFromNode} from './ReactFiberHostConfig';
17
+import {
18
+ getPublicInstance,
19
+ getInstanceFromNode,
20
+ getInstanceFromScope,
21
+} from './ReactFiberHostConfig';
22
import {isFiberSuspenseAndTimedOut} from './ReactFiberTreeReflection';
23
24
import {HostComponent, ScopeComponent, ContextProvider} from './ReactWorkTags';
@@ -138,50 +140,60 @@ function collectNearestChildContextValues<T>(
140
}
141
}
142
141
-export function createScopeMethods(
142
- scope: ReactScope,
143
- instance: ReactScopeInstance,
144
-): ReactScopeMethods {
143
+function DO_NOT_USE_queryAllNodes(fn: ReactScopeQuery): null | Array<Object> {
144
+ const currentFiber = getInstanceFromScope(this);
145
+ if (currentFiber === null) {
146
+ return null;
147
+ }
148
+ const child = currentFiber.child;
149
+ const scopedNodes = [];
150
+ if (child !== null) {
151
+ collectScopedNodesFromChildren(child, fn, scopedNodes);
152
+ }
153
+ return scopedNodes.length === 0 ? null : scopedNodes;
154
+}
155
+
156
+function DO_NOT_USE_queryFirstNode(fn: ReactScopeQuery): null | Object {
157
+ const currentFiber = getInstanceFromScope(this);
158
+ if (currentFiber === null) {
159
+ return null;
160
+ }
161
+ const child = currentFiber.child;
162
+ if (child !== null) {
163
+ return collectFirstScopedNodeFromChildren(child, fn);
164
+ }
165
+ return null;
166
+}
167
+
168
+function containsNode(node: Object): boolean {
169
+ let fiber = getInstanceFromNode(node);
170
+ while (fiber !== null) {
171
+ if (fiber.tag === ScopeComponent && fiber.stateNode === this) {
172
+ return true;
173
+ }
174
+ fiber = fiber.return;
175
+ }
176
+ return false;
177
+}
178
+
179
+function getChildContextValues<T>(context: ReactContext<T>): Array<T> {
180
+ const currentFiber = getInstanceFromScope(this);
181
+ if (currentFiber === null) {
182
+ return [];
183
+ }
184
+ const child = currentFiber.child;
185
+ const childContextValues = [];
186
+ if (child !== null) {
187
+ collectNearestChildContextValues(child, context, childContextValues);
188
+ }
189
+ return childContextValues;
190
+}
191
+
192
+export function createScopeInstance(): ReactScopeInstance {
193
return {
146
- DO_NOT_USE_queryAllNodes(fn: ReactScopeQuery): null | Array<Object> {
147
- const currentFiber = ((instance.fiber: any): Fiber);
148
- const child = currentFiber.child;
149
- const scopedNodes = [];
150
- if (child !== null) {
151
- collectScopedNodesFromChildren(child, fn, scopedNodes);
152
- }
153
- return scopedNodes.length === 0 ? null : scopedNodes;
154
- },
155
- DO_NOT_USE_queryFirstNode(fn: ReactScopeQuery): null | Object {
156
- const currentFiber = ((instance.fiber: any): Fiber);
157
- const child = currentFiber.child;
158
- if (child !== null) {
159
- return collectFirstScopedNodeFromChildren(child, fn);
160
- }
161
- return null;
162
- },
163
- containsNode(node: Object): boolean {
164
- let fiber = getInstanceFromNode(node);
165
- while (fiber !== null) {
166
- if (
167
- fiber.tag === ScopeComponent &&
168
- fiber.type === scope &&
169
- fiber.stateNode === instance
170
- ) {
171
- return true;
172
- }
173
- fiber = fiber.return;
174
- }
175
- return false;
176
- },
177
- getChildContextValues<T>(context: ReactContext<T>): Array<T> {
178
- const currentFiber = ((instance.fiber: any): Fiber);
179
- const child = currentFiber.child;
180
- const childContextValues = [];
181
- if (child !== null) {
182
- collectNearestChildContextValues(child, context, childContextValues);
183
- }
184
- return childContextValues;
185
- },
194
+ DO_NOT_USE_queryAllNodes,
195
+ DO_NOT_USE_queryFirstNode,
196
+ containsNode,
197
+ getChildContextValues,
198
};
199
}
packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js
+3
@@ -84,6 +84,9 @@ export const makeServerId = $$$hostConfig.makeServerId;
84
export const beforeActiveInstanceBlur = $$$hostConfig.beforeActiveInstanceBlur;
85
export const afterActiveInstanceBlur = $$$hostConfig.afterActiveInstanceBlur;
86
export const preparePortalMount = $$$hostConfig.preparePortalMount;
87
+export const prepareScopeUpdate = $$$hostConfig.preparePortalMount;
88
+export const prepareScopeUnmount = $$$hostConfig.prepareScopeUnmount;
89
+export const getInstanceFromScope = $$$hostConfig.getInstanceFromScope;
90
91
// -------------------
92
// Mutation
packages/react-test-renderer/src/ReactTestHostConfig.js
+12
@@ -443,3 +443,15 @@ export function afterActiveInstanceBlur() {
443
export function preparePortalMount(portalInstance: Instance): void {
444
// noop
445
}
446
+
447
+export function prepareScopeUpdate(scopeInstance: Object, inst: Object): void {
448
+ nodeToInstanceMap.set(scopeInstance, inst);
449
+}
450
+
451
+export function prepareScopeUnmount(scopeInstance: Object): void {
452
+ nodeToInstanceMap.delete(scopeInstance);
453
+}
454
+
455
+export function getInstanceFromScope(scopeInstance: Object): null | Object {
456
+ return nodeToInstanceMap.get(scopeInstance) || null;
457
+}
packages/shared/ReactTypes.js
+1
-6
@@ -179,18 +179,13 @@ export type ReactScopeQuery = (
179
instance: mixed,
180
) => boolean;
181
182
-export type ReactScopeMethods = {|
182
+export type ReactScopeInstance = {|
183
DO_NOT_USE_queryAllNodes(ReactScopeQuery): null | Array<Object>,
184
DO_NOT_USE_queryFirstNode(ReactScopeQuery): null | Object,
185
containsNode(Object): boolean,
186
getChildContextValues: <T>(context: ReactContext<T>) => Array<T>,
187
|};
188
189
-export type ReactScopeInstance = {|
190
- fiber: Object,
191
- methods: null | ReactScopeMethods,
192
-|};
193
-
189
// Mutable source version can be anything (e.g. number, string, immutable data structure)
190
// so long as it changes every time any part of the source changes.
191
export type MutableSourceVersion = $NonMaybeType<mixed>;
scripts/error-codes/codes.json
+2
-1
@@ -353,5 +353,6 @@
353
"353": "A server block should never encode any other slots. This is a bug in React.",
354
"354": "getInspectorDataForViewAtPoint() is not available in production.",
355
"355": "The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.",
356
- "356": "Could not read the cache."
356
+ "356": "Could not read the cache.",
357
+ "357": "The current renderer does not support React Scopes. This error is likely caused by a bug in React. Please file an issue."
358
}