Skip to content

Commit

Permalink
fix: use public instance in Fiber renderer and expose it from getInsp…
Browse files Browse the repository at this point in the history
…ectorDataForViewAtPoint (#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
#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)
  • Loading branch information
hoxyq authored Sep 26, 2024
1 parent 778e1ed commit d66fa02
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
28 changes: 21 additions & 7 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -224,6 +226,7 @@ function getInspectorDataForViewAtPoint(
pointerY: locationY,
frame: {left: pageX, top: pageY, width, height},
touchedViewTag: nativeViewTag,
closestPublicInstance,
});
},
);
Expand All @@ -243,6 +246,7 @@ function getInspectorDataForViewAtPoint(
pointerY: locationY,
frame: {left, top, width, height},
touchedViewTag: nativeViewTag,
closestPublicInstance: nativeViewTag,
});
},
);
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-renderer/src/ReactNativeTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export type TouchedViewDataAtPoint = $ReadOnly<{
width: number,
height: number,
}>,
closestPublicInstance?: PublicInstance,
...InspectorData,
}>;

Expand Down

0 comments on commit d66fa02

Please sign in to comment.