43
ComponentFilter,
44
BrowserTheme,
45
} from 'react-devtools-shared/src/frontend/types';
46
-import {isSynchronousXHRSupported} from './utils';
46
+import {isSynchronousXHRSupported, isReactNativeEnvironment} from './utils';
47
48
const debug = (methodName: string, ...args: Array<string>) => {
49
if (__DEBUG__) {
343
return renderer.getInstanceAndStyle(id);
344
}
345
346
- getBestMatchingRendererInterface(node: Object): RendererInterface | null {
347
- let bestMatch = null;
346
+ getIDForHostInstance(target: HostInstance): number | null {
347
+ let bestMatch: null | HostInstance = null;
348
+ let bestRenderer: null | RendererInterface = null;
349
+ // Find the nearest ancestor which is mounted by a React.
350
for (const rendererID in this._rendererInterfaces) {
351
const renderer = ((this._rendererInterfaces[
352
(rendererID: any)
353
]: any): RendererInterface);
352
- const fiber = renderer.getFiberForNative(node);
353
- if (fiber !== null) {
354
- // check if fiber.stateNode is matching the original hostInstance
355
- if (fiber.stateNode === node) {
356
- return renderer;
357
- } else if (bestMatch === null) {
358
- bestMatch = renderer;
354
+ const nearestNode: null = renderer.getNearestMountedHostInstance(target);
355
+ if (nearestNode !== null) {
356
+ if (nearestNode === target) {
357
+ // Exact match we can exit early.
358
+ bestMatch = nearestNode;
359
+ bestRenderer = renderer;
360
+ break;
361
+ }
362
+ if (
363
+ bestMatch === null ||
364
+ (!isReactNativeEnvironment() && bestMatch.contains(nearestNode))
365
+ ) {
366
+ // If this is the first match or the previous match contains the new match,
367
+ // so the new match is a deeper and therefore better match.
368
+ bestMatch = nearestNode;
369
+ bestRenderer = renderer;
370
}
371
}
372
}
362
- // if an exact match is not found, return the first valid renderer as fallback
363
- return bestMatch;
373
+ if (bestRenderer != null && bestMatch != null) {
374
+ try {
375
+ return bestRenderer.getElementIDForHostInstance(bestMatch, true);
376
+ } catch (error) {
377
+ // Some old React versions might throw if they can't find a match.
378
+ // If so we should ignore it...
379
+ }
380
+ }
381
+ return null;
382
}
383
366
- getIDForNode(node: Object): number | null {
367
- const rendererInterface = this.getBestMatchingRendererInterface(node);
368
- if (rendererInterface != null) {
384
+ getComponentNameForHostInstance(target: HostInstance): string | null {
385
+ // We duplicate this code from getIDForHostInstance to avoid an object allocation.
386
+ let bestMatch: null | HostInstance = null;
387
+ let bestRenderer: null | RendererInterface = null;
388
+ // Find the nearest ancestor which is mounted by a React.
389
+ for (const rendererID in this._rendererInterfaces) {
390
+ const renderer = ((this._rendererInterfaces[
391
+ (rendererID: any)
392
+ ]: any): RendererInterface);
393
+ const nearestNode = renderer.getNearestMountedHostInstance(target);
394
+ if (nearestNode !== null) {
395
+ if (nearestNode === target) {
396
+ // Exact match we can exit early.
397
+ bestMatch = nearestNode;
398
+ bestRenderer = renderer;
399
+ break;
400
+ }
401
+ if (
402
+ bestMatch === null ||
403
+ (!isReactNativeEnvironment() && bestMatch.contains(nearestNode))
404
+ ) {
405
+ // If this is the first match or the previous match contains the new match,
406
+ // so the new match is a deeper and therefore better match.
407
+ bestMatch = nearestNode;
408
+ bestRenderer = renderer;
409
+ }
410
+ }
411
+ }
412
+
413
+ if (bestRenderer != null && bestMatch != null) {
414
try {
370
- return rendererInterface.getElementIDForHostInstance(node, true);
415
+ const id = bestRenderer.getElementIDForHostInstance(bestMatch, true);
416
+ if (id) {
417
+ return bestRenderer.getDisplayNameForElementID(id);
418
+ }
419
} catch (error) {
420
// Some old React versions might throw if they can't find a match.
421
// If so we should ignore it...
664
}
665
};
666
619
- selectNode(target: Object): void {
620
- const id = this.getIDForNode(target);
667
+ selectNode(target: HostInstance): void {
668
+ const id = this.getIDForHostInstance(target);
669
if (id !== null) {
670
this._bridge.send('selectElement', id);
671
}