Skip to content

Commit cad8d43

Browse files
committed
Allow highlighting/inspect HostSingletons/Hoistables and Resources
1 parent 06d0b89 commit cad8d43

File tree

5 files changed

+52
-23
lines changed

5 files changed

+52
-23
lines changed

packages/react-devtools-shared/src/backend/fiber/renderer.js

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,11 +2695,11 @@ export function attach(
26952695
// If we're tracing updates and we've bailed out before reaching a host node,
26962696
// we should fall back to recursively marking the nearest host descendants for highlight.
26972697
if (traceNearestHostComponentUpdate) {
2698-
const hostFibers = findAllCurrentHostFibers(
2698+
const hostInstances = findAllCurrentHostInstances(
26992699
getFiberInstanceThrows(nextFiber),
27002700
);
2701-
hostFibers.forEach(hostFiber => {
2702-
traceUpdatesForNodes.add(hostFiber.stateNode);
2701+
hostInstances.forEach(hostInstance => {
2702+
traceUpdatesForNodes.add(hostInstance);
27032703
});
27042704
}
27052705
}
@@ -2943,31 +2943,54 @@ export function attach(
29432943
currentRootID = -1;
29442944
}
29452945

2946-
function findAllCurrentHostFibers(
2946+
function getResourceInstance(fiber: Fiber): HostInstance | null {
2947+
if (fiber.tag === HostHoistable) {
2948+
const resource = fiber.memoizedState;
2949+
// Feature Detect a DOM Specific Instance of a Resource
2950+
if (
2951+
typeof resource === 'object' &&
2952+
resource !== null &&
2953+
resource.instance != null
2954+
) {
2955+
return resource.instance;
2956+
}
2957+
}
2958+
return null;
2959+
}
2960+
2961+
function findAllCurrentHostInstances(
29472962
fiberInstance: FiberInstance,
2948-
): $ReadOnlyArray<Fiber> {
2949-
const fibers = [];
2963+
): $ReadOnlyArray<HostInstance> {
2964+
const hostInstances = [];
29502965
const fiber = findCurrentFiberUsingSlowPathByFiberInstance(fiberInstance);
29512966
if (!fiber) {
2952-
return fibers;
2967+
return hostInstances;
29532968
}
29542969

29552970
// Next we'll drill down this component to find all HostComponent/Text.
29562971
let node: Fiber = fiber;
29572972
while (true) {
2958-
if (node.tag === HostComponent || node.tag === HostText) {
2959-
fibers.push(node);
2973+
if (
2974+
node.tag === HostComponent ||
2975+
node.tag === HostText ||
2976+
node.tag === HostSingleton ||
2977+
node.tag === HostHoistable
2978+
) {
2979+
const hostInstance = node.stateNode || getResourceInstance(fiber);
2980+
if (hostInstance) {
2981+
hostInstances.push(hostInstance);
2982+
}
29602983
} else if (node.child) {
29612984
node.child.return = node;
29622985
node = node.child;
29632986
continue;
29642987
}
29652988
if (node === fiber) {
2966-
return fibers;
2989+
return hostInstances;
29672990
}
29682991
while (!node.sibling) {
29692992
if (!node.return || node.return === fiber) {
2970-
return fibers;
2993+
return hostInstances;
29712994
}
29722995
node = node.return;
29732996
}
@@ -2976,7 +2999,7 @@ export function attach(
29762999
}
29773000
// Flow needs the return here, but ESLint complains about it.
29783001
// eslint-disable-next-line no-unreachable
2979-
return fibers;
3002+
return hostInstances;
29803003
}
29813004

29823005
function findHostInstancesForElementID(id: number) {
@@ -2996,8 +3019,8 @@ export function attach(
29963019
return null;
29973020
}
29983021

2999-
const hostFibers = findAllCurrentHostFibers(devtoolsInstance);
3000-
return hostFibers.map(hostFiber => hostFiber.stateNode).filter(Boolean);
3022+
const hostInstances = findAllCurrentHostInstances(devtoolsInstance);
3023+
return hostInstances;
30013024
} catch (err) {
30023025
// The fiber might have unmounted by now.
30033026
return null;

packages/react-devtools-shared/src/backend/types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export type GetElementIDForHostInstance = (
9494
) => number | null;
9595
export type FindHostInstancesForElementID = (
9696
id: number,
97-
) => ?Array<HostInstance>;
97+
) => null | $ReadOnlyArray<HostInstance>;
9898

9999
export type ReactProviderType<T> = {
100100
$$typeof: symbol | number,

packages/react-devtools-shared/src/backend/views/Highlighter/Highlighter.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ export function hideOverlay(agent: Agent): void {
3838
: hideOverlayWeb();
3939
}
4040

41-
function showOverlayNative(elements: Array<HostInstance>, agent: Agent): void {
41+
function showOverlayNative(
42+
elements: $ReadOnlyArray<HostInstance>,
43+
agent: Agent,
44+
): void {
4245
agent.emit('showNativeHighlight', elements);
4346
}
4447

4548
function showOverlayWeb(
46-
elements: Array<HTMLElement>,
49+
elements: $ReadOnlyArray<HTMLElement>,
4750
componentName: string | null,
4851
agent: Agent,
4952
hideAfterTimeout: boolean,
@@ -64,12 +67,17 @@ function showOverlayWeb(
6467
}
6568

6669
export function showOverlay(
67-
elements: Array<HostInstance>,
70+
elements: $ReadOnlyArray<HostInstance>,
6871
componentName: string | null,
6972
agent: Agent,
7073
hideAfterTimeout: boolean,
7174
): void {
7275
return isReactNativeEnvironment()
7376
? showOverlayNative(elements, agent)
74-
: showOverlayWeb((elements: any), componentName, agent, hideAfterTimeout);
77+
: showOverlayWeb(
78+
(elements: $ReadOnlyArray<any>),
79+
componentName,
80+
agent,
81+
hideAfterTimeout,
82+
);
7583
}

packages/react-devtools-shared/src/backend/views/Highlighter/Overlay.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export default class Overlay {
187187
}
188188
}
189189

190-
inspect(nodes: Array<HTMLElement>, name?: ?string) {
190+
inspect(nodes: $ReadOnlyArray<HTMLElement>, name?: ?string) {
191191
// We can't get the size of text nodes or comment nodes. React as of v15
192192
// heavily uses comment nodes to delimit text.
193193
const elements = nodes.filter(node => node.nodeType === Node.ELEMENT_NODE);

packages/react-devtools-shared/src/backend/views/Highlighter/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import Agent from 'react-devtools-shared/src/backend/agent';
1313
import {hideOverlay, showOverlay} from './Highlighter';
1414

1515
import type {BackendBridge} from 'react-devtools-shared/src/bridge';
16-
import type {HostInstance} from '../../types';
1716

1817
// This plug-in provides in-page highlighting of the selected element.
1918
// It is used by the browser extension and the standalone DevTools shell (when connected to a browser).
@@ -113,8 +112,7 @@ export default function setupHighlighter(
113112
return;
114113
}
115114

116-
const nodes: ?Array<HostInstance> =
117-
renderer.findHostInstancesForElementID(id);
115+
const nodes = renderer.findHostInstancesForElementID(id);
118116

119117
if (nodes != null && nodes[0] != null) {
120118
const node = nodes[0];

0 commit comments

Comments
 (0)