[DevTools] Fix Profiler inaccuracy caused by stale PerformedWork flag on unvisited fibers #35645
+89
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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