5268
}
5269
}
5270
5271
+ function getNearestSuspenseNode(instance: DevToolsInstance): SuspenseNode {
5272
+ while (instance.suspenseNode === null) {
5273
+ if (instance.parent === null) {
5274
+ throw new Error(
5275
+ 'There should always be a SuspenseNode parent on a mounted instance.',
5276
+ );
5277
+ }
5278
+ instance = instance.parent;
5279
+ }
5280
+ return instance.suspenseNode;
5281
+ }
5282
+
5283
function getNearestMountedDOMNode(publicInstance: Element): null | Element {
5284
let domNode: null | Element = publicInstance;
5285
while (domNode && !publicInstanceToDevToolsInstanceMap.has(domNode)) {
5568
return result;
5569
}
5570
5571
+ const FALLBACK_THROTTLE_MS: number = 300;
5572
+
5573
+ function getSuspendedByRange(
5574
+ suspenseNode: SuspenseNode,
5575
+ ): null | [number, number] {
5576
+ let min = Infinity;
5577
+ let max = -Infinity;
5578
+ suspenseNode.suspendedBy.forEach((_, ioInfo) => {
5579
+ if (ioInfo.end > max) {
5580
+ max = ioInfo.end;
5581
+ }
5582
+ if (ioInfo.start < min) {
5583
+ min = ioInfo.start;
5584
+ }
5585
+ });
5586
+ const parentSuspenseNode = suspenseNode.parent;
5587
+ if (parentSuspenseNode !== null) {
5588
+ let parentMax = -Infinity;
5589
+ parentSuspenseNode.suspendedBy.forEach((_, ioInfo) => {
5590
+ if (ioInfo.end > parentMax) {
5591
+ parentMax = ioInfo.end;
5592
+ }
5593
+ });
5594
+ // The parent max is theoretically the earlier the parent could've committed.
5595
+ // Therefore, the theoretical max that the child could be throttled is that plus 300ms.
5596
+ const throttleTime = parentMax + FALLBACK_THROTTLE_MS;
5597
+ if (throttleTime > max) {
5598
+ // If the theoretical throttle time is later than the earliest reveal then we extend
5599
+ // the max time to show that this is timespan could possibly get throttled.
5600
+ max = throttleTime;
5601
+ }
5602
+
5603
+ // We use the end of the previous boundary as the start time for this boundary unless,
5604
+ // that's earlier than we'd need to expand to the full fallback throttle range. It
5605
+ // suggests that the parent was loaded earlier than this one.
5606
+ let startTime = max - FALLBACK_THROTTLE_MS;
5607
+ if (parentMax > startTime) {
5608
+ startTime = parentMax;
5609
+ }
5610
+ // If the first fetch of this boundary starts before that, then we use that as the start.
5611
+ if (startTime < min) {
5612
+ min = startTime;
5613
+ }
5614
+ }
5615
+ if (min < Infinity && max > -Infinity) {
5616
+ return [min, max];
5617
+ }
5618
+ return null;
5619
+ }
5620
+
5621
function getAwaitStackFromHooks(
5622
hooks: HooksTree,
5623
asyncInfo: ReactAsyncInfo,
6086
: fiberInstance.suspendedBy.map(info =>
6087
serializeAsyncInfo(info, fiberInstance, hooks),
6088
);
6089
+ const suspendedByRange = getSuspendedByRange(
6090
+ getNearestSuspenseNode(fiberInstance),
6091
+ );
6092
+
6093
return {
6094
id: fiberInstance.id,
6095
6152
: Array.from(componentLogsEntry.warnings.entries()),
6153
6154
suspendedBy: suspendedBy,
6155
+ suspendedByRange: suspendedByRange,
6156
6157
// List of owners
6158
owners,
6211
6212
// Things that Suspended this Server Component (use(), awaits and direct child promises)
6213
const suspendedBy = virtualInstance.suspendedBy;
6214
+ const suspendedByRange = getSuspendedByRange(
6215
+ getNearestSuspenseNode(virtualInstance),
6216
+ );
6217
6218
return {
6219
id: virtualInstance.id,
6266
: suspendedBy.map(info =>
6267
serializeAsyncInfo(info, virtualInstance, null),
6268
),
6269
+ suspendedByRange: suspendedByRange,
6270
6271
// List of owners
6272
owners,