Files
react/packages/react-native-renderer/src/ReactNativeFiberInspector.js
T

130 lines
3.3 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {Fiber} from 'react-reconciler/src/ReactFiber';
import {
findCurrentHostFiber,
findCurrentFiberUsingSlowPath,
} from 'react-reconciler/reflection';
import getComponentName from 'shared/getComponentName';
import {HostComponent} from 'shared/ReactWorkTags';
import invariant from 'shared/invariant';
// Module provided by RN:
import UIManager from 'UIManager';
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
const emptyObject = {};
if (__DEV__) {
Object.freeze(emptyObject);
}
let getInspectorDataForViewTag;
if (__DEV__) {
const traverseOwnerTreeUp = function(hierarchy, instance: any) {
if (instance) {
hierarchy.unshift(instance);
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
}
};
const getOwnerHierarchy = function(instance: any) {
const hierarchy = [];
traverseOwnerTreeUp(hierarchy, instance);
return hierarchy;
};
const lastNonHostInstance = function(hierarchy) {
for (let i = hierarchy.length - 1; i > 1; i--) {
const instance = hierarchy[i];
if (instance.tag !== HostComponent) {
return instance;
}
}
return hierarchy[0];
};
const getHostProps = function(fiber) {
const host = findCurrentHostFiber(fiber);
if (host) {
return host.memoizedProps || emptyObject;
}
return emptyObject;
};
const getHostNode = function(fiber: Fiber | null, findNodeHandle) {
let hostNode;
// look for children first for the hostNode
// as composite fibers do not have a hostNode
while (fiber) {
if (fiber.stateNode !== null && fiber.tag === HostComponent) {
hostNode = findNodeHandle(fiber.stateNode);
}
if (hostNode) {
return hostNode;
}
fiber = fiber.child;
}
return null;
};
const createHierarchy = function(fiberHierarchy) {
return fiberHierarchy.map(fiber => ({
name: getComponentName(fiber.type),
getInspectorData: findNodeHandle => ({
measure: callback =>
UIManager.measure(getHostNode(fiber, findNodeHandle), callback),
props: getHostProps(fiber),
source: fiber._debugSource,
}),
}));
};
getInspectorDataForViewTag = function(viewTag: number): Object {
const closestInstance = getClosestInstanceFromNode(viewTag);
// Handle case where user clicks outside of ReactNative
if (!closestInstance) {
return {
hierarchy: [],
props: emptyObject,
selection: null,
source: null,
};
}
const fiber = findCurrentFiberUsingSlowPath(closestInstance);
const fiberHierarchy = getOwnerHierarchy(fiber);
const instance = lastNonHostInstance(fiberHierarchy);
const hierarchy = createHierarchy(fiberHierarchy);
const props = getHostProps(instance);
const source = instance._debugSource;
const selection = fiberHierarchy.indexOf(instance);
return {
hierarchy,
props,
selection,
source,
};
};
} else {
getInspectorDataForViewTag = () => {
invariant(
false,
'getInspectorDataForViewTag() is not available in production',
);
};
}
export {getInspectorDataForViewTag};