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)
This commit is contained in:
Ruslan Lesiutin 2024-09-26 10:17:16 +01:00 committed by GitHub
parent 778e1ed2e5
commit d66fa02a30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 7 deletions

View File

@ -763,16 +763,30 @@ const hostResourceToDevToolsInstanceMap: Map<
Set<DevToolsInstance>,
> = 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(

View File

@ -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,
});
},
);

View File

@ -179,6 +179,7 @@ export type TouchedViewDataAtPoint = $ReadOnly<{
width: number,
height: number,
}>,
closestPublicInstance?: PublicInstance,
...InspectorData,
}>;