1
+/**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactNativeFiberInspector
10
+ * @flow
11
+ */
12
+'use strict';
13
+
14
+const ReactNativeComponentTree = require('ReactNativeComponentTree');
15
+const ReactFiberTreeReflection = require('ReactFiberTreeReflection');
16
+const getComponentName = require('getComponentName');
17
+const emptyObject = require('fbjs/lib/emptyObject');
18
+const ReactTypeOfWork = require('ReactTypeOfWork');
19
+const UIManager = require('UIManager');
20
+const invariant = require('fbjs/lib/invariant');
21
+
22
+const {getClosestInstanceFromNode} = ReactNativeComponentTree;
23
+const {findCurrentFiberUsingSlowPath} = ReactFiberTreeReflection;
24
+const {HostComponent} = ReactTypeOfWork;
25
+
26
+import type {Fiber} from 'ReactFiber';
27
+
28
+let getInspectorDataForViewTag;
29
+
30
+if (__DEV__) {
31
+ var traverseOwnerTreeUp = function(hierarchy, instance: any) {
32
+ if (instance) {
33
+ hierarchy.unshift(instance);
34
+ traverseOwnerTreeUp(hierarchy, instance._debugOwner);
35
+ }
36
+ };
37
+
38
+ var getOwnerHierarchy = function(instance: any) {
39
+ var hierarchy = [];
40
+ traverseOwnerTreeUp(hierarchy, instance);
41
+ return hierarchy;
42
+ };
43
+
44
+ var lastNonHostInstance = function(hierarchy) {
45
+ for (let i = hierarchy.length - 1; i > 1; i--) {
46
+ const instance = hierarchy[i];
47
+
48
+ if (instance.tag !== HostComponent) {
49
+ return instance;
50
+ }
51
+ }
52
+ return hierarchy[0];
53
+ };
54
+
55
+ var getHostProps = function(fiber) {
56
+ const host = ReactFiberTreeReflection.findCurrentHostFiber(fiber);
57
+ if (host) {
58
+ return host.memoizedProps || emptyObject;
59
+ }
60
+ return emptyObject;
61
+ };
62
+
63
+ var getHostNode = function(fiber: Fiber | null, findNodeHandle) {
64
+ let hostNode;
65
+ // look for children first for the hostNode
66
+ // as composite fibers do not have a hostNode
67
+ while (fiber) {
68
+ if (fiber.stateNode !== null && fiber.tag === HostComponent) {
69
+ hostNode = findNodeHandle(fiber.stateNode);
70
+ }
71
+ if (hostNode) {
72
+ return hostNode;
73
+ }
74
+ fiber = fiber.child;
75
+ }
76
+ return null;
77
+ };
78
+
79
+ var stripTopSecret = str =>
80
+ typeof str === 'string' && str.replace('topsecret-', '');
81
+
82
+ var createHierarchy = function(fiberHierarchy) {
83
+ return fiberHierarchy.map(fiber => ({
84
+ name: stripTopSecret(getComponentName(fiber)),
85
+ getInspectorData: findNodeHandle => ({
86
+ measure: callback =>
87
+ UIManager.measure(getHostNode(fiber, findNodeHandle), callback),
88
+ props: getHostProps(fiber),
89
+ source: fiber._debugSource,
90
+ }),
91
+ }));
92
+ };
93
+
94
+ getInspectorDataForViewTag = function(viewTag: number): Object {
95
+ const fiber = findCurrentFiberUsingSlowPath(
96
+ getClosestInstanceFromNode(viewTag),
97
+ );
98
+ const fiberHierarchy = getOwnerHierarchy(fiber);
99
+ const instance = lastNonHostInstance(fiberHierarchy);
100
+ const hierarchy = createHierarchy(fiberHierarchy);
101
+ const props = getHostProps(instance);
102
+ const source = instance._debugSource;
103
+ const selection = fiberHierarchy.indexOf(instance);
104
+
105
+ return {
106
+ hierarchy,
107
+ instance,
108
+ props,
109
+ selection,
110
+ source,
111
+ };
112
+ };
113
+} else {
114
+ getInspectorDataForViewTag = () => {
115
+ invariant(
116
+ false,
117
+ 'getInspectorDataForViewTag() is not available in production',
118
+ );
119
+ };
120
+}
121
+
122
+module.exports = {
123
+ getInspectorDataForViewTag,
124
+};