From d66fa02a303fc53d901bdb0d7bbdaec3e6774b19 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 26 Sep 2024 10:17:16 +0100 Subject: [PATCH] fix: use public instance in Fiber renderer and expose it from getInspectorDataForViewAtPoint (#31068) React DevTools no longer operates with just Fibers, it now builds its own Shadow Tree, which represents the tree on the Host (Fabric on Native, DOM on Web). We have to keep track of public instances for a select-to-inspect feature. We've recently changed this logic in https://github.com/facebook/react/pull/30831, and looks like we've been incorrectly getting a public instance for Fabric case. Not only this, turns out that all `getInspectorData...` APIs are returning Fibers, and not public instances. I have to expose it, so that React DevTools can correctly identify the element, which was selected. Changes for React Native are in [D63421463](https://www.internalfb.com/diff/D63421463) --- .../src/backend/fiber/renderer.js | 28 ++++++++++++++----- .../src/ReactNativeFiberInspector.js | 4 +++ .../src/ReactNativeTypes.js | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/react-devtools-shared/src/backend/fiber/renderer.js b/packages/react-devtools-shared/src/backend/fiber/renderer.js index d93e713911..22a7afcc4c 100644 --- a/packages/react-devtools-shared/src/backend/fiber/renderer.js +++ b/packages/react-devtools-shared/src/backend/fiber/renderer.js @@ -763,16 +763,30 @@ const hostResourceToDevToolsInstanceMap: Map< Set, > = new Map(); +// Ideally, this should be injected from Reconciler config function getPublicInstance(instance: HostInstance): HostInstance { // Typically the PublicInstance and HostInstance is the same thing but not in Fabric. // So we need to detect this and use that as the public instance. - return typeof instance === 'object' && - instance !== null && - typeof instance.canonical === 'object' - ? (instance.canonical: any) - : typeof instance._nativeTag === 'number' - ? instance._nativeTag - : instance; + + // React Native. Modern. Fabric. + if (typeof instance === 'object' && instance !== null) { + if (typeof instance.canonical === 'object' && instance.canonical !== null) { + if ( + typeof instance.canonical.publicInstance === 'object' && + instance.canonical.publicInstance !== null + ) { + return instance.canonical.publicInstance; + } + } + + // React Native. Legacy. Paper. + if (typeof instance._nativeTag === 'number') { + return instance._nativeTag; + } + } + + // React Web. Usually a DOM element. + return instance; } function aquireHostInstance( diff --git a/packages/react-native-renderer/src/ReactNativeFiberInspector.js b/packages/react-native-renderer/src/ReactNativeFiberInspector.js index b0859471c4..d0423f1d48 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberInspector.js +++ b/packages/react-native-renderer/src/ReactNativeFiberInspector.js @@ -209,6 +209,8 @@ function getInspectorDataForViewAtPoint( closestInstance = internalInstanceHandle.stateNode.canonical.internalInstanceHandle; + const closestPublicInstance = + internalInstanceHandle.stateNode.canonical.publicInstance; // Note: this is deprecated and we want to remove it ASAP. Keeping it here for React DevTools compatibility for now. const nativeViewTag = @@ -224,6 +226,7 @@ function getInspectorDataForViewAtPoint( pointerY: locationY, frame: {left: pageX, top: pageY, width, height}, touchedViewTag: nativeViewTag, + closestPublicInstance, }); }, ); @@ -243,6 +246,7 @@ function getInspectorDataForViewAtPoint( pointerY: locationY, frame: {left, top, width, height}, touchedViewTag: nativeViewTag, + closestPublicInstance: nativeViewTag, }); }, ); diff --git a/packages/react-native-renderer/src/ReactNativeTypes.js b/packages/react-native-renderer/src/ReactNativeTypes.js index 000ea0d0f7..9692a1256a 100644 --- a/packages/react-native-renderer/src/ReactNativeTypes.js +++ b/packages/react-native-renderer/src/ReactNativeTypes.js @@ -179,6 +179,7 @@ export type TouchedViewDataAtPoint = $ReadOnly<{ width: number, height: number, }>, + closestPublicInstance?: PublicInstance, ...InspectorData, }>;