Skip to content

Commit 99be14c

Browse files
authored
[Flight] Promote enableAsyncDebugInfo to stable without enableComponentPerformanceTrack (facebook#33996)
There's a lot of overlap between `enableComponentPerformanceTrack` and `enableAsyncDebugInfo` because they both rely on timing information. The former is mainly emit timestamps for how long server components and awaits took. The latter how long I/O took. `enableAsyncDebugInfo` is currently primarily for the component performance track but its meta data is useful for other debug tools too. This promotes that flag to stable. However, `enableComponentPerformanceTrack` needs more work due to performance concerns with Chrome DevTools so I need to separate them. This keeps doing most of the timing tracking on the server but doesn't emit the per-server component time stamps when `enableComponentPerformanceTrack` is false.
1 parent 5a04619 commit 99be14c

File tree

4 files changed

+83
-50
lines changed

4 files changed

+83
-50
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3647,7 +3647,7 @@ function initializeIOInfo(response: Response, ioInfo: ReactIOInfo): void {
36473647
// $FlowFixMe[cannot-write]
36483648
ioInfo.end += response._timeOrigin;
36493649

3650-
if (response._replayConsole) {
3650+
if (enableComponentPerformanceTrack && response._replayConsole) {
36513651
const env = response._rootEnvironmentName;
36523652
const promise = ioInfo.value;
36533653
if (promise) {
@@ -4149,7 +4149,10 @@ function processFullStringRow(
41494149
return;
41504150
}
41514151
case 78 /* "N" */: {
4152-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
4152+
if (
4153+
enableProfilerTimer &&
4154+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
4155+
) {
41534156
// Track the time origin for future debug info. We track it relative
41544157
// to the current environment's time space.
41554158
const timeOrigin: number = +row;
@@ -4169,11 +4172,7 @@ function processFullStringRow(
41694172
// Fallthrough to share the error with Console entries.
41704173
}
41714174
case 74 /* "J" */: {
4172-
if (
4173-
enableProfilerTimer &&
4174-
enableComponentPerformanceTrack &&
4175-
enableAsyncDebugInfo
4176-
) {
4175+
if (enableProfilerTimer && enableAsyncDebugInfo) {
41774176
resolveIOInfo(response, id, row);
41784177
return;
41794178
}

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,7 +2898,7 @@ describe('ReactFlight', () => {
28982898
);
28992899
});
29002900

2901-
// @gate enableAsyncIterableChildren
2901+
// @gate enableAsyncIterableChildren && enableComponentPerformanceTrack
29022902
it('preserves debug info for server-to-server pass through of async iterables', async () => {
29032903
let resolve;
29042904
const iteratorPromise = new Promise(r => (resolve = r));
@@ -3727,7 +3727,7 @@ describe('ReactFlight', () => {
37273727
expect(caughtError.digest).toBe('digest("my-error")');
37283728
});
37293729

3730-
// @gate __DEV__ && enableComponentPerformanceTrack
3730+
// @gate __DEV__ && enableComponentPerformanceTrack
37313731
it('can render deep but cut off JSX in debug info', async () => {
37323732
function createDeepJSX(n) {
37333733
if (n <= 0) {

packages/react-server/src/ReactFlightServer.js

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,10 @@ function RequestInstance(
731731
}
732732

733733
let timeOrigin: number;
734-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
734+
if (
735+
enableProfilerTimer &&
736+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
737+
) {
735738
// We start by serializing the time origin. Any future timestamps will be
736739
// emitted relatively to this origin. Instead of using performance.timeOrigin
737740
// as this origin, we use the timestamp at the start of the request.
@@ -978,7 +981,10 @@ function serializeThenable(
978981
task.keyPath, // the server component sequence continues through Promise-as-a-child.
979982
task.implicitSlot,
980983
request.abortableTasks,
981-
enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0,
984+
enableProfilerTimer &&
985+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
986+
? task.time
987+
: 0,
982988
__DEV__ ? task.debugOwner : null,
983989
__DEV__ ? task.debugStack : null,
984990
__DEV__ ? task.debugTask : null,
@@ -1048,7 +1054,10 @@ function serializeThenable(
10481054
},
10491055
reason => {
10501056
if (newTask.status === PENDING) {
1051-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
1057+
if (
1058+
enableProfilerTimer &&
1059+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
1060+
) {
10521061
// If this is async we need to time when this task finishes.
10531062
newTask.timed = true;
10541063
}
@@ -1094,7 +1103,10 @@ function serializeReadableStream(
10941103
task.keyPath,
10951104
task.implicitSlot,
10961105
request.abortableTasks,
1097-
enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0,
1106+
enableProfilerTimer &&
1107+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
1108+
? task.time
1109+
: 0,
10981110
__DEV__ ? task.debugOwner : null,
10991111
__DEV__ ? task.debugStack : null,
11001112
__DEV__ ? task.debugTask : null,
@@ -1186,7 +1198,10 @@ function serializeAsyncIterable(
11861198
task.keyPath,
11871199
task.implicitSlot,
11881200
request.abortableTasks,
1189-
enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0,
1201+
enableProfilerTimer &&
1202+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
1203+
? task.time
1204+
: 0,
11901205
__DEV__ ? task.debugOwner : null,
11911206
__DEV__ ? task.debugStack : null,
11921207
__DEV__ ? task.debugTask : null,
@@ -1616,7 +1631,10 @@ function renderFunctionComponent<Props>(
16161631
outlineComponentInfo(request, componentDebugInfo);
16171632

16181633
// Track when we started rendering this component.
1619-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
1634+
if (
1635+
enableProfilerTimer &&
1636+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
1637+
) {
16201638
advanceTaskTime(request, task, performance.now());
16211639
}
16221640

@@ -1686,12 +1704,7 @@ function renderFunctionComponent<Props>(
16861704
throw null;
16871705
}
16881706

1689-
if (
1690-
__DEV__ ||
1691-
(enableProfilerTimer &&
1692-
enableComponentPerformanceTrack &&
1693-
enableAsyncDebugInfo)
1694-
) {
1707+
if (__DEV__ || (enableProfilerTimer && enableAsyncDebugInfo)) {
16951708
// Forward any debug information for any Promises that we use():ed during the render.
16961709
// We do this at the end so that we don't keep doing this for each retry.
16971710
const trackedThenables = getTrackedThenablesAfterRendering();
@@ -2016,7 +2029,10 @@ function deferTask(request: Request, task: Task): ReactJSONValue {
20162029
task.keyPath, // unlike outlineModel this one carries along context
20172030
task.implicitSlot,
20182031
request.abortableTasks,
2019-
enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0,
2032+
enableProfilerTimer &&
2033+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
2034+
? task.time
2035+
: 0,
20202036
__DEV__ ? task.debugOwner : null,
20212037
__DEV__ ? task.debugStack : null,
20222038
__DEV__ ? task.debugTask : null,
@@ -2033,7 +2049,10 @@ function outlineTask(request: Request, task: Task): ReactJSONValue {
20332049
task.keyPath, // unlike outlineModel this one carries along context
20342050
task.implicitSlot,
20352051
request.abortableTasks,
2036-
enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0,
2052+
enableProfilerTimer &&
2053+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
2054+
? task.time
2055+
: 0,
20372056
__DEV__ ? task.debugOwner : null,
20382057
__DEV__ ? task.debugStack : null,
20392058
__DEV__ ? task.debugTask : null,
@@ -2482,7 +2501,10 @@ function emitAsyncSequence(
24822501
}
24832502

24842503
function pingTask(request: Request, task: Task): void {
2485-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
2504+
if (
2505+
enableProfilerTimer &&
2506+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
2507+
) {
24862508
// If this was async we need to emit the time when it completes.
24872509
task.timed = true;
24882510
}
@@ -2587,7 +2609,10 @@ function createTask(
25872609
| 'debugStack'
25882610
| 'debugTask',
25892611
>): any);
2590-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
2612+
if (
2613+
enableProfilerTimer &&
2614+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
2615+
) {
25912616
task.timed = false;
25922617
task.time = lastTimestamp;
25932618
}
@@ -2795,7 +2820,8 @@ function outlineModel(request: Request, value: ReactClientValue): number {
27952820
null, // The way we use outlining is for reusing an object.
27962821
false, // It makes no sense for that use case to be contextual.
27972822
request.abortableTasks,
2798-
enableProfilerTimer && enableComponentPerformanceTrack
2823+
enableProfilerTimer &&
2824+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
27992825
? performance.now() // TODO: This should really inherit the time from the task.
28002826
: 0,
28012827
null, // TODO: Currently we don't associate any debug information with
@@ -3041,7 +3067,8 @@ function serializeBlob(request: Request, blob: Blob): string {
30413067
null,
30423068
false,
30433069
request.abortableTasks,
3044-
enableProfilerTimer && enableComponentPerformanceTrack
3070+
enableProfilerTimer &&
3071+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
30453072
? performance.now() // TODO: This should really inherit the time from the task.
30463073
: 0,
30473074
null, // TODO: Currently we don't associate any debug information with
@@ -3177,7 +3204,8 @@ function renderModel(
31773204
task.keyPath,
31783205
task.implicitSlot,
31793206
request.abortableTasks,
3180-
enableProfilerTimer && enableComponentPerformanceTrack
3207+
enableProfilerTimer &&
3208+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
31813209
? task.time
31823210
: 0,
31833211
__DEV__ ? task.debugOwner : null,
@@ -5130,11 +5158,7 @@ function forwardDebugInfoFromThenable(
51305158
forwardDebugInfo(request, task, debugInfo);
51315159
}
51325160
}
5133-
if (
5134-
enableProfilerTimer &&
5135-
enableComponentPerformanceTrack &&
5136-
enableAsyncDebugInfo
5137-
) {
5161+
if (enableProfilerTimer && enableAsyncDebugInfo) {
51385162
const sequence = getAsyncSequenceFromPromise(thenable);
51395163
if (sequence !== null) {
51405164
emitAsyncSequence(request, task, sequence, debugInfo, owner, stack);
@@ -5155,11 +5179,7 @@ function forwardDebugInfoFromCurrentContext(
51555179
forwardDebugInfo(request, task, debugInfo);
51565180
}
51575181
}
5158-
if (
5159-
enableProfilerTimer &&
5160-
enableComponentPerformanceTrack &&
5161-
enableAsyncDebugInfo
5162-
) {
5182+
if (enableProfilerTimer && enableAsyncDebugInfo) {
51635183
const sequence = getCurrentAsyncSequence();
51645184
if (sequence !== null) {
51655185
emitAsyncSequence(request, task, sequence, debugInfo, null, null);
@@ -5182,11 +5202,7 @@ function forwardDebugInfoFromAbortedTask(request: Request, task: Task): void {
51825202
forwardDebugInfo(request, task, debugInfo);
51835203
}
51845204
}
5185-
if (
5186-
enableProfilerTimer &&
5187-
enableComponentPerformanceTrack &&
5188-
enableAsyncDebugInfo
5189-
) {
5205+
if (enableProfilerTimer && enableAsyncDebugInfo) {
51905206
let thenable: null | Thenable<any> = null;
51915207
if (typeof model.then === 'function') {
51925208
thenable = (model: any);
@@ -5262,7 +5278,10 @@ function advanceTaskTime(
52625278
task: Task,
52635279
timestamp: number,
52645280
): void {
5265-
if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
5281+
if (
5282+
!enableProfilerTimer ||
5283+
(!enableComponentPerformanceTrack && !enableAsyncDebugInfo)
5284+
) {
52665285
return;
52675286
}
52685287
// Emits a timing chunk, if the new timestamp is higher than the previous timestamp of this task.
@@ -5278,7 +5297,10 @@ function advanceTaskTime(
52785297
}
52795298

52805299
function markOperationEndTime(request: Request, task: Task, timestamp: number) {
5281-
if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
5300+
if (
5301+
!enableProfilerTimer ||
5302+
(!enableComponentPerformanceTrack && !enableAsyncDebugInfo)
5303+
) {
52825304
return;
52835305
}
52845306
// This is like advanceTaskTime() but always emits a timing chunk even if it doesn't advance.
@@ -5384,7 +5406,10 @@ function emitChunk(
53845406
}
53855407

53865408
function erroredTask(request: Request, task: Task, error: mixed): void {
5387-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
5409+
if (
5410+
enableProfilerTimer &&
5411+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
5412+
) {
53885413
if (task.timed) {
53895414
markOperationEndTime(request, task, performance.now());
53905415
}
@@ -5467,7 +5492,10 @@ function retryTask(request: Request, task: Task): void {
54675492
}
54685493
}
54695494
// We've finished rendering. Log the end time.
5470-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
5495+
if (
5496+
enableProfilerTimer &&
5497+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
5498+
) {
54715499
if (task.timed) {
54725500
markOperationEndTime(request, task, performance.now());
54735501
}
@@ -5605,7 +5633,10 @@ function finishAbortedTask(
56055633
}
56065634
forwardDebugInfoFromAbortedTask(request, task);
56075635
// Track when we aborted this task as its end time.
5608-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
5636+
if (
5637+
enableProfilerTimer &&
5638+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
5639+
) {
56095640
if (task.timed) {
56105641
markOperationEndTime(request, task, request.abortTime);
56115642
}
@@ -5921,7 +5952,10 @@ export function abort(request: Request, reason: mixed): void {
59215952
}
59225953
try {
59235954
request.status = ABORTING;
5924-
if (enableProfilerTimer && enableComponentPerformanceTrack) {
5955+
if (
5956+
enableProfilerTimer &&
5957+
(enableComponentPerformanceTrack || enableAsyncDebugInfo)
5958+
) {
59255959
request.abortTime = performance.now();
59265960
}
59275961
request.cacheController.abort(reason);

packages/shared/ReactFeatureFlags.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ export const enableProfilerCommitHooks = __PROFILE__;
247247
// Phase param passed to onRender callback differentiates between an "update" and a "cascading-update".
248248
export const enableProfilerNestedUpdatePhase = __PROFILE__;
249249

250-
export const enableAsyncDebugInfo = __EXPERIMENTAL__;
250+
export const enableAsyncDebugInfo = true;
251251

252252
// Track which Fiber(s) schedule render work.
253253
export const enableUpdaterTracking = __PROFILE__;

0 commit comments

Comments
 (0)