bippy 0.5.32 → 0.5.34

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.
@@ -16,34 +16,26 @@ import {
16
16
  ViewTransitionComponentTag,
17
17
  getDisplayName,
18
18
  traverseFiber,
19
- } from '../core.js';
20
- import { SERVER_FRAME_MARKER } from './constants.js';
19
+ } from "../core.js";
20
+ import { SERVER_FRAME_MARKER } from "./constants.js";
21
21
 
22
- import { parseStack, StackFrame } from './parse-stack.js';
23
- import { symbolicateStack } from './symbolication.js';
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['_debugStack']>;
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 === 'object') {
44
- return 'H' in currentDispatcherRef
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 === 'object') {
56
- if ('H' in currentDispatcherRef) {
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
- Error.prepareStackTrace = undefined;
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, 'props', {
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 === 'object' && Reflect.construct) {
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 === 'function') {
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 === 'string'
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
- 'name',
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
- 'name',
197
- { value: 'DetermineComponentFrameRoot' },
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('\n');
207
- const controlLines = controlStack.split('\n');
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('DetermineComponentFrameRoot')
203
+ !sampleLines[sampleIndex].includes("DetermineComponentFrameRoot")
213
204
  ) {
214
205
  sampleIndex++;
215
206
  }
216
207
  while (
217
208
  controlIndex < controlLines.length &&
218
- !controlLines[controlIndex].includes('DetermineComponentFrameRoot')
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('<anonymous>')) {
279
- stackFrame = stackFrame.replace('<anonymous>', displayName);
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('Activity');
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('Lazy');
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('Suspense Fallback');
316
+ stackFrame = describeBuiltInComponentFrame("Suspense Fallback");
344
317
  } else {
345
- stackFrame = describeBuiltInComponentFrame('Suspense');
318
+ stackFrame = describeBuiltInComponentFrame("Suspense");
346
319
  }
347
320
  break;
348
321
  case SuspenseListComponentTag:
349
- stackFrame = describeBuiltInComponentFrame('SuspenseList');
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('ViewTransition');
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 === 'string') {
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
- Error.prepareStackTrace = undefined;
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('Error: react-stack-top-frame\n')) {
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('\n');
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('react_stack_bottom_frame'),
442
- formattedStack.indexOf('react-stack-bottom-frame'),
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('\n', idx);
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('rsc://') && stackFrame.functionName);
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
- functionNameToUsageIndex.get(serverFrame.functionName) ?? 0;
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 !== 'string'
545
- ? getDisplayName(currentFiber.type) || '<anonymous>'
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
- (stackFrame): StackFrame => {
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
- return stackFrame;
586
- },
587
- );
536
+ if (isServerFrame) {
537
+ return getEnrichedServerStackFrame(
538
+ stackFrame,
539
+ functionNameToRscFrames,
540
+ functionNameToUsageIndex,
541
+ );
542
+ }
588
543
 
589
- const deduplicatedStackFrames = enrichedStackFrames.filter(
590
- (stackFrame, index, frames) => {
591
- if (index === 0) return true;
592
- const previousFrame = frames[index - 1];
593
- return stackFrame.functionName !== previousFrame.functionName;
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
  };