Skip to content

Commit

Permalink
Cherry-pick 272448.98@safari-7618-branch (77a82bb). https://bugs.webk…
Browse files Browse the repository at this point in the history
…it.org/show_bug.cgi?id=267141

    Do not repaint newly moved inline box
    https://bugs.webkit.org/show_bug.cgi?id=267141
    rdar://120555470

    Reviewed by Antti Koivisto.

    1. Repaint needs uptodate geometry information to compute the damaged area
    2. Whenever we invalidate the line layout path, we lose all geometry information so a full repaint is being issued on the very first invalidation.
    (note that there may be multiple mutations happening the same time)

    This patch ensures that such repaints are _not_ issued on newly inserted content.
    Since we don't keep track of whether a particular renderer has already issued repaint, moving renders between blocks could
    potentially be repainted twice; initially when they get detached and later when they get inserted at their new position.
    Repaint issued at this later stage most likely results in incorrectly computed damage area as all relevant geometries are
    relative to the former block -and in some cases it may even trigger crashes as we don't find associated layout/display boxes in
    the new block.

    * LayoutTests/fast/dynamic/move-inline-level-element-between-blocks-crash-expected.txt: Added.
    * LayoutTests/fast/dynamic/move-inline-level-element-between-blocks-crash.html: Added.
    * Source/WebCore/layout/integration/LayoutIntegrationBoxTree.cpp:
    (WebCore::LayoutIntegration::BoxTree::contains const):
    * Source/WebCore/layout/integration/LayoutIntegrationBoxTree.h:
    * Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp:
    (WebCore::LayoutIntegration::LineLayout::contains const):
    * Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.h:
    * Source/WebCore/rendering/RenderBlockFlow.cpp:
    (WebCore::RenderBlockFlow::invalidateLineLayoutPath):

    Canonical link: https://commits.webkit.org/272448.98@safari-7618-branch

Canonical link: https://commits.webkit.org/266719.391@webkitglib/2.42
  • Loading branch information
alanbaradlay authored and aperezdc committed Mar 14, 2024
1 parent a7fbf38 commit f06f423
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PASS if no crash or assert
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<style>
span {
outline-style: auto;
position: sticky;
}
img {
position: sticky;
width: 10px;
height: 10px;
}
</style>PASS if no crash or assert<div id=block></div><span><image id=img><script>
if (window.testRunner)
testRunner.dumpAsText();

document.body.offsetHeight;
img.align = "left";
document.body.offsetHeight;
block.style.display = "inline";
</script>
13 changes: 13 additions & 0 deletions Source/WebCore/layout/integration/LayoutIntegrationBoxTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,19 @@ RenderObject& BoxTree::rendererForLayoutBox(const Layout::Box& box)
return *m_boxToRendererMap.get(&box);
}

bool BoxTree::contains(const RenderElement& rendererToFind) const
{
if (!rendererToFind.layoutBox())
return false;
if (m_boxToRendererMap.contains(*rendererToFind.layoutBox()))
return true;
for (auto& renderer : m_renderers) {
if (renderer.get() == &rendererToFind)
return true;
}
return false;
}

const RenderObject& BoxTree::rendererForLayoutBox(const Layout::Box& box) const
{
return const_cast<BoxTree&>(*this).rendererForLayoutBox(box);
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/layout/integration/LayoutIntegrationBoxTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class BoxTree {
const RenderObject& rendererForLayoutBox(const Layout::Box&) const;
RenderObject& rendererForLayoutBox(const Layout::Box&);

bool contains(const RenderElement&) const;

size_t boxCount() const { return m_renderers.size(); }

const auto& renderers() const { return m_renderers; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,11 @@ Vector<FloatRect> LineLayout::collectInlineBoxRects(const RenderInline& renderIn
return result;
}

bool LineLayout::contains(const RenderElement& renderer) const
{
return m_boxTree.contains(renderer);
}

const RenderObject& LineLayout::rendererForLayoutBox(const Layout::Box& layoutBox) const
{
return m_boxTree.rendererForLayoutBox(layoutBox);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class LineLayout : public CanMakeCheckedPtr {
InlineIterator::LineBoxIterator firstLineBox() const;
InlineIterator::LineBoxIterator lastLineBox() const;

bool contains(const RenderElement&) const;
const RenderObject& rendererForLayoutBox(const Layout::Box&) const;
const RenderBlockFlow& flow() const { return downcast<RenderBlockFlow>(m_boxTree.rootRenderer()); }
RenderBlockFlow& flow() { return downcast<RenderBlockFlow>(m_boxTree.rootRenderer()); }
Expand Down
6 changes: 4 additions & 2 deletions Source/WebCore/rendering/RenderBlockFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4030,8 +4030,10 @@ void RenderBlockFlow::invalidateLineLayoutPath()
// Since we eagerly remove the display content here, repaints issued between this invalidation (triggered by style change/content mutation) and the subsequent layout would produce empty rects.
repaint();
for (auto walker = InlineWalker(*this); !walker.atEnd(); walker.advance()) {
auto& renderer = *walker.current();
if (!renderer.isInFlow())
auto& renderer = *walker.current();
if (!renderer.everHadLayout())
continue;
if (!renderer.isInFlow() && modernLineLayout()->contains(downcast<RenderElement>(renderer)))
renderer.repaint();
renderer.setPreferredLogicalWidthsDirty(true);
}
Expand Down

0 comments on commit f06f423

Please sign in to comment.