Skip to content

Commit edcb8c8

Browse files
committed
Don't assume time entries are always before and after every entry
1 parent 20a8358 commit edcb8c8

File tree

1 file changed

+74
-53
lines changed

1 file changed

+74
-53
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 74 additions & 53 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>,
@@ -2979,6 +3019,7 @@ function flushComponentPerformance(
29793019
if (typeof info.time === 'number') {
29803020
if (info.time > parentEndTime) {
29813021
parentEndTime = info.time;
3022+
break; // We assume the highest number is at the end.
29823023
}
29833024
}
29843025
}
@@ -3013,77 +3054,57 @@ function flushComponentPerformance(
30133054
}
30143055

30153056
if (debugInfo) {
3057+
// Write debug info in reverse order (just like stack traces).
30163058
let endTime = 0;
3059+
let componentEndTime = 0;
30173060
let isLastComponent = true;
3061+
let candidateInfo = null; // An entry we can write once we know its start time.
30183062
for (let i = debugInfo.length - 1; i >= 0; i--) {
30193063
const info = debugInfo[i];
30203064
if (typeof info.time === 'number') {
3021-
if (info.time > childrenEndTime) {
3022-
childrenEndTime = info.time;
3065+
const time = info.time;
3066+
if (time > childrenEndTime) {
3067+
childrenEndTime = time;
30233068
}
3024-
if (endTime === 0) {
3069+
if (componentEndTime === 0) {
30253070
// Last timestamp is the end of the last component.
3026-
endTime = info.time;
3071+
componentEndTime = info.time;
30273072
}
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(
3073+
if (candidateInfo !== null) {
3074+
if (typeof candidateInfo.name === 'string') {
3075+
// $FlowFixMe: Refined.
3076+
const componentInfo: ReactComponentInfo = candidateInfo;
3077+
logComponentInfo(
3078+
response,
3079+
root,
30443080
componentInfo,
30453081
trackIdx,
3046-
startTime,
3047-
endTime,
3082+
time,
3083+
componentEndTime,
30483084
childrenEndTime,
3049-
response._rootEnvironmentName,
3050-
root.reason,
3085+
isLastComponent,
30513086
);
3052-
} else {
3053-
logComponentRender(
3054-
componentInfo,
3087+
componentEndTime = time; // The end time of previous component is the start time of the next.
3088+
// Track the root most component of the result for deduping logging.
3089+
result.component = componentInfo;
3090+
isLastComponent = false;
3091+
} else if (candidateInfo.awaited) {
3092+
// $FlowFixMe: Refined.
3093+
const asyncInfo: ReactAsyncInfo = candidateInfo;
3094+
logComponentAwait(
3095+
asyncInfo,
30553096
trackIdx,
3056-
startTime,
3097+
time,
30573098
endTime,
3058-
childrenEndTime,
30593099
response._rootEnvironmentName,
30603100
);
30613101
}
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-
);
3102+
candidateInfo = null;
30863103
}
3104+
endTime = time; // The end time of the next entry is this time.
3105+
} else {
3106+
// Otherwise, store it until we know its start time.
3107+
candidateInfo = info;
30873108
}
30883109
}
30893110
}

0 commit comments

Comments
 (0)