Skip to content

Commit bf2bd04

Browse files
committed
[DevTools] Fix crash when inspecting Components suspended on data awaited in anonymous functions
1 parent dd4911b commit bf2bd04

File tree

4 files changed

+107
-19
lines changed

4 files changed

+107
-19
lines changed

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

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* @flow
88
*/
9-
9+
import type {StackFrame as ParsedStackFrame} from 'error-stack-parser';
1010
import type {
1111
Awaited,
1212
ReactContext,
@@ -844,7 +844,11 @@ export type HooksTree = Array<HooksNode>;
844844

845845
let mostLikelyAncestorIndex = 0;
846846

847-
function findSharedIndex(hookStack: any, rootStack: any, rootIndex: number) {
847+
function findSharedIndex(
848+
hookStack: ParsedStackFrame[],
849+
rootStack: ParsedStackFrame[],
850+
rootIndex: number,
851+
) {
848852
const source = rootStack[rootIndex].source;
849853
hookSearch: for (let i = 0; i < hookStack.length; i++) {
850854
if (hookStack[i].source === source) {
@@ -865,7 +869,10 @@ function findSharedIndex(hookStack: any, rootStack: any, rootIndex: number) {
865869
return -1;
866870
}
867871

868-
function findCommonAncestorIndex(rootStack: any, hookStack: any) {
872+
function findCommonAncestorIndex(
873+
rootStack: ParsedStackFrame[],
874+
hookStack: ParsedStackFrame[],
875+
) {
869876
let rootIndex = findSharedIndex(
870877
hookStack,
871878
rootStack,
@@ -886,7 +893,7 @@ function findCommonAncestorIndex(rootStack: any, hookStack: any) {
886893
return -1;
887894
}
888895

889-
function isReactWrapper(functionName: any, wrapperName: string) {
896+
function isReactWrapper(functionName: void | string, wrapperName: string) {
890897
const hookName = parseHookName(functionName);
891898
if (wrapperName === 'HostTransitionStatus') {
892899
return hookName === wrapperName || hookName === 'FormStatus';
@@ -895,7 +902,7 @@ function isReactWrapper(functionName: any, wrapperName: string) {
895902
return hookName === wrapperName;
896903
}
897904

898-
function findPrimitiveIndex(hookStack: any, hook: HookLogEntry) {
905+
function findPrimitiveIndex(hookStack: ParsedStackFrame[], hook: HookLogEntry) {
899906
const stackCache = getPrimitiveStackCache();
900907
const primitiveStack = stackCache.get(hook.primitive);
901908
if (primitiveStack === undefined) {
@@ -926,7 +933,7 @@ function findPrimitiveIndex(hookStack: any, hook: HookLogEntry) {
926933
return -1;
927934
}
928935

929-
function parseTrimmedStack(rootStack: any, hook: HookLogEntry) {
936+
function parseTrimmedStack(rootStack: ParsedStackFrame[], hook: HookLogEntry) {
930937
// Get the stack trace between the primitive hook function and
931938
// the root function call. I.e. the stack frames of custom hooks.
932939
const hookStack = ErrorStackParser.parse(hook.stackError);
@@ -987,7 +994,7 @@ function parseHookName(functionName: void | string): string {
987994
}
988995

989996
function buildTree(
990-
rootStack: any,
997+
rootStack: ParsedStackFrame[],
991998
readHookLog: Array<HookLogEntry>,
992999
): HooksTree {
9931000
const rootChildren: Array<HooksNode> = [];
@@ -1044,10 +1051,20 @@ function buildTree(
10441051
subHooks: children,
10451052
debugInfo: null,
10461053
hookSource: {
1047-
lineNumber: stackFrame.lineNumber,
1048-
columnNumber: stackFrame.columnNumber,
1049-
functionName: stackFrame.functionName,
1050-
fileName: stackFrame.fileName,
1054+
lineNumber:
1055+
stackFrame.lineNumber === undefined
1056+
? null
1057+
: stackFrame.lineNumber,
1058+
columnNumber:
1059+
stackFrame.columnNumber === undefined
1060+
? null
1061+
: stackFrame.columnNumber,
1062+
functionName:
1063+
stackFrame.functionName === undefined
1064+
? null
1065+
: stackFrame.functionName,
1066+
fileName:
1067+
stackFrame.fileName === undefined ? null : stackFrame.fileName,
10511068
},
10521069
};
10531070

@@ -1092,10 +1109,14 @@ function buildTree(
10921109
};
10931110
if (stack && stack.length >= 1) {
10941111
const stackFrame = stack[0];
1095-
hookSource.lineNumber = stackFrame.lineNumber;
1096-
hookSource.functionName = stackFrame.functionName;
1097-
hookSource.fileName = stackFrame.fileName;
1098-
hookSource.columnNumber = stackFrame.columnNumber;
1112+
hookSource.lineNumber =
1113+
stackFrame.lineNumber === undefined ? null : stackFrame.lineNumber;
1114+
hookSource.functionName =
1115+
stackFrame.functionName === undefined ? null : stackFrame.functionName;
1116+
hookSource.fileName =
1117+
stackFrame.fileName === undefined ? null : stackFrame.fileName;
1118+
hookSource.columnNumber =
1119+
stackFrame.columnNumber === undefined ? null : stackFrame.columnNumber;
10991120
}
11001121

11011122
levelChild.hookSource = hookSource;
@@ -1201,7 +1222,10 @@ export function inspectHooks<Props>(
12011222
// $FlowFixMe[incompatible-use] found when upgrading Flow
12021223
currentDispatcher.H = previousDispatcher;
12031224
}
1204-
const rootStack = ErrorStackParser.parse(ancestorStackError);
1225+
const rootStack =
1226+
ancestorStackError === undefined
1227+
? ([] as ParsedStackFrame[])
1228+
: ErrorStackParser.parse(ancestorStackError);
12051229
return buildTree(rootStack, readHookLog);
12061230
}
12071231

@@ -1249,7 +1273,10 @@ function inspectHooksOfForwardRef<Props, Ref>(
12491273
hookLog = [];
12501274
currentDispatcher.H = previousDispatcher;
12511275
}
1252-
const rootStack = ErrorStackParser.parse(ancestorStackError);
1276+
const rootStack =
1277+
ancestorStackError === undefined
1278+
? ([] as ParsedStackFrame[])
1279+
: ErrorStackParser.parse(ancestorStackError);
12531280
return buildTree(rootStack, readHookLog);
12541281
}
12551282

packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ describe('ReactHooksInspection', () => {
752752
"hookSource": {
753753
"columnNumber": 0,
754754
"fileName": "**",
755-
"functionName": undefined,
755+
"functionName": null,
756756
"lineNumber": 0,
757757
},
758758
"id": null,

packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ describe('ReactHooksInspectionIntegration', () => {
885885
"hookSource": {
886886
"columnNumber": 0,
887887
"fileName": "**",
888-
"functionName": undefined,
888+
"functionName": null,
889889
"lineNumber": 0,
890890
},
891891
"id": 0,

scripts/flow/environment.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,67 @@ declare module 'create-react-class' {
2929
declare const exports: $FlowFixMe;
3030
}
3131

32+
declare module 'error-stack-parser' {
33+
// flow-typed signature: 132e48034ef4756600e1d98681a166b5
34+
// flow-typed version: c6154227d1/error-stack-parser_v2.x.x/flow_>=v0.104.x
35+
36+
declare interface StackFrame {
37+
constructor(object: StackFrame): StackFrame;
38+
39+
isConstructor?: boolean;
40+
getIsConstructor(): boolean;
41+
setIsConstructor(): void;
42+
43+
isEval?: boolean;
44+
getIsEval(): boolean;
45+
setIsEval(): void;
46+
47+
isNative?: boolean;
48+
getIsNative(): boolean;
49+
setIsNative(): void;
50+
51+
isTopLevel?: boolean;
52+
getIsTopLevel(): boolean;
53+
setIsTopLevel(): void;
54+
55+
columnNumber?: number;
56+
getColumnNumber(): number;
57+
setColumnNumber(): void;
58+
59+
lineNumber?: number;
60+
getLineNumber(): number;
61+
setLineNumber(): void;
62+
63+
fileName?: string;
64+
getFileName(): string;
65+
setFileName(): void;
66+
67+
functionName?: string;
68+
getFunctionName(): string;
69+
setFunctionName(): void;
70+
71+
source?: string;
72+
getSource(): string;
73+
setSource(): void;
74+
75+
args?: any[];
76+
getArgs(): any[];
77+
setArgs(): void;
78+
79+
evalOrigin?: StackFrame;
80+
getEvalOrigin(): StackFrame;
81+
setEvalOrigin(): void;
82+
83+
toString(): string;
84+
}
85+
86+
declare class ErrorStackParser {
87+
parse(error: Error): Array<StackFrame>;
88+
}
89+
90+
declare module.exports: ErrorStackParser;
91+
}
92+
3293
declare interface ConsoleTask {
3394
run<T>(f: () => T): T;
3495
}

0 commit comments

Comments
 (0)