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;