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,68 @@ 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 , function (
99+ x ,
100+ y ,
101+ width ,
102+ height ,
103+ pageX ,
104+ pageY ,
105+ ) {
106+ callback ( x , y , width , height , pageX , pageY ) ;
107+ } ) ;
108+ } else {
109+ return UIManager . measure (
110+ getHostNode ( fiber , findNodeHandle ) ,
111+ callback ,
112+ ) ;
113+ }
114+ } ,
115+ } ;
116+ } ,
89117 } ) ) ;
90118 } ;
91119
120+ const getInspectorDataForInstance = function ( closestInstance ) : InspectorData {
121+ // Handle case where user clicks outside of ReactNative
122+ if ( ! closestInstance ) {
123+ return {
124+ hierarchy : [ ] ,
125+ props : emptyObject ,
126+ selection : null ,
127+ source : null ,
128+ } ;
129+ }
130+
131+ const fiber = findCurrentFiberUsingSlowPath ( closestInstance ) ;
132+ const fiberHierarchy = getOwnerHierarchy ( fiber ) ;
133+ const instance = lastNonHostInstance ( fiberHierarchy ) ;
134+ const hierarchy = createHierarchy ( fiberHierarchy ) ;
135+ const props = getHostProps ( instance ) ;
136+ const source = instance . _debugSource ;
137+ const selection = fiberHierarchy . indexOf ( instance ) ;
138+
139+ return {
140+ hierarchy,
141+ props,
142+ selection,
143+ source,
144+ } ;
145+ } ;
146+
92147 getInspectorDataForViewTag = function ( viewTag : number ) : Object {
93148 const closestInstance = getClosestInstanceFromNode ( viewTag ) ;
94149
@@ -117,13 +172,90 @@ if (__DEV__) {
117172 source,
118173 } ;
119174 } ;
175+
176+ getInspectorDataForViewAtPoint = function (
177+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
178+ inspectedView : Object ,
179+ locationX : number ,
180+ locationY : number ,
181+ callback : ( viewData : TouchedViewDataAtPoint ) = > mixed ,
182+ ) : void {
183+ let closestInstance = null ;
184+
185+ if ( inspectedView . _internalInstanceHandle != null ) {
186+ // For Fabric we can look up the instance handle directly and measure it.
187+ nativeFabricUIManager . findNodeAtPoint (
188+ inspectedView . _internalInstanceHandle . stateNode . node ,
189+ locationX ,
190+ locationY ,
191+ internalInstanceHandle => {
192+ if ( internalInstanceHandle == null ) {
193+ callback ( {
194+ pointerY : locationY ,
195+ frame : { left : 0 , top : 0 , width : 0 , height : 0 } ,
196+ ...getInspectorDataForInstance ( closestInstance ) ,
197+ } ) ;
198+ }
199+
200+ closestInstance =
201+ internalInstanceHandle . stateNode . canonical . _internalInstanceHandle ;
202+ nativeFabricUIManager . measure (
203+ internalInstanceHandle . stateNode . node ,
204+ ( x , y , width , height , pageX , pageY ) => {
205+ callback ( {
206+ pointerY : locationY ,
207+ frame : { left : pageX , top : pageY , width, height} ,
208+ ...getInspectorDataForInstance ( closestInstance ) ,
209+ } ) ;
210+ } ,
211+ ) ;
212+ } ,
213+ ) ;
214+ } else if ( inspectedView . _internalFiberInstanceHandle != null ) {
215+ // For Paper we fall back to the old strategy using the React tag.
216+ UIManager . findSubviewIn (
217+ findNodeHandle ( inspectedView ) ,
218+ [ locationX , locationY ] ,
219+ ( nativeViewTag , left , top , width , height ) => {
220+ const inspectorData = getInspectorDataForInstance (
221+ getClosestInstanceFromNode ( nativeViewTag ) ,
222+ ) ;
223+ callback ( {
224+ ...inspectorData ,
225+ pointerY : locationY ,
226+ frame : { left, top, width, height} ,
227+ touchedViewTag : nativeViewTag ,
228+ } ) ;
229+ } ,
230+ ) ;
231+ } else if ( __DEV__ ) {
232+ console . error (
233+ 'getInspectorDataForViewAtPoint expects to receieve a host component' ,
234+ ) ;
235+
236+ return ;
237+ }
238+ } ;
120239} else {
121240 getInspectorDataForViewTag = ( ) => {
122241 invariant (
123242 false ,
124243 'getInspectorDataForViewTag() is not available in production' ,
125244 ) ;
126245 } ;
246+
247+ getInspectorDataForViewAtPoint = (
248+ findNodeHandle : ( componentOrHandle : any ) = > ?number ,
249+ inspectedView : Object ,
250+ locationX : number ,
251+ locationY : number ,
252+ callback : ( viewData : TouchedViewDataAtPoint ) => mixed ,
253+ ) : void => {
254+ invariant (
255+ false ,
256+ 'getInspectorDataForViewAtPoint() is not available in production.' ,
257+ ) ;
258+ } ;
127259}
128260
129- export { getInspectorDataForViewTag } ;
261+ export { getInspectorDataForViewAtPoint , getInspectorDataForViewTag } ;
0 commit comments