88 */
99
1010import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
11+ import type { TouchedViewDataAtPoint , InspectorData } from './ReactNativeTypes' ;
1112
1213import {
1314 findCurrentHostFiber ,
@@ -27,6 +28,7 @@ if (__DEV__) {
2728}
2829
2930let getInspectorDataForViewTag ;
31+ let getInspectorDataForViewAtPoint ;
3032
3133if ( __DEV__ ) {
3234 const traverseOwnerTreeUp = function ( hierarchy , instance : any ) {
@@ -80,15 +82,59 @@ if (__DEV__) {
8082 const createHierarchy = function ( fiberHierarchy ) {
8183 return fiberHierarchy . map ( fiber => ( {
8284 name : getComponentName ( fiber . type ) ,
83- getInspectorData : findNodeHandle => ( {
84- measure : callback =>
85- UIManager . measure ( getHostNode ( fiber , findNodeHandle ) , callback ) ,
86- props : getHostProps ( fiber ) ,
87- source : fiber . _debugSource ,
88- } ) ,
85+ getInspectorData : findNodeHandle => {
86+ return {
87+ props : getHostProps ( fiber ) ,
88+ source : fiber . _debugSource ,
89+ measure : callback => {
90+ // If this is Fabric, we'll find a ShadowNode and use that to measure.
91+ const hostFiber = findCurrentHostFiber ( fiber ) ;
92+ const shadowNode =
93+ hostFiber != null &&
94+ hostFiber . stateNode !== null &&
95+ hostFiber . stateNode . node ;
96+
97+ if ( shadowNode ) {
98+ nativeFabricUIManager . measure ( shadowNode , callback ) ;
99+ } else {
100+ return UIManager . measure (
101+ getHostNode ( fiber , findNodeHandle ) ,
102+ callback ,
103+ ) ;
104+ }
105+ } ,
106+ } ;
107+ } ,
89108 } ) ) ;
90109 } ;
91110
111+ const getInspectorDataForInstance = function ( closestInstance ) : InspectorData {
112+ // Handle case where user clicks outside of ReactNative
113+ if ( ! closestInstance ) {
114+ return {
115+ hierarchy : [ ] ,
116+ props : emptyObject ,
117+ selectedIndex : null ,
118+ source : null ,
119+ } ;
120+ }
121+
122+ const fiber = findCurrentFiberUsingSlowPath ( closestInstance ) ;
123+ const fiberHierarchy = getOwnerHierarchy ( fiber ) ;
124+ const instance = lastNonHostInstance ( fiberHierarchy ) ;
125+ const hierarchy = createHierarchy ( fiberHierarchy ) ;
126+ const props = getHostProps ( instance ) ;
127+ const source = instance . _debugSource ;
128+ const selectedIndex = fiberHierarchy . indexOf ( instance ) ;
129+
130+ return {
131+ hierarchy,
132+ props,
133+ selectedIndex,
134+ source,
135+ } ;
136+ } ;
137+
92138 getInspectorDataForViewTag = function ( viewTag : number ) : Object {
93139 const closestInstance = getClosestInstanceFromNode ( viewTag ) ;
94140
@@ -97,7 +143,7 @@ if (__DEV__) {
97143 return {
98144 hierarchy : [ ] ,
99145 props : emptyObject ,
100- selection : null ,
146+ selectedIndex : null ,
101147 source : null ,
102148 } ;
103149 }
@@ -108,22 +154,99 @@ if (__DEV__) {
108154 const hierarchy = createHierarchy ( fiberHierarchy ) ;
109155 const props = getHostProps ( instance ) ;
110156 const source = instance . _debugSource ;
111- const selection = fiberHierarchy . indexOf ( instance ) ;
157+ const selectedIndex = fiberHierarchy . indexOf ( instance ) ;
112158
113159 return {
114160 hierarchy,
115161 props,
116- selection ,
162+ selectedIndex ,
117163 source,
118164 } ;
119165 } ;
166+
167+ getInspectorDataForViewAtPoint = function (
168+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
169+ inspectedView : Object ,
170+ locationX : number ,
171+ locationY : number ,
172+ callback : ( viewData : TouchedViewDataAtPoint ) = > mixed ,
173+ ) : void {
174+ let closestInstance = null ;
175+
176+ if ( inspectedView . _internalInstanceHandle != null ) {
177+ // For Fabric we can look up the instance handle directly and measure it.
178+ nativeFabricUIManager . findNodeAtPoint (
179+ inspectedView . _internalInstanceHandle . stateNode . node ,
180+ locationX ,
181+ locationY ,
182+ internalInstanceHandle => {
183+ if ( internalInstanceHandle == null ) {
184+ callback ( {
185+ pointerY : locationY ,
186+ frame : { left : 0 , top : 0 , width : 0 , height : 0 } ,
187+ ...getInspectorDataForInstance ( closestInstance ) ,
188+ } ) ;
189+ }
190+
191+ closestInstance =
192+ internalInstanceHandle . stateNode . canonical . _internalInstanceHandle ;
193+ nativeFabricUIManager . measure (
194+ internalInstanceHandle . stateNode . node ,
195+ ( x , y , width , height , pageX , pageY ) => {
196+ callback ( {
197+ pointerY : locationY ,
198+ frame : { left : pageX , top : pageY , width, height} ,
199+ ...getInspectorDataForInstance ( closestInstance ) ,
200+ } ) ;
201+ } ,
202+ ) ;
203+ } ,
204+ ) ;
205+ } else if ( inspectedView . _internalFiberInstanceHandleDEV != null ) {
206+ // For Paper we fall back to the old strategy using the React tag.
207+ UIManager . findSubviewIn (
208+ findNodeHandle ( inspectedView ) ,
209+ [ locationX , locationY ] ,
210+ ( nativeViewTag , left , top , width , height ) => {
211+ const inspectorData = getInspectorDataForInstance (
212+ getClosestInstanceFromNode ( nativeViewTag ) ,
213+ ) ;
214+ callback ( {
215+ ...inspectorData ,
216+ pointerY : locationY ,
217+ frame : { left, top, width, height} ,
218+ touchedViewTag : nativeViewTag ,
219+ } ) ;
220+ } ,
221+ ) ;
222+ } else {
223+ console . error (
224+ 'getInspectorDataForViewAtPoint expects to receieve a host component' ,
225+ ) ;
226+
227+ return ;
228+ }
229+ } ;
120230} else {
121231 getInspectorDataForViewTag = ( ) => {
122232 invariant (
123233 false ,
124234 'getInspectorDataForViewTag() is not available in production' ,
125235 ) ;
126236 } ;
237+
238+ getInspectorDataForViewAtPoint = (
239+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
240+ inspectedView : Object ,
241+ locationX : number ,
242+ locationY : number ,
243+ callback : ( viewData : TouchedViewDataAtPoint ) => mixed ,
244+ ) : void => {
245+ invariant (
246+ false ,
247+ 'getInspectorDataForViewAtPoint() is not available in production.' ,
248+ ) ;
249+ } ;
127250}
128251
129- export { getInspectorDataForViewTag } ;
252+ export { getInspectorDataForViewAtPoint , getInspectorDataForViewTag } ;
0 commit comments