bippy 0.5.32 → 0.5.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -69
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +6 -5
- package/dist/core.d.ts +6 -5
- package/dist/core.js +1 -1
- package/dist/core2.d.cts +1 -1
- package/dist/core2.d.ts +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.iife.js +1 -1
- package/dist/install-hook-only.d.cts +1 -1
- package/dist/install-hook-only.iife.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +12 -12
- package/dist/source.d.cts +4 -2
- package/dist/source.d.ts +4 -2
- package/dist/source.js +13 -13
- package/package.json +35 -36
- package/src/core.ts +91 -194
- package/src/index.ts +2 -2
- package/src/install-hook-only.ts +1 -1
- package/src/rdt-hook.ts +19 -27
- package/src/source/constants.ts +13 -14
- package/src/source/get-display-name-from-source.ts +10 -20
- package/src/source/get-source.ts +26 -31
- package/src/source/index.ts +6 -6
- package/src/source/owner-stack.ts +83 -127
- package/src/source/parse-stack.ts +46 -92
- package/src/source/symbolication.ts +19 -54
- package/src/types.ts +18 -43
|
@@ -16,34 +16,26 @@ import {
|
|
|
16
16
|
ViewTransitionComponentTag,
|
|
17
17
|
getDisplayName,
|
|
18
18
|
traverseFiber,
|
|
19
|
-
} from
|
|
20
|
-
import { SERVER_FRAME_MARKER } from
|
|
19
|
+
} from "../core.js";
|
|
20
|
+
import { SERVER_FRAME_MARKER } from "./constants.js";
|
|
21
21
|
|
|
22
|
-
import { parseStack, StackFrame } from
|
|
23
|
-
import { symbolicateStack } from
|
|
22
|
+
import { parseStack, StackFrame } from "./parse-stack.js";
|
|
23
|
+
import { symbolicateStack } from "./symbolication.js";
|
|
24
24
|
|
|
25
25
|
export const hasDebugStack = (
|
|
26
26
|
fiber: Fiber,
|
|
27
27
|
): fiber is Fiber & {
|
|
28
|
-
_debugStack: NonNullable<Fiber[
|
|
28
|
+
_debugStack: NonNullable<Fiber["_debugStack"]>;
|
|
29
29
|
} => {
|
|
30
|
-
return
|
|
31
|
-
fiber._debugStack instanceof Error &&
|
|
32
|
-
typeof fiber._debugStack?.stack === 'string'
|
|
33
|
-
);
|
|
30
|
+
return fiber._debugStack instanceof Error && typeof fiber._debugStack?.stack === "string";
|
|
34
31
|
};
|
|
35
32
|
|
|
36
33
|
const getCurrentDispatcher = (): null | React.RefObject<unknown> => {
|
|
37
34
|
const rdtHook = getRDTHook();
|
|
38
|
-
for (const renderer of [
|
|
39
|
-
...Array.from(_renderers),
|
|
40
|
-
...Array.from(rdtHook.renderers.values()),
|
|
41
|
-
]) {
|
|
35
|
+
for (const renderer of [...Array.from(_renderers), ...Array.from(rdtHook.renderers.values())]) {
|
|
42
36
|
const currentDispatcherRef = renderer.currentDispatcherRef;
|
|
43
|
-
if (currentDispatcherRef && typeof currentDispatcherRef ===
|
|
44
|
-
return
|
|
45
|
-
? currentDispatcherRef.H
|
|
46
|
-
: currentDispatcherRef.current;
|
|
37
|
+
if (currentDispatcherRef && typeof currentDispatcherRef === "object") {
|
|
38
|
+
return "H" in currentDispatcherRef ? currentDispatcherRef.H : currentDispatcherRef.current;
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
41
|
return null;
|
|
@@ -52,8 +44,8 @@ const getCurrentDispatcher = (): null | React.RefObject<unknown> => {
|
|
|
52
44
|
const setCurrentDispatcher = (value: null | React.RefObject<unknown>): void => {
|
|
53
45
|
for (const renderer of _renderers) {
|
|
54
46
|
const currentDispatcherRef = renderer.currentDispatcherRef;
|
|
55
|
-
if (currentDispatcherRef && typeof currentDispatcherRef ===
|
|
56
|
-
if (
|
|
47
|
+
if (currentDispatcherRef && typeof currentDispatcherRef === "object") {
|
|
48
|
+
if ("H" in currentDispatcherRef) {
|
|
57
49
|
currentDispatcherRef.H = value;
|
|
58
50
|
} else {
|
|
59
51
|
currentDispatcherRef.current = value;
|
|
@@ -82,11 +74,12 @@ const describeNativeComponentFrame = (
|
|
|
82
74
|
construct: boolean,
|
|
83
75
|
): string => {
|
|
84
76
|
if (!component || reEntry) {
|
|
85
|
-
return
|
|
77
|
+
return "";
|
|
86
78
|
}
|
|
87
79
|
|
|
88
80
|
const previousPrepareStackTrace = Error.prepareStackTrace;
|
|
89
|
-
|
|
81
|
+
// HACK: V8 API allows undefined but bun-types declares it as non-optional
|
|
82
|
+
(Error as { prepareStackTrace?: typeof Error.prepareStackTrace }).prepareStackTrace = undefined;
|
|
90
83
|
reEntry = true;
|
|
91
84
|
|
|
92
85
|
const previousDispatcher = getCurrentDispatcher();
|
|
@@ -117,14 +110,14 @@ const describeNativeComponentFrame = (
|
|
|
117
110
|
const ThrowingConstructor = function () {
|
|
118
111
|
throw Error();
|
|
119
112
|
};
|
|
120
|
-
Object.defineProperty(ThrowingConstructor.prototype,
|
|
113
|
+
Object.defineProperty(ThrowingConstructor.prototype, "props", {
|
|
121
114
|
set: function () {
|
|
122
115
|
// We use a throwing setter instead of frozen or non-writable props
|
|
123
116
|
// because that won't throw in a non-strict mode function.
|
|
124
117
|
throw Error();
|
|
125
118
|
},
|
|
126
119
|
});
|
|
127
|
-
if (typeof Reflect ===
|
|
120
|
+
if (typeof Reflect === "object" && Reflect.construct) {
|
|
128
121
|
// We construct a different control for this case to include any extra
|
|
129
122
|
// frames added by the construct call.
|
|
130
123
|
try {
|
|
@@ -159,7 +152,7 @@ const describeNativeComponentFrame = (
|
|
|
159
152
|
// silence the error.
|
|
160
153
|
// TODO: Implement component stacks for async client components?
|
|
161
154
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- we literally check if this is a promise here
|
|
162
|
-
if (maybePromise && typeof maybePromise.catch ===
|
|
155
|
+
if (maybePromise && typeof maybePromise.catch === "function") {
|
|
163
156
|
maybePromise.catch(() => {});
|
|
164
157
|
}
|
|
165
158
|
}
|
|
@@ -168,7 +161,7 @@ const describeNativeComponentFrame = (
|
|
|
168
161
|
if (
|
|
169
162
|
sample instanceof Error &&
|
|
170
163
|
control instanceof Error &&
|
|
171
|
-
typeof sample.stack ===
|
|
164
|
+
typeof sample.stack === "string"
|
|
172
165
|
) {
|
|
173
166
|
return [sample.stack, control.stack];
|
|
174
167
|
}
|
|
@@ -178,12 +171,11 @@ const describeNativeComponentFrame = (
|
|
|
178
171
|
};
|
|
179
172
|
|
|
180
173
|
// @ts-expect-error --- displayName is not a property of the function
|
|
181
|
-
RunInRootFrame.DetermineComponentFrameRoot.displayName =
|
|
182
|
-
'DetermineComponentFrameRoot';
|
|
174
|
+
RunInRootFrame.DetermineComponentFrameRoot.displayName = "DetermineComponentFrameRoot";
|
|
183
175
|
const namePropDescriptor = Object.getOwnPropertyDescriptor(
|
|
184
176
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
185
177
|
RunInRootFrame.DetermineComponentFrameRoot,
|
|
186
|
-
|
|
178
|
+
"name",
|
|
187
179
|
);
|
|
188
180
|
// Before ES6, the `name` property was not configurable.
|
|
189
181
|
if (namePropDescriptor?.configurable) {
|
|
@@ -193,39 +185,35 @@ const describeNativeComponentFrame = (
|
|
|
193
185
|
RunInRootFrame.DetermineComponentFrameRoot,
|
|
194
186
|
// Configurable properties can be updated even if its writable descriptor
|
|
195
187
|
// is set to `false`.
|
|
196
|
-
|
|
197
|
-
{ value:
|
|
188
|
+
"name",
|
|
189
|
+
{ value: "DetermineComponentFrameRoot" },
|
|
198
190
|
);
|
|
199
191
|
}
|
|
200
192
|
|
|
201
|
-
const [sampleStack, controlStack] =
|
|
202
|
-
RunInRootFrame.DetermineComponentFrameRoot();
|
|
193
|
+
const [sampleStack, controlStack] = RunInRootFrame.DetermineComponentFrameRoot();
|
|
203
194
|
if (sampleStack && controlStack) {
|
|
204
195
|
// This extracts the first frame from the sample that isn't also in the control.
|
|
205
196
|
// Skipping one frame that we assume is the frame that calls the two.
|
|
206
|
-
const sampleLines = sampleStack.split(
|
|
207
|
-
const controlLines = controlStack.split(
|
|
197
|
+
const sampleLines = sampleStack.split("\n");
|
|
198
|
+
const controlLines = controlStack.split("\n");
|
|
208
199
|
let sampleIndex = 0;
|
|
209
200
|
let controlIndex = 0;
|
|
210
201
|
while (
|
|
211
202
|
sampleIndex < sampleLines.length &&
|
|
212
|
-
!sampleLines[sampleIndex].includes(
|
|
203
|
+
!sampleLines[sampleIndex].includes("DetermineComponentFrameRoot")
|
|
213
204
|
) {
|
|
214
205
|
sampleIndex++;
|
|
215
206
|
}
|
|
216
207
|
while (
|
|
217
208
|
controlIndex < controlLines.length &&
|
|
218
|
-
!controlLines[controlIndex].includes(
|
|
209
|
+
!controlLines[controlIndex].includes("DetermineComponentFrameRoot")
|
|
219
210
|
) {
|
|
220
211
|
controlIndex++;
|
|
221
212
|
}
|
|
222
213
|
// We couldn't find our intentionally injected common root frame, attempt
|
|
223
214
|
// to find another common root frame by search from the bottom of the
|
|
224
215
|
// control stack...
|
|
225
|
-
if (
|
|
226
|
-
sampleIndex === sampleLines.length ||
|
|
227
|
-
controlIndex === controlLines.length
|
|
228
|
-
) {
|
|
216
|
+
if (sampleIndex === sampleLines.length || controlIndex === controlLines.length) {
|
|
229
217
|
sampleIndex = sampleLines.length - 1;
|
|
230
218
|
controlIndex = controlLines.length - 1;
|
|
231
219
|
while (
|
|
@@ -242,11 +230,7 @@ const describeNativeComponentFrame = (
|
|
|
242
230
|
controlIndex--;
|
|
243
231
|
}
|
|
244
232
|
}
|
|
245
|
-
for (
|
|
246
|
-
;
|
|
247
|
-
sampleIndex >= 1 && controlIndex >= 0;
|
|
248
|
-
sampleIndex--, controlIndex--
|
|
249
|
-
) {
|
|
233
|
+
for (; sampleIndex >= 1 && controlIndex >= 0; sampleIndex--, controlIndex--) {
|
|
250
234
|
// Next we find the first one that isn't the same which should be the
|
|
251
235
|
// frame that called our sample function and the control.
|
|
252
236
|
if (sampleLines[sampleIndex] !== controlLines[controlIndex]) {
|
|
@@ -261,22 +245,16 @@ const describeNativeComponentFrame = (
|
|
|
261
245
|
controlIndex--;
|
|
262
246
|
// We may still have similar intermediate frames from the construct call.
|
|
263
247
|
// The next one that isn't the same should be our match though.
|
|
264
|
-
if (
|
|
265
|
-
controlIndex < 0 ||
|
|
266
|
-
sampleLines[sampleIndex] !== controlLines[controlIndex]
|
|
267
|
-
) {
|
|
248
|
+
if (controlIndex < 0 || sampleLines[sampleIndex] !== controlLines[controlIndex]) {
|
|
268
249
|
// V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
|
|
269
|
-
let stackFrame = `\n${sampleLines[sampleIndex].replace(
|
|
270
|
-
' at new ',
|
|
271
|
-
' at ',
|
|
272
|
-
)}`;
|
|
250
|
+
let stackFrame = `\n${sampleLines[sampleIndex].replace(" at new ", " at ")}`;
|
|
273
251
|
|
|
274
252
|
const displayName = getDisplayName(component);
|
|
275
253
|
// If our component frame is labeled "<anonymous>"
|
|
276
254
|
// but we have a user-provided "displayName"
|
|
277
255
|
// splice it in to make the stack more readable.
|
|
278
|
-
if (displayName && stackFrame.includes(
|
|
279
|
-
stackFrame = stackFrame.replace(
|
|
256
|
+
if (displayName && stackFrame.includes("<anonymous>")) {
|
|
257
|
+
stackFrame = stackFrame.replace("<anonymous>", displayName);
|
|
280
258
|
}
|
|
281
259
|
// Return the line we found.
|
|
282
260
|
return stackFrame;
|
|
@@ -297,23 +275,18 @@ const describeNativeComponentFrame = (
|
|
|
297
275
|
console.warn = previousConsoleWarn;
|
|
298
276
|
}
|
|
299
277
|
|
|
300
|
-
const componentName = component ? getDisplayName(component) :
|
|
301
|
-
const syntheticFrame = componentName
|
|
302
|
-
? describeBuiltInComponentFrame(componentName)
|
|
303
|
-
: '';
|
|
278
|
+
const componentName = component ? getDisplayName(component) : "";
|
|
279
|
+
const syntheticFrame = componentName ? describeBuiltInComponentFrame(componentName) : "";
|
|
304
280
|
return syntheticFrame;
|
|
305
281
|
};
|
|
306
282
|
|
|
307
283
|
// https://github.com/facebook/react/blob/ac3e705a18696168acfcaed39dce0cfaa6be8836/packages/react-reconciler/src/ReactFiberComponentStack.js#L180
|
|
308
|
-
export const describeFiber = (
|
|
309
|
-
fiber: Fiber,
|
|
310
|
-
childFiber: Fiber | null,
|
|
311
|
-
): string => {
|
|
284
|
+
export const describeFiber = (fiber: Fiber, childFiber: Fiber | null): string => {
|
|
312
285
|
const tag = fiber.tag as number;
|
|
313
|
-
let stackFrame =
|
|
286
|
+
let stackFrame = "";
|
|
314
287
|
switch (tag) {
|
|
315
288
|
case ActivityComponentTag:
|
|
316
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
289
|
+
stackFrame = describeBuiltInComponentFrame("Activity");
|
|
317
290
|
break;
|
|
318
291
|
case ClassComponentTag:
|
|
319
292
|
stackFrame = describeNativeComponentFrame(fiber.type, true);
|
|
@@ -335,26 +308,26 @@ export const describeFiber = (
|
|
|
335
308
|
break;
|
|
336
309
|
case LazyComponentTag:
|
|
337
310
|
// TODO: When we support Thenables as component types we should rename this.
|
|
338
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
311
|
+
stackFrame = describeBuiltInComponentFrame("Lazy");
|
|
339
312
|
break;
|
|
340
313
|
case SuspenseComponentTag:
|
|
341
314
|
if (fiber.child !== childFiber && childFiber !== null) {
|
|
342
315
|
// If we came from the second Fiber then we're in the Suspense Fallback.
|
|
343
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
316
|
+
stackFrame = describeBuiltInComponentFrame("Suspense Fallback");
|
|
344
317
|
} else {
|
|
345
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
318
|
+
stackFrame = describeBuiltInComponentFrame("Suspense");
|
|
346
319
|
}
|
|
347
320
|
break;
|
|
348
321
|
case SuspenseListComponentTag:
|
|
349
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
322
|
+
stackFrame = describeBuiltInComponentFrame("SuspenseList");
|
|
350
323
|
break;
|
|
351
324
|
case ViewTransitionComponentTag:
|
|
352
325
|
// Note: enableViewTransition feature flag is not available in this codebase,
|
|
353
326
|
// so we'll always include ViewTransition
|
|
354
|
-
stackFrame = describeBuiltInComponentFrame(
|
|
327
|
+
stackFrame = describeBuiltInComponentFrame("ViewTransition");
|
|
355
328
|
break;
|
|
356
329
|
default:
|
|
357
|
-
return
|
|
330
|
+
return "";
|
|
358
331
|
}
|
|
359
332
|
|
|
360
333
|
return stackFrame;
|
|
@@ -367,7 +340,7 @@ export const describeFiber = (
|
|
|
367
340
|
*/
|
|
368
341
|
export const getFallbackOwnerStack = (thisFiber: Fiber): string => {
|
|
369
342
|
try {
|
|
370
|
-
let componentStack =
|
|
343
|
+
let componentStack = "";
|
|
371
344
|
let currentFiber: Fiber | null = thisFiber;
|
|
372
345
|
let previousFiber: Fiber | null = null;
|
|
373
346
|
do {
|
|
@@ -379,11 +352,8 @@ export const getFallbackOwnerStack = (thisFiber: Fiber): string => {
|
|
|
379
352
|
if (debugInfo && Array.isArray(debugInfo)) {
|
|
380
353
|
for (let i = debugInfo.length - 1; i >= 0; i--) {
|
|
381
354
|
const debugEntry = debugInfo[i];
|
|
382
|
-
if (typeof debugEntry.name ===
|
|
383
|
-
componentStack += describeDebugInfoFrame(
|
|
384
|
-
debugEntry.name,
|
|
385
|
-
debugEntry.env,
|
|
386
|
-
);
|
|
355
|
+
if (typeof debugEntry.name === "string") {
|
|
356
|
+
componentStack += describeDebugInfoFrame(debugEntry.name, debugEntry.env);
|
|
387
357
|
}
|
|
388
358
|
}
|
|
389
359
|
}
|
|
@@ -396,7 +366,7 @@ export const getFallbackOwnerStack = (thisFiber: Fiber): string => {
|
|
|
396
366
|
if (error instanceof Error) {
|
|
397
367
|
return `\nError generating stack: ${error.message}\n${error.stack}`;
|
|
398
368
|
}
|
|
399
|
-
return
|
|
369
|
+
return "";
|
|
400
370
|
}
|
|
401
371
|
};
|
|
402
372
|
|
|
@@ -420,29 +390,30 @@ export const getFallbackOwnerStack = (thisFiber: Fiber): string => {
|
|
|
420
390
|
*/
|
|
421
391
|
export const formatOwnerStack = (stack: string): string => {
|
|
422
392
|
const prevPrepareStackTrace = Error.prepareStackTrace;
|
|
423
|
-
|
|
393
|
+
// HACK: V8 API allows undefined but bun-types declares it as non-optional
|
|
394
|
+
(Error as { prepareStackTrace?: typeof Error.prepareStackTrace }).prepareStackTrace = undefined;
|
|
424
395
|
let formattedStack = stack;
|
|
425
396
|
if (!formattedStack) {
|
|
426
|
-
return
|
|
397
|
+
return "";
|
|
427
398
|
}
|
|
428
399
|
Error.prepareStackTrace = prevPrepareStackTrace;
|
|
429
400
|
|
|
430
|
-
if (formattedStack.startsWith(
|
|
401
|
+
if (formattedStack.startsWith("Error: react-stack-top-frame\n")) {
|
|
431
402
|
// V8's default formatting prefixes with the error message which we
|
|
432
403
|
// don't want/need
|
|
433
404
|
formattedStack = formattedStack.slice(29);
|
|
434
405
|
}
|
|
435
|
-
let idx = formattedStack.indexOf(
|
|
406
|
+
let idx = formattedStack.indexOf("\n");
|
|
436
407
|
if (idx !== -1) {
|
|
437
408
|
// pop the JSX frame
|
|
438
409
|
formattedStack = formattedStack.slice(idx + 1);
|
|
439
410
|
}
|
|
440
411
|
idx = Math.max(
|
|
441
|
-
formattedStack.indexOf(
|
|
442
|
-
formattedStack.indexOf(
|
|
412
|
+
formattedStack.indexOf("react_stack_bottom_frame"),
|
|
413
|
+
formattedStack.indexOf("react-stack-bottom-frame"),
|
|
443
414
|
);
|
|
444
415
|
if (idx !== -1) {
|
|
445
|
-
idx = formattedStack.lastIndexOf(
|
|
416
|
+
idx = formattedStack.lastIndexOf("\n", idx);
|
|
446
417
|
}
|
|
447
418
|
if (idx !== -1) {
|
|
448
419
|
// cut off everything after the bottom frame since it'll be internals.
|
|
@@ -451,7 +422,7 @@ export const formatOwnerStack = (stack: string): string => {
|
|
|
451
422
|
// we didn't find any internal callsite out to user space.
|
|
452
423
|
// This means that this was called outside an owner or the owner is fully internal.
|
|
453
424
|
// to keep things light we exclude the entire trace in this case.
|
|
454
|
-
return
|
|
425
|
+
return "";
|
|
455
426
|
}
|
|
456
427
|
return formattedStack;
|
|
457
428
|
};
|
|
@@ -462,12 +433,9 @@ interface OwnerStackEntry {
|
|
|
462
433
|
}
|
|
463
434
|
|
|
464
435
|
const isReactServerComponentFrame = (stackFrame: StackFrame): boolean =>
|
|
465
|
-
Boolean(stackFrame.fileName?.startsWith(
|
|
436
|
+
Boolean(stackFrame.fileName?.startsWith("rsc://") && stackFrame.functionName);
|
|
466
437
|
|
|
467
|
-
const areStackFramesEqual = (
|
|
468
|
-
firstFrame: StackFrame,
|
|
469
|
-
secondFrame: StackFrame,
|
|
470
|
-
): boolean =>
|
|
438
|
+
const areStackFramesEqual = (firstFrame: StackFrame, secondFrame: StackFrame): boolean =>
|
|
471
439
|
firstFrame.fileName === secondFrame.fileName &&
|
|
472
440
|
firstFrame.lineNumber === secondFrame.lineNumber &&
|
|
473
441
|
firstFrame.columnNumber === secondFrame.columnNumber;
|
|
@@ -506,17 +474,13 @@ const getEnrichedServerStackFrame = (
|
|
|
506
474
|
return { ...serverFrame, isServer: true };
|
|
507
475
|
}
|
|
508
476
|
|
|
509
|
-
const availableRscFrames = functionNameToRscFrames.get(
|
|
510
|
-
serverFrame.functionName,
|
|
511
|
-
);
|
|
477
|
+
const availableRscFrames = functionNameToRscFrames.get(serverFrame.functionName);
|
|
512
478
|
if (!availableRscFrames || availableRscFrames.length === 0) {
|
|
513
479
|
return { ...serverFrame, isServer: true };
|
|
514
480
|
}
|
|
515
481
|
|
|
516
|
-
const currentUsageIndex =
|
|
517
|
-
|
|
518
|
-
const resolvedRscFrame =
|
|
519
|
-
availableRscFrames[currentUsageIndex % availableRscFrames.length];
|
|
482
|
+
const currentUsageIndex = functionNameToUsageIndex.get(serverFrame.functionName) ?? 0;
|
|
483
|
+
const resolvedRscFrame = availableRscFrames[currentUsageIndex % availableRscFrames.length];
|
|
520
484
|
functionNameToUsageIndex.set(serverFrame.functionName, currentUsageIndex + 1);
|
|
521
485
|
|
|
522
486
|
return {
|
|
@@ -541,15 +505,13 @@ const getOwnerStackEntries = (rootFiber: Fiber): OwnerStackEntry[] => {
|
|
|
541
505
|
if (!hasDebugStack(currentFiber)) return;
|
|
542
506
|
|
|
543
507
|
const componentName =
|
|
544
|
-
typeof currentFiber.type !==
|
|
545
|
-
? getDisplayName(currentFiber.type) ||
|
|
508
|
+
typeof currentFiber.type !== "string"
|
|
509
|
+
? getDisplayName(currentFiber.type) || "<anonymous>"
|
|
546
510
|
: currentFiber.type;
|
|
547
511
|
|
|
548
512
|
ownerStackEntries.push({
|
|
549
513
|
componentName,
|
|
550
|
-
stackFrames: parseStack(
|
|
551
|
-
formatOwnerStack(currentFiber._debugStack?.stack),
|
|
552
|
-
),
|
|
514
|
+
stackFrames: parseStack(formatOwnerStack(currentFiber._debugStack?.stack)),
|
|
553
515
|
});
|
|
554
516
|
},
|
|
555
517
|
true,
|
|
@@ -565,34 +527,28 @@ export const getOwnerStack = async (
|
|
|
565
527
|
): Promise<StackFrame[]> => {
|
|
566
528
|
const ownerStackEntries = getOwnerStackEntries(fiber);
|
|
567
529
|
const fallbackStackFrames = parseStack(getFallbackOwnerStack(fiber));
|
|
568
|
-
const functionNameToRscFrames =
|
|
569
|
-
buildFunctionNameToRscFramesMap(ownerStackEntries);
|
|
530
|
+
const functionNameToRscFrames = buildFunctionNameToRscFramesMap(ownerStackEntries);
|
|
570
531
|
const functionNameToUsageIndex = new Map<string, number>();
|
|
571
532
|
|
|
572
|
-
const enrichedStackFrames = fallbackStackFrames.map(
|
|
573
|
-
(
|
|
574
|
-
const isServerFrame =
|
|
575
|
-
stackFrame.source?.includes(SERVER_FRAME_MARKER) ?? false;
|
|
576
|
-
|
|
577
|
-
if (isServerFrame) {
|
|
578
|
-
return getEnrichedServerStackFrame(
|
|
579
|
-
stackFrame,
|
|
580
|
-
functionNameToRscFrames,
|
|
581
|
-
functionNameToUsageIndex,
|
|
582
|
-
);
|
|
583
|
-
}
|
|
533
|
+
const enrichedStackFrames = fallbackStackFrames.map((stackFrame): StackFrame => {
|
|
534
|
+
const isServerFrame = stackFrame.source?.includes(SERVER_FRAME_MARKER) ?? false;
|
|
584
535
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
536
|
+
if (isServerFrame) {
|
|
537
|
+
return getEnrichedServerStackFrame(
|
|
538
|
+
stackFrame,
|
|
539
|
+
functionNameToRscFrames,
|
|
540
|
+
functionNameToUsageIndex,
|
|
541
|
+
);
|
|
542
|
+
}
|
|
588
543
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
544
|
+
return stackFrame;
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const deduplicatedStackFrames = enrichedStackFrames.filter((stackFrame, index, frames) => {
|
|
548
|
+
if (index === 0) return true;
|
|
549
|
+
const previousFrame = frames[index - 1];
|
|
550
|
+
return stackFrame.functionName !== previousFrame.functionName;
|
|
551
|
+
});
|
|
596
552
|
|
|
597
553
|
return symbolicateStack(deduplicatedStackFrames, shouldCache, fetchFunction);
|
|
598
554
|
};
|