Skip to content

Commit 6f7b74c

Browse files
committed
Don't assume time entries are always before and after every entry
1 parent 1184bb2 commit 6f7b74c

File tree

1 file changed

+85
-65
lines changed

1 file changed

+85
-65
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 85 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,6 +2902,46 @@ function resolveTypedArray(
29022902
resolveBuffer(response, id, view);
29032903
}
29042904

2905+
function logComponentInfo(
2906+
response: Response,
2907+
root: SomeChunk<any>,
2908+
componentInfo: ReactComponentInfo,
2909+
trackIdx: number,
2910+
startTime: number,
2911+
componentEndTime: number,
2912+
childrenEndTime: number,
2913+
isLastComponent: boolean,
2914+
): void {
2915+
// $FlowFixMe: Refined.
2916+
if (
2917+
isLastComponent &&
2918+
root.status === ERRORED &&
2919+
root.reason !== response._closedReason
2920+
) {
2921+
// If this is the last component to render before this chunk rejected, then conceptually
2922+
// this component errored. If this was a cancellation then it wasn't this component that
2923+
// errored.
2924+
logComponentErrored(
2925+
componentInfo,
2926+
trackIdx,
2927+
startTime,
2928+
componentEndTime,
2929+
childrenEndTime,
2930+
response._rootEnvironmentName,
2931+
root.reason,
2932+
);
2933+
} else {
2934+
logComponentRender(
2935+
componentInfo,
2936+
trackIdx,
2937+
startTime,
2938+
componentEndTime,
2939+
childrenEndTime,
2940+
response._rootEnvironmentName,
2941+
);
2942+
}
2943+
}
2944+
29052945
function flushComponentPerformance(
29062946
response: Response,
29072947
root: SomeChunk<any>,
@@ -2957,28 +2997,28 @@ function flushComponentPerformance(
29572997
// in parallel with the previous.
29582998
const debugInfo = __DEV__ && root._debugInfo;
29592999
if (debugInfo) {
2960-
for (let i = 1; i < debugInfo.length; i++) {
3000+
let startTime = 0;
3001+
for (let i = 0; i < debugInfo.length; i++) {
29613002
const info = debugInfo[i];
3003+
if (typeof info.time === 'number') {
3004+
startTime = info.time;
3005+
}
29623006
if (typeof info.name === 'string') {
2963-
// $FlowFixMe: Refined.
2964-
const startTimeInfo = debugInfo[i - 1];
2965-
if (typeof startTimeInfo.time === 'number') {
2966-
const startTime = startTimeInfo.time;
2967-
if (startTime < trackTime) {
2968-
// The start time of this component is before the end time of the previous
2969-
// component on this track so we need to bump the next one to a parallel track.
2970-
trackIdx++;
2971-
}
2972-
trackTime = startTime;
2973-
break;
3007+
if (startTime < trackTime) {
3008+
// The start time of this component is before the end time of the previous
3009+
// component on this track so we need to bump the next one to a parallel track.
3010+
trackIdx++;
29743011
}
3012+
trackTime = startTime;
3013+
break;
29753014
}
29763015
}
29773016
for (let i = debugInfo.length - 1; i >= 0; i--) {
29783017
const info = debugInfo[i];
29793018
if (typeof info.time === 'number') {
29803019
if (info.time > parentEndTime) {
29813020
parentEndTime = info.time;
3021+
break; // We assume the highest number is at the end.
29823022
}
29833023
}
29843024
}
@@ -3013,77 +3053,57 @@ function flushComponentPerformance(
30133053
}
30143054

30153055
if (debugInfo) {
3056+
// Write debug info in reverse order (just like stack traces).
30163057
let endTime = 0;
3058+
let componentEndTime = 0;
30173059
let isLastComponent = true;
3060+
let candidateInfo = null; // An entry we can write once we know its start time.
30183061
for (let i = debugInfo.length - 1; i >= 0; i--) {
30193062
const info = debugInfo[i];
30203063
if (typeof info.time === 'number') {
3021-
if (info.time > childrenEndTime) {
3022-
childrenEndTime = info.time;
3064+
const time = info.time;
3065+
if (time > childrenEndTime) {
3066+
childrenEndTime = time;
30233067
}
3024-
if (endTime === 0) {
3068+
if (componentEndTime === 0) {
30253069
// Last timestamp is the end of the last component.
3026-
endTime = info.time;
3070+
componentEndTime = info.time;
30273071
}
3028-
}
3029-
if (typeof info.name === 'string' && i > 0) {
3030-
// $FlowFixMe: Refined.
3031-
const componentInfo: ReactComponentInfo = info;
3032-
const startTimeInfo = debugInfo[i - 1];
3033-
if (typeof startTimeInfo.time === 'number') {
3034-
const startTime = startTimeInfo.time;
3035-
if (
3036-
isLastComponent &&
3037-
root.status === ERRORED &&
3038-
root.reason !== response._closedReason
3039-
) {
3040-
// If this is the last component to render before this chunk rejected, then conceptually
3041-
// this component errored. If this was a cancellation then it wasn't this component that
3042-
// errored.
3043-
logComponentErrored(
3072+
if (candidateInfo !== null) {
3073+
if (typeof candidateInfo.name === 'string') {
3074+
// $FlowFixMe: Refined.
3075+
const componentInfo: ReactComponentInfo = candidateInfo;
3076+
logComponentInfo(
3077+
response,
3078+
root,
30443079
componentInfo,
30453080
trackIdx,
3046-
startTime,
3047-
endTime,
3081+
time,
3082+
componentEndTime,
30483083
childrenEndTime,
3049-
response._rootEnvironmentName,
3050-
root.reason,
3084+
isLastComponent,
30513085
);
3052-
} else {
3053-
logComponentRender(
3054-
componentInfo,
3086+
componentEndTime = time; // The end time of previous component is the start time of the next.
3087+
// Track the root most component of the result for deduping logging.
3088+
result.component = componentInfo;
3089+
isLastComponent = false;
3090+
} else if (candidateInfo.awaited) {
3091+
// $FlowFixMe: Refined.
3092+
const asyncInfo: ReactAsyncInfo = candidateInfo;
3093+
logComponentAwait(
3094+
asyncInfo,
30553095
trackIdx,
3056-
startTime,
3096+
time,
30573097
endTime,
3058-
childrenEndTime,
30593098
response._rootEnvironmentName,
30603099
);
30613100
}
3062-
// Track the root most component of the result for deduping logging.
3063-
result.component = componentInfo;
3064-
// Set the end time of the previous component to the start of the previous.
3065-
endTime = startTime;
3066-
}
3067-
isLastComponent = false;
3068-
} else if (info.awaited && i > 0 && i < debugInfo.length - 2) {
3069-
// $FlowFixMe: Refined.
3070-
const asyncInfo: ReactAsyncInfo = info;
3071-
const startTimeInfo = debugInfo[i - 1];
3072-
const endTimeInfo = debugInfo[i + 1];
3073-
if (
3074-
typeof startTimeInfo.time === 'number' &&
3075-
typeof endTimeInfo.time === 'number'
3076-
) {
3077-
const awaitStartTime = startTimeInfo.time;
3078-
const awaitEndTime = endTimeInfo.time;
3079-
logComponentAwait(
3080-
asyncInfo,
3081-
trackIdx,
3082-
awaitStartTime,
3083-
awaitEndTime,
3084-
response._rootEnvironmentName,
3085-
);
3101+
candidateInfo = null;
30863102
}
3103+
endTime = time; // The end time of the next entry is this time.
3104+
} else {
3105+
// Otherwise, store it until we know its start time.
3106+
candidateInfo = info;
30873107
}
30883108
}
30893109
}

0 commit comments

Comments
 (0)