Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 7af6d5a321879450ab6d21f113e233e957caf14f
https://github.com/WebKit/WebKit/commit/7af6d5a321879450ab6d21f113e233e957caf14f
Author: Vitaly Dyachkov <[email protected]>
Date: 2026-07-16 (Thu, 16 Jul 2026)
Changed paths:
M LayoutTests/inspector/timeline/timeline-layout-events-expected.txt
M LayoutTests/inspector/timeline/timeline-layout-events-iframe-expected.txt
M LayoutTests/inspector/timeline/timeline-layout-events-iframe.html
M LayoutTests/inspector/timeline/timeline-layout-events.html
M Source/JavaScriptCore/inspector/protocol/Timeline.json
M Source/WebCore/inspector/InspectorInstrumentation.cpp
M Source/WebCore/inspector/InspectorInstrumentation.h
M Source/WebCore/inspector/agents/InspectorTimelineAgent.cpp
M Source/WebCore/inspector/agents/InspectorTimelineAgent.h
M Source/WebCore/inspector/agents/page/PageTimelineAgent.cpp
M Source/WebCore/inspector/agents/page/PageTimelineAgent.h
M Source/WebCore/page/LocalFrameViewLayoutContext.cpp
M Source/WebCore/rendering/RenderElement.cpp
M Source/WebCore/rendering/RenderElement.h
M Source/WebCore/rendering/RenderObject.cpp
M Source/WebCore/rendering/RenderObject.h
M Source/WebCore/rendering/RenderObjectInlines.h
M Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
M Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
M Source/WebInspectorUI/UserInterface/Models/LayoutTimelineRecord.js
M Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js
M Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js
Log Message:
-----------
Web Inspector: Emit per-element `Layout Invalidated` events
https://bugs.webkit.org/show_bug.cgi?id=317852
Reviewed by Devin Rousso.
Currently, the `Layout Invalidated` event is emitted only when layout is
scheduled, with the layout root element set as the associated node. This
event does not reflect the number of subnodes that actually require
relayout.
If we have the following node tree:
```
A
/ \
B C
```
Where both `B` and `C` require relayout, the timeline will show:
```
Layout Invalidated: B (layout root)
Layout Invalidated: A (layout root - common ancestor for B and C)
Layout: A (layout root)
```
This is indistinguishable from a case where many more subnodes of `A`
require relayout:
```
A
/ | \ \
B C D...Z
```
The timeline will look the same, but layout will take much longer.
This patch makes the `Layout Invalidated` event fire on every
`setNeedsLayout*` call of each `RenderElement`, using its element as the
associated node. The original `Layout Invalidated` event is renamed to
`Layout Scheduled` to better reflect the actual logic.
To avoid event flooding, `Layout Invalidated` is only emitted the first
time an element is marked as needing layout within a given layout cycle.
Subsequent `setNeedsLayout*` calls on the same element before layout
runs are silently skipped.
With this patch, the timeline will look like this:
```
Layout Invalidated: B
Layout Scheduled: B (layout root)
Layout Invalidated: C
Layout Scheduled: A (layout root - common ancestor for B and C)
Layout Invalidated: D
Layout Invalidated: ...
Layout Invalidated: Z
Layout: A (layout root)
```
While more verbose, this provides much more detailed insight into the
engine internals, making it easier for web developers to debug layout
issues.
* LayoutTests/inspector/timeline/timeline-layout-events-expected.txt:
* LayoutTests/inspector/timeline/timeline-layout-events-iframe-expected.txt:
* LayoutTests/inspector/timeline/timeline-layout-events-iframe.html:
* LayoutTests/inspector/timeline/timeline-layout-events.html:
* Source/JavaScriptCore/inspector/protocol/Timeline.json:
* Source/WebCore/inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::willInvalidateLayoutImpl):
(WebCore::InspectorInstrumentation::didScheduleLayoutImpl):
(WebCore::InspectorInstrumentation::didInvalidateLayoutImpl):
* Source/WebCore/inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::willInvalidateLayout):
(WebCore::InspectorInstrumentation::didScheduleLayout):
(WebCore::InspectorInstrumentation::didInvalidateLayout):
* Source/WebCore/inspector/agents/InspectorTimelineAgent.cpp:
(WebCore::toProtocol):
* Source/WebCore/inspector/agents/InspectorTimelineAgent.h:
* Source/WebCore/inspector/agents/page/PageTimelineAgent.cpp:
(WebCore::PageTimelineAgent::willInvalidateLayout):
(WebCore::PageTimelineAgent::didScheduleLayout):
(WebCore::PageTimelineAgent::didInvalidateLayout):
* Source/WebCore/inspector/agents/page/PageTimelineAgent.h:
* Source/WebCore/page/LocalFrameViewLayoutContext.cpp:
(WebCore::LocalFrameViewLayoutContext::scheduleLayout):
(WebCore::LocalFrameViewLayoutContext::scheduleSubtreeLayout):
* Source/WebCore/rendering/RenderElement.cpp:
(WebCore::RenderElement::setNeedsOutOfFlowMovementLayout):
(WebCore::RenderElement::setNeedsLayoutForOverflowChange):
(WebCore::RenderElement::setOutOfFlowChildNeedsStaticPositionLayout):
* Source/WebCore/rendering/RenderElement.h:
* Source/WebCore/rendering/RenderObject.cpp:
(WebCore::RenderObject::notifyInspectorOfLayoutInvalidate):
* Source/WebCore/rendering/RenderObject.h:
* Source/WebCore/rendering/RenderObjectInlines.h:
(WebCore::RenderObject::setNeedsLayout):
* Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js:
* Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js:
(WI.TimelineManager.prototype._processRecord):
* Source/WebInspectorUI/UserInterface/Models/LayoutTimelineRecord.js:
(WI.LayoutTimelineRecord.displayNameForEventType):
* Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js:
(WI.CPUTimelineView.prototype._attemptSelectIndicatatorTimelineRecord):
* Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js:
(WI.TimelineTabContentView.iconClassNameForRecord):
Canonical link: https://commits.webkit.org/317302@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications