@@ -74,6 +74,7 @@ import {readTemporaryReference} from './ReactFlightTemporaryReferences';
7474import {
7575 markAllTracksInOrder,
7676 logComponentRender,
77+ logDedupedComponentRender,
7778} from './ReactFlightPerformanceTrack';
7879
7980import {
@@ -132,6 +133,7 @@ export type JSONValue =
132133type ProfilingResult = {
133134 track: number,
134135 endTime: number,
136+ component: null | ReactComponentInfo,
135137};
136138
137139const ROW_ID = 0;
@@ -653,7 +655,7 @@ export function reportGlobalError(response: Response, error: Error): void {
653655 });
654656 if (enableProfilerTimer && enableComponentPerformanceTrack) {
655657 markAllTracksInOrder();
656- flushComponentPerformance(getChunk(response, 0), 0, -Infinity);
658+ flushComponentPerformance(getChunk(response, 0), 0, -Infinity, -Infinity );
657659 }
658660}
659661
@@ -2761,7 +2763,8 @@ function resolveTypedArray(
27612763function flushComponentPerformance(
27622764 root: SomeChunk<any>,
27632765 trackIdx: number, // Next available track
2764- trackTime: number, // The time after which it is available
2766+ trackTime: number, // The time after which it is available,
2767+ parentEndTime: number,
27652768): ProfilingResult {
27662769 if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
27672770 // eslint-disable-next-line react-internal/prod-error-codes
@@ -2778,6 +2781,22 @@ function flushComponentPerformance(
27782781 // chunk in two places. We should extend the current end time as if it was
27792782 // rendered as part of this tree.
27802783 const previousResult: ProfilingResult = root._children;
2784+ const previousEndTime = previousResult.endTime;
2785+ if (
2786+ parentEndTime > -Infinity &&
2787+ parentEndTime < previousEndTime &&
2788+ previousResult.component !== null
2789+ ) {
2790+ // Log a placeholder for the deduped value under this child starting
2791+ // from the end of the self time of the parent and spanning until the
2792+ // the deduped end.
2793+ logDedupedComponentRender(
2794+ previousResult.component,
2795+ trackIdx,
2796+ parentEndTime,
2797+ previousEndTime,
2798+ );
2799+ }
27812800 // Since we didn't bump the track this time, we just return the same track.
27822801 previousResult.track = trackIdx;
27832802 return previousResult;
@@ -2805,15 +2824,27 @@ function flushComponentPerformance(
28052824 // The start time of this component is before the end time of the previous
28062825 // component on this track so we need to bump the next one to a parallel track.
28072826 trackIdx++;
2808- trackTime = startTime;
28092827 }
2828+ trackTime = startTime;
28102829 break;
28112830 }
28122831 }
28132832 }
2833+ for (let i = debugInfo.length - 1; i >= 0; i--) {
2834+ const info = debugInfo[i];
2835+ if (typeof info.time === 'number') {
2836+ if (info.time > parentEndTime) {
2837+ parentEndTime = info.time;
2838+ }
2839+ }
2840+ }
28142841 }
28152842
2816- const result: ProfilingResult = {track: trackIdx, endTime: -Infinity};
2843+ const result: ProfilingResult = {
2844+ track: trackIdx,
2845+ endTime: -Infinity,
2846+ component: null,
2847+ };
28172848 root._children = result;
28182849 let childrenEndTime = -Infinity;
28192850 let childTrackIdx = trackIdx;
@@ -2823,7 +2854,11 @@ function flushComponentPerformance(
28232854 children[i],
28242855 childTrackIdx,
28252856 childTrackTime,
2857+ parentEndTime,
28262858 );
2859+ if (childResult.component !== null) {
2860+ result.component = childResult.component;
2861+ }
28272862 childTrackIdx = childResult.track;
28282863 const childEndTime = childResult.endTime;
28292864 childTrackTime = childEndTime;
@@ -2855,6 +2890,8 @@ function flushComponentPerformance(
28552890 endTime,
28562891 childrenEndTime,
28572892 );
2893+ // Track the root most component of the result for deduping logging.
2894+ result.component = componentInfo;
28582895 }
28592896 }
28602897 }
0 commit comments