main
js 147 lines 4.41 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import {
11 getLegacyRenderImplementation,
12 getModernRenderImplementation,
13 } from './utils';
14
15 describe('profiling HostRoot', () => {
16 let React;
17 let Scheduler;
18 let store;
19 let utils;
20 let getEffectDurations;
21 let effectDurations;
22 let passiveEffectDurations;
23
24 beforeEach(() => {
25 utils = require('./utils');
26 utils.beforeEachProfiling();
27
28 getEffectDurations = require('../backend/utils').getEffectDurations;
29
30 store = global.store;
31
32 React = require('react');
33 Scheduler = require('scheduler');
34
35 effectDurations = [];
36 passiveEffectDurations = [];
37
38 // This is the DevTools hook installed by the env.beforEach()
39 // The hook is installed as a read-only property on the window,
40 // so for our test purposes we can just override the commit hook.
41 const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
42 hook.onPostCommitFiberRoot = function onPostCommitFiberRoot(
43 rendererID,
44 root,
45 ) {
46 const {effectDuration, passiveEffectDuration} = getEffectDurations(root);
47 effectDurations.push(effectDuration);
48 passiveEffectDurations.push(passiveEffectDuration);
49 };
50 });
51
52 const {render: legacyRender} = getLegacyRenderImplementation();
53 const {render: modernRender} = getModernRenderImplementation();
54
55 // @reactVersion >= 18.0
56 // @reactVersion <= 18.2
57 it('should expose passive and layout effect durations for render()', () => {
58 function App() {
59 React.useEffect(() => {
60 Scheduler.unstable_advanceTime(10);
61 });
62 React.useLayoutEffect(() => {
63 Scheduler.unstable_advanceTime(100);
64 });
65 return null;
66 }
67
68 utils.act(() => store.profilerStore.startProfiling());
69 utils.act(() => {
70 legacyRender(<App />);
71 });
72 utils.act(() => store.profilerStore.stopProfiling());
73
74 expect(effectDurations).toHaveLength(1);
75 const effectDuration = effectDurations[0];
76 expect(effectDuration === null || effectDuration === 100).toBe(true);
77 expect(passiveEffectDurations).toHaveLength(1);
78 const passiveEffectDuration = passiveEffectDurations[0];
79 expect(passiveEffectDuration === null || passiveEffectDuration === 10).toBe(
80 true,
81 );
82 });
83
84 // @reactVersion >=18.0
85 it('should expose passive and layout effect durations for createRoot()', () => {
86 function App() {
87 React.useEffect(() => {
88 Scheduler.unstable_advanceTime(10);
89 });
90 React.useLayoutEffect(() => {
91 Scheduler.unstable_advanceTime(100);
92 });
93 return null;
94 }
95
96 utils.act(() => store.profilerStore.startProfiling());
97 utils.act(() => {
98 modernRender(<App />);
99 });
100 utils.act(() => store.profilerStore.stopProfiling());
101
102 expect(effectDurations).toHaveLength(1);
103 const effectDuration = effectDurations[0];
104 expect(effectDuration === null || effectDuration === 100).toBe(true);
105 expect(passiveEffectDurations).toHaveLength(1);
106 const passiveEffectDuration = passiveEffectDurations[0];
107 expect(passiveEffectDuration === null || passiveEffectDuration === 10).toBe(
108 true,
109 );
110 });
111
112 // @reactVersion >=18.0
113 it('should properly reset passive and layout effect durations between commits', () => {
114 function App({shouldCascade}) {
115 const [, setState] = React.useState(false);
116 React.useEffect(() => {
117 Scheduler.unstable_advanceTime(10);
118 });
119 React.useLayoutEffect(() => {
120 Scheduler.unstable_advanceTime(100);
121 });
122 React.useLayoutEffect(() => {
123 if (shouldCascade) {
124 setState(true);
125 }
126 }, [shouldCascade]);
127 return null;
128 }
129
130 utils.act(() => store.profilerStore.startProfiling());
131 utils.act(() => modernRender(<App />));
132 utils.act(() => modernRender(<App shouldCascade={true} />));
133 utils.act(() => store.profilerStore.stopProfiling());
134
135 expect(effectDurations).toHaveLength(3);
136 expect(passiveEffectDurations).toHaveLength(3);
137
138 for (let i = 0; i < effectDurations.length; i++) {
139 const effectDuration = effectDurations[i];
140 expect(effectDuration === null || effectDuration === 100).toBe(true);
141 const passiveEffectDuration = passiveEffectDurations[i];
142 expect(
143 passiveEffectDuration === null || passiveEffectDuration === 10,
144 ).toBe(true);
145 }
146 });
147 });