125
| $ReadOnlyArray<JSONValue>;
126
127
type ProfilingResult = {
128
+ track: number,
129
endTime: number,
130
};
131
643
}
644
});
645
if (enableProfilerTimer && enableComponentPerformanceTrack) {
645
- flushComponentPerformance(getChunk(response, 0));
646
+ flushComponentPerformance(getChunk(response, 0), 0, -Infinity);
647
}
648
}
649
2741
resolveBuffer(response, id, view);
2742
}
2743
2743
-function flushComponentPerformance(root: SomeChunk<any>): number {
2744
+function flushComponentPerformance(
2745
+ root: SomeChunk<any>,
2746
+ trackIdx: number, // Next available track
2747
+ trackTime: number, // The time after which it is available
2748
+): ProfilingResult {
2749
if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
2745
- return 0;
2750
+ // eslint-disable-next-line react-internal/prod-error-codes
2751
+ throw new Error(
2752
+ 'flushComponentPerformance should never be called in production mode. This is a bug in React.',
2753
+ );
2754
}
2755
// Write performance.measure() entries for Server Components in tree order.
2756
// This must be done at the end to collect the end time from the whole tree.
2761
// chunk in two places. We should extend the current end time as if it was
2762
// rendered as part of this tree.
2763
const previousResult: ProfilingResult = root._children;
2756
- return previousResult.endTime;
2764
+ // Since we didn't bump the track this time, we just return the same track.
2765
+ previousResult.track = trackIdx;
2766
+ return previousResult;
2767
}
2768
const children = root._children;
2769
if (root.status === RESOLVED_MODEL) {
2772
// the performance characteristics of the app by profiling.
2773
initializeModelChunk(root);
2774
}
2765
- const result: ProfilingResult = {endTime: -Infinity};
2775
+
2776
+ // First find the start time of the first component to know if it was running
2777
+ // in parallel with the previous.
2778
+ const debugInfo = root._debugInfo;
2779
+ if (debugInfo) {
2780
+ for (let i = 1; i < debugInfo.length; i++) {
2781
+ const info = debugInfo[i];
2782
+ if (typeof info.name === 'string') {
2783
+ // $FlowFixMe: Refined.
2784
+ const startTimeInfo = debugInfo[i - 1];
2785
+ if (typeof startTimeInfo.time === 'number') {
2786
+ const startTime = startTimeInfo.time;
2787
+ if (startTime < trackTime) {
2788
+ // The start time of this component is before the end time of the previous
2789
+ // component on this track so we need to bump the next one to a parallel track.
2790
+ trackIdx++;
2791
+ trackTime = startTime;
2792
+ }
2793
+ break;
2794
+ }
2795
+ }
2796
+ }
2797
+ }
2798
+
2799
+ const result: ProfilingResult = {track: trackIdx, endTime: -Infinity};
2800
root._children = result;
2801
let childrenEndTime = -Infinity;
2802
+ let childTrackIdx = trackIdx;
2803
+ let childTrackTime = trackTime;
2804
for (let i = 0; i < children.length; i++) {
2769
- const childEndTime = flushComponentPerformance(children[i]);
2805
+ const childResult = flushComponentPerformance(
2806
+ children[i],
2807
+ childTrackIdx,
2808
+ childTrackTime,
2809
+ );
2810
+ childTrackIdx = childResult.track;
2811
+ const childEndTime = childResult.endTime;
2812
+ childTrackTime = childEndTime;
2813
if (childEndTime > childrenEndTime) {
2814
childrenEndTime = childEndTime;
2815
}
2816
}
2774
- const debugInfo = root._debugInfo;
2817
+
2818
if (debugInfo) {
2819
let endTime = 0;
2820
for (let i = debugInfo.length - 1; i >= 0; i--) {
2833
const startTime = startTimeInfo.time;
2834
logComponentRender(
2835
componentInfo,
2836
+ trackIdx,
2837
startTime,
2838
endTime,
2839
childrenEndTime,
2842
}
2843
}
2844
}
2801
- return (result.endTime = childrenEndTime);
2845
+ result.endTime = childrenEndTime;
2846
+ return result;
2847
}
2848
2849
function processFullBinaryRow(