Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 9cc37e9a285bf627be80c888364fbd3e2683c16b
      
https://github.com/WebKit/WebKit/commit/9cc37e9a285bf627be80c888364fbd3e2683c16b
  Author: Sammy Gill <[email protected]>
  Date:   2026-04-22 (Wed, 22 Apr 2026)

  Changed paths:
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-overflow/max-width-container-with-scrollable-descendant-expected.html
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-overflow/max-width-container-with-scrollable-descendant-ref.html
    A 
LayoutTests/imported/w3c/web-platform-tests/css/css-overflow/max-width-container-with-scrollable-descendant.html
    M Source/WebCore/Headers.cmake
    M Source/WebCore/Sources.txt
    M Source/WebCore/WebCore.xcodeproj/project.pbxproj
    M Source/WebCore/page/LocalFrameViewLayoutContext.cpp
    M Source/WebCore/page/LocalFrameViewLayoutContext.h
    M Source/WebCore/rendering/RelayoutScopeForScrollbarChange.cpp
    M Source/WebCore/rendering/RenderBlock.cpp
    M Source/WebCore/rendering/RenderObject.cpp
    M Source/WebCore/rendering/RenderObject.h
    A Source/WebCore/rendering/SubtreeScrollbarChangesState.cpp
    A Source/WebCore/rendering/SubtreeScrollbarChangesState.h

  Log Message:
  -----------
  Begin tracking scrollbar changes in subtree for intrinsically sized renderers.
https://bugs.webkit.org/show_bug.cgi?id=310940
rdar://166836126

Reviewed by Alan Baradlay.

According to css-overflow, when a box has some type of scrollbar change,
it is supposed to impact its intrinsic size.

"When reserving space for a scrollbar placed at the edge of an element’s box,
the reserved space is inserted between the inner border edge and the
outer padding edge... When the box is intrinsically sized, this reserved space
is added to the size of its contents."
https://drafts.csswg.org/css-overflow-3/#scrollbar-sizing

For example, consider the following testcase:
<div style="width: max-content; background-color: green;">
  <div style="height: 79px; overflow: auto;">
    <div style="width: 10px; height: 80px;"></div>
  </div>
</div>

When the child of the max-content div ends up getting a scrollbar due to
its overflowing content, the logical width of the max-content div should
be updated to reflact that. However, we currently fail to detect this
change and the size of the width: max-content div ends up remaining the
same.

This patch serves as a first step towards fixing this class of bugs by
adding some infrastructure that keeps track of scrollbar changes for a
subtree where the root is intrinsically sized according to its computed
logical width.

The basic idea is that when we run into such a renderer we want to start
keeping track of any descendants that gain or lose a scrollbar. If that
happens we will want to recompute our logical width in response.

Tests: 
imported/w3c/web-platform-tests/css/css-overflow/max-width-container-with-scrollable-descendant-ref.html
       
imported/w3c/web-platform-tests/css/css-overflow/max-width-container-with-scrollable-descendant.html

* Source/WebCore/rendering/SubtreeScrollbarChangesState.cpp: Added.
SubtreeScrollbarChangesState is a new bit of state that indicates a renderer is
interested in knowing about any time a descendant has a scrollbar
change. This state is created with the renderer that wants to know about
these changes and is passed down the subtree during layout. By the time
we are back at the subtree root we should have a list of any descendants
that gained or lost a scrollbar.

SubtreeScrollbarChangesHandler is a new stack-based helper class that
can be used to indicate that the passed-in renderer will be able to
handle and contain any changes that come from a descendant
gaining/losing a scrollbar. The renderer that is the subtree root is
certainly a renderer that will need to handle the changes, but it is
possible for a descendant of that root to be able to contain the
changes. For example, if the descendant has a fixed width, then the
scrollbar changes below it will not have an impact above.

(WebCore::SubtreeScrollbarChangesHandler::SubtreeScrollbarChangesHandler):
If the handler is not the subtree root and is some other descendant that
can contain the scrollbar changes, then we need to make sure to properly
save the list of renderers that is already in the SubtreeScrollbarChangesState
and make sure the list in LocalFrameViewLayoutContext is empty. This is because
we want to only handle the descendants of the handler and not, for
example, those of the siblings of the handler.

(WebCore::SubtreeScrollbarChangesHandler::~SubtreeScrollbarChangesHandler):
1.) Make sure that we restore the list of descendants that were saved in
the constructor by adding a ScopeExit that does so. It will also debug assert
that the list of descendants which was populated for the handler is
empty.

2.) Make sure that the list of descendants is handled properly.

If we are the subtree root, then we need to invalidate the preferred widths of
descendants and the containing block chain up to the subtree root so
that when we perform layout again on the subtree root we can properly
update the logical width.

If we are not the subtree root then we will need to just call
layoutBlock on the renderers which is what would have happened in
the RelayoutScopeForScrollbarChange destructor. A ListHashSet is
used here to make sure that we call layoutBlock in the same order we
would have traversed the tree.

* Source/WebCore/rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layout):
We need to initialize the state and handle it some time before and after
we perform layout. Doing it here will allow us to do so before the various
renderers perform layout via layoutBlock. We will need to create the
SubtreeScrollbarChangesHandler if either this renderer is the one that
has the intrinsic logical width or the renderer is some descendant that can
properly contain the changes as we are walking back up the tree.

* Source/WebCore/rendering/RelayoutScopeForScrollbarChange.cpp:
(WebCore::RelayoutScopeForScrollbarChange::~RelayoutScopeForScrollbarChange):
If we are currently tracking a subtree for scrollbar changes then we
will add them into the list to be propagated back up. In that case we
also do not want to call layoutBlock here since it should be handled by
an ancestor.

Canonical link: https://commits.webkit.org/311766@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to