Skip to content

Commit 36fd29f

Browse files
author
Brian Vaughn
authored
Don't show empty (no work) commits in Profiler (#17253)
1 parent a2e05b6 commit 36fd29f

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

packages/react-devtools-shared/src/__tests__/profilerStore-test.js

+40
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,44 @@ describe('ProfilerStore', () => {
7979
store.profilerStore.profilingData = fauxProfilingData;
8080
expect(store.profilerStore.profilingData).toBe(fauxProfilingData);
8181
});
82+
83+
// This test covers current broken behavior (arguably) with the synthetic event system.
84+
it('should filter empty commits', () => {
85+
const inputRef = React.createRef();
86+
const ControlledInput = () => {
87+
const [name, setName] = React.useState('foo');
88+
const handleChange = event => setName(event.target.value);
89+
return <input ref={inputRef} value={name} onChange={handleChange} />;
90+
};
91+
92+
const container = document.createElement('div');
93+
94+
// This element has to be in the <body> for the event system to work.
95+
document.body.appendChild(container);
96+
97+
// It's important that this test uses legacy sync mode.
98+
// The root API does not trigger this particular failing case.
99+
ReactDOM.render(<ControlledInput />, container);
100+
101+
utils.act(() => store.profilerStore.startProfiling());
102+
103+
// Sets a value in a way that React doesn't see,
104+
// so that a subsequent "change" event will trigger the event handler.
105+
const setUntrackedValue = Object.getOwnPropertyDescriptor(
106+
HTMLInputElement.prototype,
107+
'value',
108+
).set;
109+
110+
const target = inputRef.current;
111+
setUntrackedValue.call(target, 'bar');
112+
target.dispatchEvent(new Event('input', {bubbles: true, cancelable: true}));
113+
expect(target.value).toBe('bar');
114+
115+
utils.act(() => store.profilerStore.stopProfiling());
116+
117+
// Only one commit should have been recorded (in response to the "change" event).
118+
const root = store.roots[0];
119+
const data = store.profilerStore.getDataForRoot(root);
120+
expect(data.commitData).toHaveLength(1);
121+
});
82122
});

packages/react-devtools-shared/src/backend/renderer.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,7 @@ export function attach(
16431643
}
16441644
}
16451645
}
1646+
16461647
if (shouldIncludeInTree) {
16471648
const isProfilingSupported = nextFiber.hasOwnProperty('treeBaseDuration');
16481649
if (isProfilingSupported) {
@@ -1742,6 +1743,14 @@ export function attach(
17421743
const current = root.current;
17431744
const alternate = current.alternate;
17441745

1746+
// Certain types of updates bail out at the root without doing any actual render work.
1747+
// React should probably not call the DevTools commit hook in this case,
1748+
// but if it does- we can detect it and filter them out from the profiler.
1749+
const didBailoutAtRoot =
1750+
alternate !== null &&
1751+
alternate.expirationTime === 0 &&
1752+
alternate.childExpirationTime === 0;
1753+
17451754
currentRootID = getFiberID(getPrimaryFiber(current));
17461755

17471756
// Before the traversals, remember to start tracking
@@ -1758,7 +1767,7 @@ export function attach(
17581767
// where some v16 renderers support profiling and others don't.
17591768
const isProfilingSupported = root.memoizedInteractions != null;
17601769

1761-
if (isProfiling && isProfilingSupported) {
1770+
if (isProfiling && isProfilingSupported && !didBailoutAtRoot) {
17621771
// If profiling is active, store commit time and duration, and the current interactions.
17631772
// The frontend may request this information after profiling has stopped.
17641773
currentCommitProfilingMetadata = {
@@ -1802,7 +1811,7 @@ export function attach(
18021811
mountFiberRecursively(current, null, false, false);
18031812
}
18041813

1805-
if (isProfiling && isProfilingSupported) {
1814+
if (isProfiling && isProfilingSupported && !didBailoutAtRoot) {
18061815
const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get(
18071816
currentRootID,
18081817
);

packages/react-devtools-shared/src/backend/types.js

+3
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ export type DevToolsHook = {
284284
onCommitFiberRoot: (
285285
rendererID: RendererID,
286286
fiber: Object,
287+
// Added in v16.9 to support Profiler priority labels
287288
commitPriority?: number,
289+
// Added in v16.9 to support Fast Refresh
290+
didError?: boolean,
288291
) => void,
289292
};

0 commit comments

Comments
 (0)