Repository: facebook/react
File: packages/react-devtools-shared/src/backend/fiber/renderer.js (JavaScript)

Code before:
      return Array.from(instance.getClientRects());
    }
    if (instance.canonical) {
      // Native
      const publicInstance = instance.canonical.publicInstance;
      if (!publicInstance) {
        // The publicInstance may not have been initialized yet if there was no ref on this node.
        // We can't initialize it from any existing Hook but we could fallback to this async form:
        // renderer.extraDevToolsConfig.getInspectorDataForInstance(instance).hierarchy[last].getInspectorData().measure(callback)
        return null;
      }
      if (typeof publicInstance.getBoundingClientRect === 'function') {
        // enableAccessToHostTreeInFabric / ReadOnlyElement
        return [publicInstance.getBoundingClientRect()];
      }
      if (typeof publicInstance.unstable_getBoundingClientRect === 'function') {
        // ReactFabricHostComponent
        return [publicInstance.unstable_getBoundingClientRect()];
      }
    }
    return null;
  }

  function measureInstance(instance: DevToolsInstance): null | Array<Rect> {
    // Synchronously return the client rects of the Host instances directly inside this Instance.
    const hostInstances = findAllCurrentHostInstances(instance);
    let result: null | Array<Rect> = null;
    for (let i = 0; i < hostInstances.length; i++) {
      const childResult = measureHostInstance(hostInstances[i]);
      if (childResult !== null) {
        if (result === null) {
          result = childResult;
        } else {
          result = result.concat(childResult);
        }
      }
    }
    return result;
  }

  function getStringID(string: string | null): number {
    if (string === null) {
      return 0;
    }
    const existingEntry = pendingStringTable.get(string);
    if (existingEntry !== undefined) {
      return existingEntry.id;
    }

    const id = pendingStringTable.size + 1;
    const encodedString = utfEncodeString(string);

Review comment (suggestion):
@hoxyq The current technique is required to be async which should be fine with the new React Native APIs. However, currently we can only read the size this way if the publicInstance has been initialized which is now lazy. So it works sometimes. Sometimes it'll be blank. https://github.com/facebook/react/pull/33943

So this works sometimes but not always.

We don't have access to initialize this from the injected hooks. We do have access to the `extraDevToolsConfig` which has some info we can use. However, that's only available as an async API which would require a more complex implementation here. That would work for old versions too.

We could also add another injected devtools hook for measuring instances but that would require upgrading React Native versions to get them.

Code after:
    if (typeof instance.getClientRects === 'function') {
      // DOM
      const result = [];
      const doc = instance.ownerDocument;
      const win = doc && doc.defaultView;
      const scrollX = win ? win.scrollX : 0;
      const scrollY = win ? win.scrollY : 0;
      const rects = instance.getClientRects();
      for (let i = 0; i < rects.length; i++) {
        const rect = rects[i];
        result.push({
          x: rect.x + scrollX,
          y: rect.y + scrollY,
          width: rect.width,
          height: rect.height,
        });
      }
      return result;
    }
    if (instance.canonical) {
      // Native
      const publicInstance = instance.canonical.publicInstance;
      if (!publicInstance) {
        // The publicInstance may not have been initialized yet if there was no ref on this node.
        // We can't initialize it from any existing Hook but we could fallback to this async form:
        // renderer.extraDevToolsConfig.getInspectorDataForInstance(instance).hierarchy[last].getInspectorData().measure(callback)
        return null;
      }
      if (typeof publicInstance.getBoundingClientRect === 'function') {
        // enableAccessToHostTreeInFabric / ReadOnlyElement
        return [publicInstance.getBoundingClientRect()];
      }
      if (typeof publicInstance.unstable_getBoundingClientRect === 'function') {
        // ReactFabricHostComponent
        return [publicInstance.unstable_getBoundingClientRect()];
      }
    }
    return null;
  }

  function measureInstance(instance: DevToolsInstance): null | Array<Rect> {
    // Synchronously return the client rects of the Host instances directly inside this Instance.
    const hostInstances = findAllCurrentHostInstances(instance);
    let result: null | Array<Rect> = null;
    for (let i = 0; i < hostInstances.length; i++) {
      const childResult = measureHostInstance(hostInstances[i]);
      if (childResult !== null) {
        if (result === null) {
          result = childResult;
        } else {
          result = result.concat(childResult);