diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index 4403687383ae7..4a13d094a826b 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -3647,7 +3647,7 @@ function initializeIOInfo(response: Response, ioInfo: ReactIOInfo): void { // $FlowFixMe[cannot-write] ioInfo.end += response._timeOrigin; - if (response._replayConsole) { + if (enableComponentPerformanceTrack && response._replayConsole) { const env = response._rootEnvironmentName; const promise = ioInfo.value; if (promise) { @@ -4149,7 +4149,10 @@ function processFullStringRow( return; } case 78 /* "N" */: { - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { // Track the time origin for future debug info. We track it relative // to the current environment's time space. const timeOrigin: number = +row; @@ -4169,11 +4172,7 @@ function processFullStringRow( // Fallthrough to share the error with Console entries. } case 74 /* "J" */: { - if ( - enableProfilerTimer && - enableComponentPerformanceTrack && - enableAsyncDebugInfo - ) { + if (enableProfilerTimer && enableAsyncDebugInfo) { resolveIOInfo(response, id, row); return; } diff --git a/packages/react-client/src/ReactFlightPerformanceTrack.js b/packages/react-client/src/ReactFlightPerformanceTrack.js index 0832497d9445c..984408500d532 100644 --- a/packages/react-client/src/ReactFlightPerformanceTrack.js +++ b/packages/react-client/src/ReactFlightPerformanceTrack.js @@ -110,7 +110,7 @@ export function logComponentRender( } debugTask.run( // $FlowFixMe[method-unbinding] - performance.measure.bind(performance, entryName, { + performance.measure.bind(performance, '\u200b' + entryName, { start: startTime < 0 ? 0 : startTime, end: childrenEndTime, detail: { @@ -125,7 +125,7 @@ export function logComponentRender( ); } else { console.timeStamp( - entryName, + '\u200b' + entryName, startTime < 0 ? 0 : startTime, childrenEndTime, trackNames[trackIdx], @@ -163,7 +163,7 @@ export function logComponentAborted( if (componentInfo.props != null) { addObjectToProperties(componentInfo.props, properties, 0, ''); } - performance.measure(entryName, { + performance.measure('\u200b' + entryName, { start: startTime < 0 ? 0 : startTime, end: childrenEndTime, detail: { @@ -220,7 +220,7 @@ export function logComponentErrored( if (componentInfo.props != null) { addObjectToProperties(componentInfo.props, properties, 0, ''); } - performance.measure(entryName, { + performance.measure('\u200b' + entryName, { start: startTime < 0 ? 0 : startTime, end: childrenEndTime, detail: { @@ -614,7 +614,7 @@ export function logIOInfoErrored( getIOLongName(ioInfo, description, ioInfo.env, rootEnv) + ' Rejected'; debugTask.run( // $FlowFixMe[method-unbinding] - performance.measure.bind(performance, entryName, { + performance.measure.bind(performance, '\u200b' + entryName, { start: startTime < 0 ? 0 : startTime, end: endTime, detail: { @@ -667,7 +667,7 @@ export function logIOInfo( ); debugTask.run( // $FlowFixMe[method-unbinding] - performance.measure.bind(performance, entryName, { + performance.measure.bind(performance, '\u200b' + entryName, { start: startTime < 0 ? 0 : startTime, end: endTime, detail: { diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js index 2ccf874cee91b..150997c1c3746 100644 --- a/packages/react-client/src/__tests__/ReactFlight-test.js +++ b/packages/react-client/src/__tests__/ReactFlight-test.js @@ -2898,7 +2898,7 @@ describe('ReactFlight', () => { ); }); - // @gate enableAsyncIterableChildren + // @gate enableAsyncIterableChildren && enableComponentPerformanceTrack it('preserves debug info for server-to-server pass through of async iterables', async () => { let resolve; const iteratorPromise = new Promise(r => (resolve = r)); @@ -3727,7 +3727,7 @@ describe('ReactFlight', () => { expect(caughtError.digest).toBe('digest("my-error")'); }); - // @gate __DEV__ && enableComponentPerformanceTrack + // @gate __DEV__ && enableComponentPerformanceTrack it('can render deep but cut off JSX in debug info', async () => { function createDeepJSX(n) { if (n <= 0) { diff --git a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js index 3f5f92c895b8f..4f70a589cb08d 100644 --- a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js +++ b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js @@ -272,7 +272,7 @@ export function logComponentRender( // $FlowFixMe[method-unbinding] performance.measure.bind( performance, - name, + '\u200b' + name, reusableComponentOptions, ), ); @@ -369,10 +369,10 @@ export function logComponentErrored( if (__DEV__ && debugTask) { debugTask.run( // $FlowFixMe[method-unbinding] - performance.measure.bind(performance, name, options), + performance.measure.bind(performance, '\u200b' + name, options), ); } else { - performance.measure(name, options); + performance.measure('\u200b' + name, options); } } else { console.timeStamp( @@ -436,10 +436,10 @@ function logComponentEffectErrored( if (debugTask) { debugTask.run( // $FlowFixMe[method-unbinding] - performance.measure.bind(performance, name, options), + performance.measure.bind(performance, '\u200b' + name, options), ); } else { - performance.measure(name, options); + performance.measure('\u200b' + name, options); } } else { console.timeStamp( diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 30698b8311acc..1a5cee7ba7245 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -731,7 +731,10 @@ function RequestInstance( } let timeOrigin: number; - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { // We start by serializing the time origin. Any future timestamps will be // emitted relatively to this origin. Instead of using performance.timeOrigin // as this origin, we use the timestamp at the start of the request. @@ -978,7 +981,10 @@ function serializeThenable( task.keyPath, // the server component sequence continues through Promise-as-a-child. task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0, + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ? task.time + : 0, __DEV__ ? task.debugOwner : null, __DEV__ ? task.debugStack : null, __DEV__ ? task.debugTask : null, @@ -1048,7 +1054,10 @@ function serializeThenable( }, reason => { if (newTask.status === PENDING) { - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { // If this is async we need to time when this task finishes. newTask.timed = true; } @@ -1094,7 +1103,10 @@ function serializeReadableStream( task.keyPath, task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0, + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ? task.time + : 0, __DEV__ ? task.debugOwner : null, __DEV__ ? task.debugStack : null, __DEV__ ? task.debugTask : null, @@ -1186,7 +1198,10 @@ function serializeAsyncIterable( task.keyPath, task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0, + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ? task.time + : 0, __DEV__ ? task.debugOwner : null, __DEV__ ? task.debugStack : null, __DEV__ ? task.debugTask : null, @@ -1616,7 +1631,10 @@ function renderFunctionComponent( outlineComponentInfo(request, componentDebugInfo); // Track when we started rendering this component. - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { advanceTaskTime(request, task, performance.now()); } @@ -1686,12 +1704,7 @@ function renderFunctionComponent( throw null; } - if ( - __DEV__ || - (enableProfilerTimer && - enableComponentPerformanceTrack && - enableAsyncDebugInfo) - ) { + if (__DEV__ || (enableProfilerTimer && enableAsyncDebugInfo)) { // Forward any debug information for any Promises that we use():ed during the render. // We do this at the end so that we don't keep doing this for each retry. const trackedThenables = getTrackedThenablesAfterRendering(); @@ -2016,7 +2029,10 @@ function deferTask(request: Request, task: Task): ReactJSONValue { task.keyPath, // unlike outlineModel this one carries along context task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0, + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ? task.time + : 0, __DEV__ ? task.debugOwner : null, __DEV__ ? task.debugStack : null, __DEV__ ? task.debugTask : null, @@ -2033,7 +2049,10 @@ function outlineTask(request: Request, task: Task): ReactJSONValue { task.keyPath, // unlike outlineModel this one carries along context task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack ? task.time : 0, + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ? task.time + : 0, __DEV__ ? task.debugOwner : null, __DEV__ ? task.debugStack : null, __DEV__ ? task.debugTask : null, @@ -2482,7 +2501,10 @@ function emitAsyncSequence( } function pingTask(request: Request, task: Task): void { - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { // If this was async we need to emit the time when it completes. task.timed = true; } @@ -2587,7 +2609,10 @@ function createTask( | 'debugStack' | 'debugTask', >): any); - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { task.timed = false; task.time = lastTimestamp; } @@ -2795,7 +2820,8 @@ function outlineModel(request: Request, value: ReactClientValue): number { null, // The way we use outlining is for reusing an object. false, // It makes no sense for that use case to be contextual. request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) ? performance.now() // TODO: This should really inherit the time from the task. : 0, null, // TODO: Currently we don't associate any debug information with @@ -3041,7 +3067,8 @@ function serializeBlob(request: Request, blob: Blob): string { null, false, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) ? performance.now() // TODO: This should really inherit the time from the task. : 0, null, // TODO: Currently we don't associate any debug information with @@ -3177,7 +3204,8 @@ function renderModel( task.keyPath, task.implicitSlot, request.abortableTasks, - enableProfilerTimer && enableComponentPerformanceTrack + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) ? task.time : 0, __DEV__ ? task.debugOwner : null, @@ -5130,11 +5158,7 @@ function forwardDebugInfoFromThenable( forwardDebugInfo(request, task, debugInfo); } } - if ( - enableProfilerTimer && - enableComponentPerformanceTrack && - enableAsyncDebugInfo - ) { + if (enableProfilerTimer && enableAsyncDebugInfo) { const sequence = getAsyncSequenceFromPromise(thenable); if (sequence !== null) { emitAsyncSequence(request, task, sequence, debugInfo, owner, stack); @@ -5155,11 +5179,7 @@ function forwardDebugInfoFromCurrentContext( forwardDebugInfo(request, task, debugInfo); } } - if ( - enableProfilerTimer && - enableComponentPerformanceTrack && - enableAsyncDebugInfo - ) { + if (enableProfilerTimer && enableAsyncDebugInfo) { const sequence = getCurrentAsyncSequence(); if (sequence !== null) { emitAsyncSequence(request, task, sequence, debugInfo, null, null); @@ -5182,11 +5202,7 @@ function forwardDebugInfoFromAbortedTask(request: Request, task: Task): void { forwardDebugInfo(request, task, debugInfo); } } - if ( - enableProfilerTimer && - enableComponentPerformanceTrack && - enableAsyncDebugInfo - ) { + if (enableProfilerTimer && enableAsyncDebugInfo) { let thenable: null | Thenable = null; if (typeof model.then === 'function') { thenable = (model: any); @@ -5262,7 +5278,10 @@ function advanceTaskTime( task: Task, timestamp: number, ): void { - if (!enableProfilerTimer || !enableComponentPerformanceTrack) { + if ( + !enableProfilerTimer || + (!enableComponentPerformanceTrack && !enableAsyncDebugInfo) + ) { return; } // Emits a timing chunk, if the new timestamp is higher than the previous timestamp of this task. @@ -5278,7 +5297,10 @@ function advanceTaskTime( } function markOperationEndTime(request: Request, task: Task, timestamp: number) { - if (!enableProfilerTimer || !enableComponentPerformanceTrack) { + if ( + !enableProfilerTimer || + (!enableComponentPerformanceTrack && !enableAsyncDebugInfo) + ) { return; } // This is like advanceTaskTime() but always emits a timing chunk even if it doesn't advance. @@ -5384,7 +5406,10 @@ function emitChunk( } function erroredTask(request: Request, task: Task, error: mixed): void { - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { if (task.timed) { markOperationEndTime(request, task, performance.now()); } @@ -5467,7 +5492,10 @@ function retryTask(request: Request, task: Task): void { } } // We've finished rendering. Log the end time. - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { if (task.timed) { markOperationEndTime(request, task, performance.now()); } @@ -5605,7 +5633,10 @@ function finishAbortedTask( } forwardDebugInfoFromAbortedTask(request, task); // Track when we aborted this task as its end time. - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { if (task.timed) { markOperationEndTime(request, task, request.abortTime); } @@ -5921,7 +5952,10 @@ export function abort(request: Request, reason: mixed): void { } try { request.status = ABORTING; - if (enableProfilerTimer && enableComponentPerformanceTrack) { + if ( + enableProfilerTimer && + (enableComponentPerformanceTrack || enableAsyncDebugInfo) + ) { request.abortTime = performance.now(); } request.cacheController.abort(reason); diff --git a/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js b/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js index 68c3431adc0c7..0a98d87e363ca 100644 --- a/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js +++ b/packages/react-server/src/__tests__/ReactFlightAsyncDebugInfo-test.js @@ -610,7 +610,7 @@ describe('ReactFlightAsyncDebugInfo', () => { expect(entries).toMatchInlineSnapshot(` [ { - "name": "Component", + "name": "\u200bComponent", }, { "name": "await getData (…/pulls)", diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 0e80e113490e5..5dd612837a6b9 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -247,7 +247,7 @@ export const enableProfilerCommitHooks = __PROFILE__; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". export const enableProfilerNestedUpdatePhase = __PROFILE__; -export const enableAsyncDebugInfo = __EXPERIMENTAL__; +export const enableAsyncDebugInfo = true; // Track which Fiber(s) schedule render work. export const enableUpdaterTracking = __PROFILE__;