Skip to content

Commit ab390c6

Browse files
author
Brian Vaughn
authored
ReactDebugHooks optionally includes fileName, and line/column numbers (#21781)
1 parent 6bf1117 commit ab390c6

File tree

1 file changed

+56
-9
lines changed

1 file changed

+56
-9
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

+56-9
Original file line numberDiff line numberDiff line change
@@ -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+
335342
export type HooksNode = {
336343
id: number | null,
337344
isStateEditable: boolean,
338345
name: string,
339346
value: mixed,
340347
subHooks: Array<HooksNode>,
348+
hookSource?: HookSource,
341349
...
342350
};
343351
export 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

611655
function 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

654699
function resolveDefaultProps(Component, baseProps) {
@@ -669,6 +714,7 @@ function resolveDefaultProps(Component, baseProps) {
669714
export 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

Comments
 (0)