Skip to content

Commit 248e72c

Browse files
committed
fix: preserve component stack on repeated element grabs
1 parent 53baff6 commit 248e72c

1 file changed

Lines changed: 35 additions & 9 deletions

File tree

src/react-native/get-rendered-by.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,37 @@ type V8CallSite = {
1717
getColumnNumber(): number | null;
1818
};
1919

20+
const restoreStackDescriptor = (
21+
error: Error,
22+
descriptor: PropertyDescriptor | undefined,
23+
) => {
24+
try {
25+
if (descriptor) {
26+
Object.defineProperty(error, "stack", descriptor);
27+
} else {
28+
delete (error as Error & { stack?: unknown }).stack;
29+
}
30+
} catch {
31+
// Best effort only. Some runtimes may prevent restoring non-configurable properties.
32+
}
33+
};
34+
2035
const firstUserFrameFromError = (
2136
error: Error,
2237
): { file: string | null; line: number | null; column: number | null } | null => {
38+
const stackDescriptorBeforeCallSites = Object.getOwnPropertyDescriptor(error, "stack");
2339
let callSites: V8CallSite[] | null = null;
2440
const prev = (Error as any).prepareStackTrace;
25-
(Error as any).prepareStackTrace = (_: unknown, sites: V8CallSite[]) => {
26-
callSites = sites;
27-
return "";
28-
};
29-
void error.stack;
30-
(Error as any).prepareStackTrace = prev;
41+
try {
42+
(Error as any).prepareStackTrace = (_: unknown, sites: V8CallSite[]) => {
43+
callSites = sites;
44+
return "";
45+
};
46+
void error.stack;
47+
} finally {
48+
(Error as any).prepareStackTrace = prev;
49+
restoreStackDescriptor(error, stackDescriptorBeforeCallSites);
50+
}
3151

3252
if (callSites && (callSites as V8CallSite[]).length > 0) {
3353
const sites = callSites as V8CallSite[];
@@ -62,10 +82,16 @@ const firstUserFrameFromError = (
6282
return null;
6383
}
6484

85+
const stackDescriptorBeforeString = Object.getOwnPropertyDescriptor(error, "stack");
6586
const prevStr = (Error as any).prepareStackTrace;
66-
(Error as any).prepareStackTrace = undefined;
67-
let stack = error.stack ?? "";
68-
(Error as any).prepareStackTrace = prevStr;
87+
let stack = "";
88+
try {
89+
(Error as any).prepareStackTrace = undefined;
90+
stack = error.stack ?? "";
91+
} finally {
92+
(Error as any).prepareStackTrace = prevStr;
93+
restoreStackDescriptor(error, stackDescriptorBeforeString);
94+
}
6995

7096
if (stack.startsWith("Error: react-stack-top-frame\n")) {
7197
stack = stack.slice("Error: react-stack-top-frame\n".length);

0 commit comments

Comments
 (0)