@@ -332,12 +332,20 @@ const Dispatcher: DispatcherType = {
332332
333333// Inspect
334334
335+ export type HookSource = {
336+ lineNumber : number | null ,
337+ columnNumber : number | null ,
338+ fileName : string | null ,
339+ functionName : string | null ,
340+ } ;
341+
335342export type HooksNode = {
336343 id : number | null ,
337344 isStateEditable : boolean ,
338345 name : string ,
339346 value : mixed ,
340347 subHooks : Array < HooksNode > ,
348+ hookSource ? : HookSource ,
341349 ...
342350} ;
343351export type HooksTree = Array< HooksNode > ;
@@ -473,7 +481,11 @@ function parseCustomHookName(functionName: void | string): string {
473481 return functionName . substr ( startIndex ) ;
474482}
475483
476- function buildTree ( rootStack , readHookLog ) : HooksTree {
484+ function buildTree (
485+ rootStack ,
486+ readHookLog ,
487+ includeHooksSource : boolean ,
488+ ) : HooksTree {
477489 const rootChildren = [ ] ;
478490 let prevStack = null ;
479491 let levelChildren = rootChildren ;
@@ -508,13 +520,25 @@ function buildTree(rootStack, readHookLog): HooksTree {
508520 // to the tree.
509521 for ( let j = stack . length - commonSteps - 1 ; j >= 1 ; j -- ) {
510522 const children = [ ] ;
511- levelChildren . push ( {
523+ const stackFrame = stack [ j ] ;
524+ const levelChild : HooksNode = {
512525 id : null ,
513526 isStateEditable : false ,
514527 name : parseCustomHookName ( stack [ j - 1 ] . functionName ) ,
515528 value : undefined ,
516529 subHooks : children ,
517- } ) ;
530+ } ;
531+
532+ if ( includeHooksSource ) {
533+ levelChild . hookSource = {
534+ lineNumber : stackFrame . lineNumber ,
535+ columnNumber : stackFrame . columnNumber ,
536+ functionName : stackFrame . functionName ,
537+ fileName : stackFrame . fileName ,
538+ } ;
539+ }
540+
541+ levelChildren . push ( levelChild ) ;
518542 stackOfChildren . push ( levelChildren ) ;
519543 levelChildren = children ;
520544 }
@@ -531,14 +555,33 @@ function buildTree(rootStack, readHookLog): HooksTree {
531555
532556 // For the time being, only State and Reducer hooks support runtime overrides.
533557 const isStateEditable = primitive === 'Reducer' || primitive === 'State' ;
534-
535- levelChildren . push ( {
558+ const levelChild : HooksNode = {
536559 id,
537560 isStateEditable,
538561 name : primitive ,
539562 value : hook . value ,
540563 subHooks : [ ] ,
541- } ) ;
564+ } ;
565+
566+ if ( includeHooksSource ) {
567+ const hookSource : HookSource = {
568+ lineNumber : null ,
569+ functionName : null ,
570+ fileName : null ,
571+ columnNumber : null ,
572+ } ;
573+ if ( stack && stack . length >= 1 ) {
574+ const stackFrame = stack [ 0 ] ;
575+ hookSource . lineNumber = stackFrame . lineNumber ;
576+ hookSource . functionName = stackFrame . functionName ;
577+ hookSource . fileName = stackFrame . fileName ;
578+ hookSource . columnNumber = stackFrame . columnNumber ;
579+ }
580+
581+ levelChild . hookSource = hookSource ;
582+ }
583+
584+ levelChildren . push ( levelChild ) ;
542585 }
543586
544587 // Associate custom hook values (useDebugValue() hook entries) with the correct hooks.
@@ -585,6 +628,7 @@ export function inspectHooks<Props>(
585628 renderFunction : Props => React$Node ,
586629 props : Props ,
587630 currentDispatcher : ?CurrentDispatcherRef ,
631+ includeHooksSource ? : boolean = false ,
588632) : HooksTree {
589633 // DevTools will pass the current renderer's injected dispatcher.
590634 // Other apps might compile debug hooks as part of their app though.
@@ -605,7 +649,7 @@ export function inspectHooks<Props>(
605649 currentDispatcher . current = previousDispatcher ;
606650 }
607651 const rootStack = ErrorStackParser . parse ( ancestorStackError ) ;
608- return buildTree ( rootStack , readHookLog ) ;
652+ return buildTree ( rootStack , readHookLog , includeHooksSource ) ;
609653}
610654
611655function setupContexts ( contextMap : Map < ReactContext < any > , any > , fiber : Fiber ) {
@@ -634,6 +678,7 @@ function inspectHooksOfForwardRef<Props, Ref>(
634678 props : Props ,
635679 ref : Ref ,
636680 currentDispatcher : CurrentDispatcherRef ,
681+ includeHooksSource : boolean ,
637682) : HooksTree {
638683 const previousDispatcher = currentDispatcher . current ;
639684 let readHookLog ;
@@ -648,7 +693,7 @@ function inspectHooksOfForwardRef<Props, Ref>(
648693 currentDispatcher . current = previousDispatcher ;
649694 }
650695 const rootStack = ErrorStackParser.parse(ancestorStackError);
651- return buildTree(rootStack, readHookLog);
696+ return buildTree(rootStack, readHookLog, includeHooksSource );
652697}
653698
654699function resolveDefaultProps ( Component , baseProps ) {
@@ -669,6 +714,7 @@ function resolveDefaultProps(Component, baseProps) {
669714export function inspectHooksOfFiber (
670715 fiber : Fiber ,
671716 currentDispatcher : ?CurrentDispatcherRef ,
717+ includeHooksSource ?: boolean = false ,
672718) {
673719 // DevTools will pass the current renderer's injected dispatcher.
674720 // Other apps might compile debug hooks as part of their app though.
@@ -706,9 +752,10 @@ export function inspectHooksOfFiber(
706752 props ,
707753 fiber . ref ,
708754 currentDispatcher ,
755+ includeHooksSource ,
709756 ) ;
710757 }
711- return inspectHooks(type, props, currentDispatcher);
758+ return inspectHooks(type, props, currentDispatcher, includeHooksSource );
712759 } finally {
713760 currentHook = null ;
714761 restoreContexts ( contextMap ) ;
0 commit comments