[DevTools] Fix Profiler inaccuracy caused by stale PerformedWork flag on unvisited fibers#436
[DevTools] Fix Profiler inaccuracy caused by stale PerformedWork flag on unvisited fibers#436everettbu wants to merge 1 commit into
Conversation
Greptile OverviewGreptile SummaryThis PR fixes a DevTools Profiler bug where components were incorrectly reported as "rendered" when they were actually skipped due to JSX element caching (e.g., from React Compiler). The Issue: The Fix: Key Changes:
This follows the same pattern used elsewhere in the codebase for detecting unvisited fibers (ref: renderer.js:4942) and is distinct from the "bailout" case where fibers are visited but skip via Confidence Score: 5/5
Important Files Changed
|
|
Upstream PR was closed or merged. Code is synced via branch mirror. |
Mirror of facebook/react#35645
Original author: yongsk0066
Summary
Fixes an issue where DevTools Profiler reports components as "rendered" and "Highlight updates" flashes on components that were actually skipped.
This can cause confusion for developers using React Compiler, as cached components appear to be re-rendering in DevTools—making it seem like optimizations aren't working when they actually are.
When React Compiler caches JSX elements, the parent may bail out entirely (
childLanes === 0), and child fibers are never visited by the reconciler. However,didFiberRenderwas checking thePerformedWorkflag which could be stale from a previous render, causing false positives in the Profiler.Here's an example to reproduce the issue (also available in my demo repo). Note that
ChildComponentis wrapped with a<div>.Compiled output (some parts omitted, full output available in playground or demo repo):
I referenced a similar comparison pattern from renderer.js#L4936-L4940 (introduced in #30684), which uses fiber identity to check if a child was not visited. This fix adds the same check before checking the
PerformedWorkflag—if the fiber is the same object, it was never visited this render, so any flag is stale.Note: This is different from the "We don't reflect bailouts" case—that's for components that were visited but bailed out via
shouldComponentUpdateorReact.memo, while this fix handles fibers that were never visited because the parent bailed out entirely withchildLanes === 0.How did you test this change?
Added a test case using
useMemoCacheto simulate React Compiler's JSX caching behavior. The test verifies that cached children are not reported infiberActualDurations.I created a reproduction demo at https://github.com/yongsk0066/devtools-rendered-demo (live demo). Tested with React Developer Tools 7.0.1 (10/20/2025). To reproduce the issue, enable "Highlight updates when components render" and check if highlights appear on cached children, or check in Profiler if cached components are shown without hatching.
I also built the DevTools extension locally with the fix
Before fix:
profiling json
wrapped.mp4
After fix:
profiling json
fixed_wrapped.mp4
cc
@hoxyq