Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[React Native] Add getInspectorDataForViewAtPoint #18233

Merged
merged 11 commits into from
Mar 11, 2020
9 changes: 8 additions & 1 deletion packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import ReactVersion from 'shared/ReactVersion';
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';

import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
import {
getInspectorDataForViewAtPoint,
getInspectorDataForViewTag,
} from './ReactNativeFiberInspector';

import {LegacyRoot} from 'shared/ReactRootTags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
Expand Down Expand Up @@ -233,6 +236,10 @@ export {
injectIntoDevTools({
findFiberByHostInstance: getClosestInstanceFromNode,
getInspectorDataForViewTag: getInspectorDataForViewTag,
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind(
null,
findNodeHandle,
),
bundleType: __DEV__ ? 1 : 0,
version: ReactVersion,
rendererPackageName: 'react-native-renderer',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,17 @@ class ReactNativeFiberHostComponent {
_children: Array<Instance | number>;
_nativeTag: number;
viewConfig: ReactNativeBaseComponentViewConfig<>;
_internalFiberInstanceHandle: Object;

constructor(tag: number, viewConfig: ReactNativeBaseComponentViewConfig<>) {
constructor(
tag: number,
viewConfig: ReactNativeBaseComponentViewConfig<>,
internalInstanceHandle: Object,
) {
this._nativeTag = tag;
this._children = [];
this.viewConfig = viewConfig;
this._internalFiberInstanceHandle = internalInstanceHandle;
}

blur() {
Expand Down
113 changes: 112 additions & 1 deletion packages/react-native-renderer/src/ReactNativeFiberInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
*/

import type {Fiber} from 'react-reconciler/src/ReactFiber';
import type {
ReactFabricType,
HostComponent as ReactNativeHostComponent,
} from './ReactNativeTypes';

import {
findCurrentHostFiber,
Expand All @@ -27,6 +31,7 @@ if (__DEV__) {
}

let getInspectorDataForViewTag;
let getInspectorDataForViewAtPoint;

if (__DEV__) {
const traverseOwnerTreeUp = function(hierarchy, instance: any) {
Expand Down Expand Up @@ -89,6 +94,34 @@ if (__DEV__) {
}));
};

const getInspectorDataForInstance = function(closestInstance, frame): Object {
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
// Handle case where user clicks outside of ReactNative
if (!closestInstance) {
return {
hierarchy: [],
props: emptyObject,
selection: null,
source: null,
};
}

const fiber = findCurrentFiberUsingSlowPath(closestInstance);
const fiberHierarchy = getOwnerHierarchy(fiber);
const instance = lastNonHostInstance(fiberHierarchy);
const hierarchy = createHierarchy(fiberHierarchy);
const props = getHostProps(instance);
const source = instance._debugSource;
const selection = fiberHierarchy.indexOf(instance);

return {
hierarchy,
frame,
props,
selection,
source,
};
};

getInspectorDataForViewTag = function(viewTag: number): Object {
const closestInstance = getClosestInstanceFromNode(viewTag);

Expand Down Expand Up @@ -117,13 +150,91 @@ if (__DEV__) {
source,
};
};

getInspectorDataForViewAtPoint = function(
findNodeHandle,
inspectedView: ?React.ElementRef<ReactNativeHostComponent<mixed>>,
x: number,
y: number,
callback: (obj: Object) => mixed,
): void {
let closestInstance = null;
let frame = {
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
left: 0,
top: 0,
width: 0,
height: 0,
};

if (inspectedView._internalInstanceHandle != null) {
// For Fabric we can look up the instance handle directly and measure it.
nativeFabricUIManager.findNodeAtPoint(
inspectedView._internalInstanceHandle.stateNode.node,
x,
y,
shadowNode => {
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
if (shadowNode == null) {
callback(getInspectorDataForInstance(closestInstance, frame));
}

closestInstance =
shadowNode.stateNode.canonical._internalInstanceHandle;
nativeFabricUIManager.measure(
shadowNode.stateNode.node,
(x, y, width, height, pageX, pageY) => {
frame = {
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
left: pageX,
top: pageY,
width,
height,
};

callback(getInspectorDataForInstance(closestInstance, frame));
},
);
},
);
} else if (inspectedView._internalFiberInstanceHandle != null) {
// For Paper we fall back to the old strategy using the React tag.
UIManager.findSubviewIn(
findNodeHandle(inspectedView),
[x, y],
(nativeViewTag, left, top, width, height) => {
frame = {
left,
top,
width,
height,
};
const inspectorData = getInspectorDataForInstance(
getClosestInstanceFromNode(nativeViewTag),
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
frame,
);
callback({...inspectorData, nativeViewTag});
rickhanlonii marked this conversation as resolved.
Show resolved Hide resolved
},
);
} else if (__DEV__) {
console.error(
'getInspectorDataForViewAtPoint expects to receieve a host component',
);

return;
}
};
} else {
getInspectorDataForViewTag = () => {
invariant(
false,
'getInspectorDataForViewTag() is not available in production',
);
};

getInspectorDataForViewAtPoint = () => {
invariant(
false,
'getInspectorDataForViewAtPoint() is not available in production',
);
};
}

export {getInspectorDataForViewTag};
export {getInspectorDataForViewAtPoint, getInspectorDataForViewTag};
6 changes: 5 additions & 1 deletion packages/react-native-renderer/src/ReactNativeHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ export function createInstance(
updatePayload, // props
);

const component = new ReactNativeFiberHostComponent(tag, viewConfig);
const component = new ReactNativeFiberHostComponent(
tag,
viewConfig,
internalInstanceHandle,
);

precacheFiberNode(internalInstanceHandle, tag);
updateFiberProps(tag, props);
Expand Down
9 changes: 8 additions & 1 deletion packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ import ReactVersion from 'shared/ReactVersion';
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';

import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
import {
getInspectorDataForViewTag,
getInspectorDataForViewAtPoint,
} from './ReactNativeFiberInspector';

import {LegacyRoot} from 'shared/ReactRootTags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
Expand Down Expand Up @@ -247,6 +250,10 @@ export {
injectIntoDevTools({
findFiberByHostInstance: getClosestInstanceFromNode,
getInspectorDataForViewTag: getInspectorDataForViewTag,
getInspectorDataForViewAtPoint: getInspectorDataForViewAtPoint.bind(
null,
findNodeHandle,
),
bundleType: __DEV__ ? 1 : 0,
version: ReactVersion,
rendererPackageName: 'react-native-renderer',
Expand Down