@samitouri / QOS-React / commits / 548235db10

Enable React performance tracks in Canary (#34665)

Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>

Sebastian "Sebbie" Silbermann committed Oct 1, 2025 at 18:13 UTC 548235db1077648029af40fe8e75621ad56586fb
4 files changed +25 -17
packages/react-devtools-shared/src/__tests__/preprocessData-test.js
+20 -13
@@ -24,21 +24,8 @@ let utils;
24 let assertLog;
25 let waitFor;
26
27 -// This flag is on experimental which disables timeline profiler.
28 -const enableComponentPerformanceTrack =
29 - React.version.startsWith('19') && React.version.includes('experimental');
30 -
27 describe('Timeline profiler', () => {
32 - if (enableComponentPerformanceTrack) {
33 - test('no tests', () => {});
34 - // Ignore all tests.
35 - return;
36 - }
37 -
28 describe('User Timing API', () => {
39 - if (enableComponentPerformanceTrack) {
40 - return;
41 - }
29 let currentlyNotClearedMarks;
30 let registeredMarks;
31 let featureDetectionMarkName = null;
@@ -168,6 +155,7 @@ describe('Timeline profiler', () => {
155 });
156
157 // @reactVersion >= 18.0
158 + // @reactVersion < 19.2
159 it('should return array of lane numbers from bitmask string', () => {
160 expect(getLanesFromTransportDecimalBitmask('1')).toEqual([0]);
161 expect(getLanesFromTransportDecimalBitmask('512')).toEqual([9]);
@@ -184,6 +172,7 @@ describe('Timeline profiler', () => {
172 });
173
174 // @reactVersion >= 18.0
175 + // @reactVersion < 19.2
176 it('should return empty array if laneBitmaskString is not a bitmask', () => {
177 expect(getLanesFromTransportDecimalBitmask('')).toEqual([]);
178 expect(getLanesFromTransportDecimalBitmask('hello')).toEqual([]);
@@ -192,6 +181,7 @@ describe('Timeline profiler', () => {
181 });
182
183 // @reactVersion >= 18.0
184 + // @reactVersion < 19.2
185 it('should ignore lanes outside REACT_TOTAL_NUM_LANES', () => {
186 const REACT_TOTAL_NUM_LANES =
187 require('react-devtools-timeline/src/constants').REACT_TOTAL_NUM_LANES;
@@ -317,11 +307,13 @@ describe('Timeline profiler', () => {
307 });
308
309 // @reactVersion >= 18.0
310 + // @reactVersion < 19.2
311 it('should throw given an empty timeline', async () => {
312 await expect(async () => preprocessData([])).rejects.toThrow();
313 });
314
315 // @reactVersion >= 18.0
316 + // @reactVersion < 19.2
317 it('should throw given a timeline with no Profile event', async () => {
318 const randomSample = createUserTimingEntry({
319 dur: 100,
@@ -338,6 +330,7 @@ describe('Timeline profiler', () => {
330 });
331
332 // @reactVersion >= 18.0
333 + // @reactVersion < 19.2
334 it('should throw given a timeline without an explicit profiler version mark nor any other React marks', async () => {
335 const cpuProfilerSample = creactCpuProfilerSample();
336
@@ -349,6 +342,7 @@ describe('Timeline profiler', () => {
342 });
343
344 // @reactVersion >= 18.0
345 + // @reactVersion < 19.2
346 it('should throw given a timeline with React scheduling marks, but without an explicit profiler version mark', async () => {
347 const cpuProfilerSample = creactCpuProfilerSample();
348 const scheduleRenderSample = createUserTimingEntry({
@@ -363,6 +357,7 @@ describe('Timeline profiler', () => {
357 });
358
359 // @reactVersion >= 18.0
360 + // @reactVersion < 19.2
361 it('should return empty data given a timeline with no React scheduling profiling marks', async () => {
362 const cpuProfilerSample = creactCpuProfilerSample();
363 const randomSample = createUserTimingEntry({
@@ -467,6 +462,7 @@ describe('Timeline profiler', () => {
462 });
463
464 // @reactVersion >= 18.0
465 + // @reactVersion < 19.2
466 it('should process legacy data format (before lane labels were added)', async () => {
467 const cpuProfilerSample = creactCpuProfilerSample();
468
@@ -854,6 +850,7 @@ describe('Timeline profiler', () => {
850 `);
851 });
852
853 + // @reactVersion < 19.2
854 it('should process a sample createRoot render sequence', async () => {
855 function App() {
856 const [didMount, setDidMount] = React.useState(false);
@@ -1190,6 +1187,7 @@ describe('Timeline profiler', () => {
1187 });
1188
1189 // @reactVersion >= 18.0
1190 + // @reactVersion < 19.2
1191 it('should populate other user timing marks', async () => {
1192 const userTimingData = createUserTimingData([]);
1193 userTimingData.push(
@@ -1240,6 +1238,7 @@ describe('Timeline profiler', () => {
1238 });
1239
1240 // @reactVersion >= 18.0
1241 + // @reactVersion < 19.2
1242 it('should include a suspended resource "displayName" if one is set', async () => {
1243 let promise = null;
1244 let resolvedValue = null;
@@ -1381,6 +1380,7 @@ describe('Timeline profiler', () => {
1380 });
1381
1382 // @reactVersion >= 18.2
1383 + // @reactVersion < 19.2
1384 it('should not warn when React finishes a previously long (async) update with a short (sync) update inside of an event', async () => {
1385 function Yield({id, value}) {
1386 Scheduler.log(`${id}:${value}`);
@@ -1443,6 +1443,7 @@ describe('Timeline profiler', () => {
1443
1444 describe('nested updates', () => {
1445 // @reactVersion >= 18.2
1446 + // @reactVersion < 19.2
1447 it('should not warn about short nested (state) updates during layout effects', async () => {
1448 function Component() {
1449 const [didMount, setDidMount] = React.useState(false);
@@ -1474,6 +1475,7 @@ describe('Timeline profiler', () => {
1475 });
1476
1477 // @reactVersion >= 18.2
1478 + // @reactVersion < 19.2
1479 it('should not warn about short (forced) updates during layout effects', async () => {
1480 class Component extends React.Component {
1481 _didMount: boolean = false;
@@ -1629,6 +1631,7 @@ describe('Timeline profiler', () => {
1631 });
1632
1633 // @reactVersion >= 18.2
1634 + // @reactVersion < 19.2
1635 it('should not warn about transition updates scheduled during commit phase', async () => {
1636 function Component() {
1637 const [value, setValue] = React.useState(0);
@@ -1770,6 +1773,7 @@ describe('Timeline profiler', () => {
1773
1774 describe('errors thrown while rendering', () => {
1775 // @reactVersion >= 18.0
1776 + // @reactVersion < 19.2
1777 it('shoult parse Errors thrown during render', async () => {
1778 jest.spyOn(console, 'error');
1779
@@ -1818,6 +1822,7 @@ describe('Timeline profiler', () => {
1822 // This also tests an edge case where a component suspends while profiling
1823 // before the first commit is logged (so the lane-to-labels map will not yet exist).
1824 // @reactVersion >= 18.2
1825 + // @reactVersion < 19.2
1826 it('should warn about suspending during an update', async () => {
1827 let promise = null;
1828 let resolvedValue = null;
@@ -1884,6 +1889,7 @@ describe('Timeline profiler', () => {
1889 });
1890
1891 // @reactVersion >= 18.2
1892 + // @reactVersion < 19.2
1893 it('should not warn about suspending during an transition', async () => {
1894 let promise = null;
1895 let resolvedValue = null;
@@ -2152,6 +2158,7 @@ describe('Timeline profiler', () => {
2158 `);
2159 });
2160
2161 + // @reactVersion < 19.2
2162 it('should process a sample createRoot render sequence', async () => {
2163 function App() {
2164 const [didMount, setDidMount] = React.useState(false);
packages/shared/ReactFeatureFlags.js
+1 -1
@@ -229,7 +229,7 @@ export const enableProfilerTimer = __PROFILE__;
229 // Component rendering tracks to show up in the Performance tab.
230 // This flag will be used for both Server Component and Client Component tracks.
231 // All calls should also be gated on enableProfilerTimer.
232 -export const enableComponentPerformanceTrack = __EXPERIMENTAL__;
232 +export const enableComponentPerformanceTrack: boolean = true;
233
234 // Adds user timing marks for e.g. state updates, suspense, and work loop stuff,
235 // for an experimental timeline tool.
packages/shared/forks/ReactFeatureFlags.native-oss.js
+3 -2
@@ -41,8 +41,9 @@ export const enableObjectFiber: boolean = false;
41 export const enablePostpone: boolean = false;
42 export const enableReactTestRendererWarning: boolean = false;
43 export const enableRetryLaneExpiration: boolean = false;
44 -export const enableSchedulingProfiler: boolean = __PROFILE__;
45 -export const enableComponentPerformanceTrack: boolean = false;
44 +export const enableComponentPerformanceTrack: boolean = true;
45 +export const enableSchedulingProfiler: boolean =
46 + !enableComponentPerformanceTrack && __PROFILE__;
47 export const enableScopeAPI: boolean = false;
48 export const enableEagerAlternateStateNodeCleanup: boolean = true;
49 export const enableSuspenseAvoidThisFallback: boolean = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1 -1
@@ -15,7 +15,7 @@ export const enableSchedulingProfiler: boolean = false;
15 export const enableProfilerTimer: boolean = __PROFILE__;
16 export const enableProfilerCommitHooks: boolean = __PROFILE__;
17 export const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;
18 -export const enableComponentPerformanceTrack: boolean = false;
18 +export const enableComponentPerformanceTrack: boolean = true;
19 export const enableUpdaterTracking: boolean = false;
20 export const enableLegacyCache: boolean = __EXPERIMENTAL__;
21 export const enableAsyncIterableChildren: boolean = false;