Skip to content

Commit 74eaf3e

Browse files
author
Brian Vaughn
committed
Export getInspectorDataForInstance API in Facebook RN builds
This API can be used (even in production builds) to support internal UI review tools like UIQR/PFH
1 parent bb1c821 commit 74eaf3e

12 files changed

+88
-63
lines changed

packages/react-native-renderer/src/ReactFabric.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
injectIntoDevTools,
2525
getPublicRootInstance,
2626
} from 'react-reconciler/src/ReactFiberReconciler';
27+
import {getInspectorDataForInstance} from './ReactNativeFiberInspector';
2728

2829
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
2930
import {setBatchingImplementation} from './legacy-events/ReactGenericBatching';
@@ -267,6 +268,8 @@ export {
267268
unmountComponentAtNode,
268269
stopSurface,
269270
createPortal,
271+
// Used by internal Facebook production builds to support a UI review tool.
272+
getInspectorDataForInstance,
270273
};
271274

272275
injectIntoDevTools({

packages/react-native-renderer/src/ReactNativeFiberInspector.js

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -19,67 +19,24 @@ import {HostComponent} from 'react-reconciler/src/ReactWorkTags';
1919
import invariant from 'shared/invariant';
2020
// Module provided by RN:
2121
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
22-
22+
import {enableGetInspectorDataForInstanceInProduction} from 'shared/ReactFeatureFlags';
2323
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
2424

2525
const emptyObject = {};
2626
if (__DEV__) {
2727
Object.freeze(emptyObject);
2828
}
2929

30-
let getInspectorDataForViewTag;
31-
let getInspectorDataForViewAtPoint;
32-
33-
if (__DEV__) {
34-
const traverseOwnerTreeUp = function(hierarchy, instance: any) {
35-
if (instance) {
36-
hierarchy.unshift(instance);
37-
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
38-
}
39-
};
40-
41-
const getOwnerHierarchy = function(instance: any) {
42-
const hierarchy = [];
43-
traverseOwnerTreeUp(hierarchy, instance);
44-
return hierarchy;
45-
};
46-
47-
const lastNonHostInstance = function(hierarchy) {
48-
for (let i = hierarchy.length - 1; i > 1; i--) {
49-
const instance = hierarchy[i];
50-
51-
if (instance.tag !== HostComponent) {
52-
return instance;
53-
}
54-
}
55-
return hierarchy[0];
56-
};
57-
58-
const getHostProps = function(fiber) {
59-
const host = findCurrentHostFiber(fiber);
60-
if (host) {
61-
return host.memoizedProps || emptyObject;
62-
}
63-
return emptyObject;
64-
};
65-
66-
const getHostNode = function(fiber: Fiber | null, findNodeHandle) {
67-
let hostNode;
68-
// look for children first for the hostNode
69-
// as composite fibers do not have a hostNode
70-
while (fiber) {
71-
if (fiber.stateNode !== null && fiber.tag === HostComponent) {
72-
hostNode = findNodeHandle(fiber.stateNode);
73-
}
74-
if (hostNode) {
75-
return hostNode;
76-
}
77-
fiber = fiber.child;
78-
}
79-
return null;
80-
};
30+
let createHierarchy;
31+
let getHostNode;
32+
let getHostProps;
33+
let lastNonHostInstance;
34+
let getInspectorDataForInstance;
35+
let getOwnerHierarchy;
36+
let traverseOwnerTreeUp;
8137

82-
const createHierarchy = function(fiberHierarchy) {
38+
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
39+
createHierarchy = function(fiberHierarchy) {
8340
return fiberHierarchy.map(fiber => ({
8441
name: getComponentNameFromType(fiber.type),
8542
getInspectorData: findNodeHandle => {
@@ -108,7 +65,33 @@ if (__DEV__) {
10865
}));
10966
};
11067

111-
const getInspectorDataForInstance = function(closestInstance): InspectorData {
68+
getHostNode = function(fiber: Fiber | null, findNodeHandle) {
69+
let hostNode;
70+
// look for children first for the hostNode
71+
// as composite fibers do not have a hostNode
72+
while (fiber) {
73+
if (fiber.stateNode !== null && fiber.tag === HostComponent) {
74+
hostNode = findNodeHandle(fiber.stateNode);
75+
}
76+
if (hostNode) {
77+
return hostNode;
78+
}
79+
fiber = fiber.child;
80+
}
81+
return null;
82+
};
83+
84+
getHostProps = function(fiber) {
85+
const host = findCurrentHostFiber(fiber);
86+
if (host) {
87+
return host.memoizedProps || emptyObject;
88+
}
89+
return emptyObject;
90+
};
91+
92+
getInspectorDataForInstance = function(
93+
closestInstance: Fiber | null,
94+
): InspectorData {
11295
// Handle case where user clicks outside of ReactNative
11396
if (!closestInstance) {
11497
return {
@@ -135,6 +118,35 @@ if (__DEV__) {
135118
};
136119
};
137120

121+
getOwnerHierarchy = function(instance: any) {
122+
const hierarchy = [];
123+
traverseOwnerTreeUp(hierarchy, instance);
124+
return hierarchy;
125+
};
126+
127+
lastNonHostInstance = function(hierarchy) {
128+
for (let i = hierarchy.length - 1; i > 1; i--) {
129+
const instance = hierarchy[i];
130+
131+
if (instance.tag !== HostComponent) {
132+
return instance;
133+
}
134+
}
135+
return hierarchy[0];
136+
};
137+
138+
traverseOwnerTreeUp = function(hierarchy, instance: any) {
139+
if (instance) {
140+
hierarchy.unshift(instance);
141+
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
142+
}
143+
};
144+
}
145+
146+
let getInspectorDataForViewTag;
147+
let getInspectorDataForViewAtPoint;
148+
149+
if (__DEV__) {
138150
getInspectorDataForViewTag = function(viewTag: number): Object {
139151
const closestInstance = getClosestInstanceFromNode(viewTag);
140152

@@ -258,4 +270,8 @@ if (__DEV__) {
258270
};
259271
}
260272

261-
export {getInspectorDataForViewAtPoint, getInspectorDataForViewTag};
273+
export {
274+
getInspectorDataForInstance,
275+
getInspectorDataForViewAtPoint,
276+
getInspectorDataForViewTag,
277+
};

packages/react-native-renderer/src/ReactNativeRenderer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
UIManager,
3838
legacySendAccessibilityEvent,
3939
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
40+
import {getInspectorDataForInstance} from './ReactNativeFiberInspector';
4041

4142
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
4243
import {
@@ -270,6 +271,8 @@ export {
270271
createPortal,
271272
batchedUpdates as unstable_batchedUpdates,
272273
Internals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
274+
// Used by internal Facebook production builds to support a UI review tool.
275+
getInspectorDataForInstance,
273276
};
274277

275278
injectIntoDevTools({

packages/shared/ReactFeatureFlags.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ export const enableNewReconciler = false;
106106

107107
export const disableNativeComponentFrames = false;
108108

109+
// Used by React Native in Facebook internal builds for UI review tools.
110+
export const enableGetInspectorDataForInstanceInProduction = false;
111+
109112
// Errors that are thrown while unmounting (or after in the case of passive effects)
110113
// should bypass any error boundaries that are also unmounting (or have unmounted)
111114
// and be handled by the nearest still-mounted boundary.

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const disableNativeComponentFrames = false;
4848
export const skipUnmountedBoundaries = false;
4949
export const deletedTreeCleanUpLevel = 1;
5050
export const enableSuspenseLayoutEffectSemantics = false;
51-
51+
export const enableGetInspectorDataForInstanceInProduction = true;
5252
export const enableNewReconciler = false;
5353
export const deferRenderPhaseUpdateToNextBatch = true;
5454

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.test-renderer.native.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.testing.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = false;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.testing.www.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const disableNativeComponentFrames = false;
4747
export const skipUnmountedBoundaries = true;
4848
export const deletedTreeCleanUpLevel = 1;
4949
export const enableSuspenseLayoutEffectSemantics = false;
50-
50+
export const enableGetInspectorDataForInstanceInProduction = false;
5151
export const enableNewReconciler = false;
5252
export const deferRenderPhaseUpdateToNextBatch = true;
5353

packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const warnAboutDeprecatedLifecycles = true;
6060
export const disableLegacyContext = __EXPERIMENTAL__;
6161
export const warnAboutStringRefs = false;
6262
export const warnAboutDefaultPropsOnFunctionComponents = false;
63-
63+
export const enableGetInspectorDataForInstanceInProduction = false;
6464
export const enableSuspenseServerRenderer = true;
6565
export const enableSelectiveHydration = true;
6666

0 commit comments

Comments
 (0)