Title: [224327] trunk
Revision
224327
Author
[email protected]
Date
2017-11-02 04:31:06 -0700 (Thu, 02 Nov 2017)

Log Message

Remove empty continuations in RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers
https://bugs.webkit.org/show_bug.cgi?id=179014

Reviewed by Geoff Garen.

Source/WebCore:

Treat continuation similarly to other anonymous wrappers. This makes things more understandable
and allows removal of some questionable code in RenderBlock::takeChild.

The patch also makes continuation chain a double linked so we can efficiently remove single
continuations from the chain. It also gets rid of algorithms that recurse in continuation chain.

* accessibility/AccessibilityRenderObject.cpp:
(WebCore::firstChildInContinuation):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::styleDidChange):

    Don't add and remove continuations from the chain when updating style. Prevent recursion by walking
    the chain only in the (non-continuation) head renderer.

(WebCore::RenderBlock::dropAnonymousBoxChild):

    Make a member function.

(WebCore::RenderBlock::takeChild):

    Remove code that destroyed empty continuations and caused the parent to destroy itself.
    Empty continuations are now removed by RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers.

* rendering/RenderBlock.h:
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::ContinuationChainNode::ContinuationChainNode):
(WebCore::RenderBoxModelObject::ContinuationChainNode::~ContinuationChainNode):
(WebCore::RenderBoxModelObject::ContinuationChainNode::insertAfter):

    Track continuations with double linked lists.

(WebCore::continuationChainNodeMap):
(WebCore::RenderBoxModelObject::willBeDestroyed):

    Don't recurse to destroy continuation chain.
    Destroy all continuations iteratively if this is the head of the chain.
    When destroying a continuation renderer simply remove it from the chain.

(WebCore::RenderBoxModelObject::continuation const):
(WebCore::RenderBoxModelObject::insertIntoContinuationChainAfter):
(WebCore::RenderBoxModelObject::removeFromContinuationChain):
(WebCore::RenderBoxModelObject::ensureContinuationChainNode):
(WebCore::continuationMap): Deleted.
(WebCore::RenderBoxModelObject::setContinuation): Deleted.
* rendering/RenderBoxModelObject.h:
* rendering/RenderElement.cpp:
(WebCore::RenderElement::RenderElement):
(WebCore::RenderElement::removeAnonymousWrappersForInlinesIfNecessary):

    Make this a function of the parent renderer itself instead of getting 'parent()' as first operation and
    then using it.
    Don't remove continuations (isAnonymousBlockContinuation() test gives wrong result for the last continuation of the chain).

(WebCore::RenderElement::styleDidChange):

    removeAnonymousWrappersForInlinesIfNecessary is no function of the parent.

(WebCore::RenderElement::updateOutlineAutoAncestor):
* rendering/RenderElement.h:
(WebCore::RenderElement::hasContinuationChainNode const):
(WebCore::RenderElement::setHasContinuationChainNode):
(WebCore::RenderElement::hasContinuation const): Deleted.
(WebCore::RenderElement::setHasContinuation): Deleted.
* rendering/RenderInline.cpp:
(WebCore::RenderInline::styleDidChange):

    Don't add and remove continuations from the chain when updating style. Prevent recursion by walking
    the chain only in the (non-continuation) head renderer.

(WebCore::RenderInline::addChildIgnoringContinuation):

    Remove the old continuation from the chain. splitFlow() will add it back into the right place.

(WebCore::RenderInline::splitInlines):
(WebCore::RenderInline::addChildToContinuation):
(WebCore::RenderInline::childBecameNonInline):

    Remove the old continuation from the chain. splitFlow() will add it back into the right place.

* rendering/RenderInline.h:
* rendering/RenderObject.cpp:
(WebCore::RenderObject::propagateRepaintToParentWithOutlineAutoIfNeeded const):
(WebCore::RenderObject::outputRenderObject const):
(WebCore::findDestroyRootIncludingAnonymous):

    Allow anonymous continuations as destroy roots.

(WebCore::RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers):

    Removing a continuation may leave behind unnecessary anonymous sibling wrappers.
    Call removeAnonymousWrappersForInlinesIfNecessary() on parent after removal to get rid of them.
    If takeChild/removeAnonymousWrappersForInlinesIfNecessary leaves us with empty anonymous parent destroy that too.

* rendering/RenderRubyRun.cpp:
(WebCore::RenderRubyRun::takeChild):

    Similar to RenderBlock::takeChild, remove the code that would make the renderer destroy itself.
    Cleaning up RenderRubyRuns is now handled by removeFromParentAndDestroyCleaningUpAnonymousWrappers.

LayoutTests:

* fast/ruby/float-overhang-from-ruby-text-expected.txt:
* platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (224326 => 224327)


--- trunk/LayoutTests/ChangeLog	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/LayoutTests/ChangeLog	2017-11-02 11:31:06 UTC (rev 224327)
@@ -1,3 +1,13 @@
+2017-11-02  Antti Koivisto  <[email protected]>
+
+        Remove empty continuations in RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers
+        https://bugs.webkit.org/show_bug.cgi?id=179014
+
+        Reviewed by Geoff Garen.
+
+        * fast/ruby/float-overhang-from-ruby-text-expected.txt:
+        * platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt:
+
 2017-11-02  Ms2ger  <[email protected]>
 
         [GTK] Test gardening.

Modified: trunk/LayoutTests/fast/ruby/float-overhang-from-ruby-text-expected.txt (224326 => 224327)


--- trunk/LayoutTests/fast/ruby/float-overhang-from-ruby-text-expected.txt	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/LayoutTests/fast/ruby/float-overhang-from-ruby-text-expected.txt	2017-11-02 11:31:06 UTC (rev 224327)
@@ -17,7 +17,6 @@
       RenderBlock {DIV} at (0,75) size 784x50
         RenderRuby (inline) {RUBY} at (0,0) size 100x50
           RenderRubyRun (anonymous) at (0,0) size 100x50
-            RenderRubyBase (anonymous) at (0,0) size 100x50
-              RenderText {#text} at (0,0) size 100x50
-                text run at (0,0) width 100: "aa"
+            RenderText {#text} at (0,0) size 100x50
+              text run at (0,0) width 100: "aa"
         RenderText {#text} at (0,0) size 0x0

Modified: trunk/LayoutTests/platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt (224326 => 224327)


--- trunk/LayoutTests/platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/LayoutTests/platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt	2017-11-02 11:31:06 UTC (rev 224327)
@@ -24,9 +24,8 @@
               RenderText {#text} at (30,0) size 47x18
                 text run at (30,0) width 47: "HTML"
           RenderRubyRun (anonymous) at (259,10) size 9x18
-            RenderRubyBase (anonymous) at (0,0) size 8x18
-              RenderText {#text} at (0,0) size 8x18
-                text run at (0,0) width 8: "5"
+            RenderText {#text} at (0,0) size 8x18
+              text run at (0,0) width 8: "5"
         RenderText {#text} at (267,10) size 38x18
           text run at (267,10) width 38: " spec."
       RenderBlock {P} at (0,164) size 784x28

Modified: trunk/Source/WebCore/ChangeLog (224326 => 224327)


--- trunk/Source/WebCore/ChangeLog	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/ChangeLog	2017-11-02 11:31:06 UTC (rev 224327)
@@ -1,3 +1,109 @@
+2017-11-02  Antti Koivisto  <[email protected]>
+
+        Remove empty continuations in RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers
+        https://bugs.webkit.org/show_bug.cgi?id=179014
+
+        Reviewed by Geoff Garen.
+
+        Treat continuation similarly to other anonymous wrappers. This makes things more understandable
+        and allows removal of some questionable code in RenderBlock::takeChild.
+
+        The patch also makes continuation chain a double linked so we can efficiently remove single
+        continuations from the chain. It also gets rid of algorithms that recurse in continuation chain.
+
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::firstChildInContinuation):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::styleDidChange):
+
+            Don't add and remove continuations from the chain when updating style. Prevent recursion by walking
+            the chain only in the (non-continuation) head renderer.
+
+        (WebCore::RenderBlock::dropAnonymousBoxChild):
+
+            Make a member function.
+
+        (WebCore::RenderBlock::takeChild):
+
+            Remove code that destroyed empty continuations and caused the parent to destroy itself.
+            Empty continuations are now removed by RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers.
+
+        * rendering/RenderBlock.h:
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::ContinuationChainNode::ContinuationChainNode):
+        (WebCore::RenderBoxModelObject::ContinuationChainNode::~ContinuationChainNode):
+        (WebCore::RenderBoxModelObject::ContinuationChainNode::insertAfter):
+
+            Track continuations with double linked lists.
+
+        (WebCore::continuationChainNodeMap):
+        (WebCore::RenderBoxModelObject::willBeDestroyed):
+
+            Don't recurse to destroy continuation chain. 
+            Destroy all continuations iteratively if this is the head of the chain.
+            When destroying a continuation renderer simply remove it from the chain.
+
+        (WebCore::RenderBoxModelObject::continuation const):
+        (WebCore::RenderBoxModelObject::insertIntoContinuationChainAfter):
+        (WebCore::RenderBoxModelObject::removeFromContinuationChain):
+        (WebCore::RenderBoxModelObject::ensureContinuationChainNode):
+        (WebCore::continuationMap): Deleted.
+        (WebCore::RenderBoxModelObject::setContinuation): Deleted.
+        * rendering/RenderBoxModelObject.h:
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::RenderElement):
+        (WebCore::RenderElement::removeAnonymousWrappersForInlinesIfNecessary):
+
+            Make this a function of the parent renderer itself instead of getting 'parent()' as first operation and
+            then using it.
+            Don't remove continuations (isAnonymousBlockContinuation() test gives wrong result for the last continuation of the chain).
+
+        (WebCore::RenderElement::styleDidChange):
+
+            removeAnonymousWrappersForInlinesIfNecessary is no function of the parent.
+
+        (WebCore::RenderElement::updateOutlineAutoAncestor):
+        * rendering/RenderElement.h:
+        (WebCore::RenderElement::hasContinuationChainNode const):
+        (WebCore::RenderElement::setHasContinuationChainNode):
+        (WebCore::RenderElement::hasContinuation const): Deleted.
+        (WebCore::RenderElement::setHasContinuation): Deleted.
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::styleDidChange):
+
+            Don't add and remove continuations from the chain when updating style. Prevent recursion by walking
+            the chain only in the (non-continuation) head renderer.
+
+        (WebCore::RenderInline::addChildIgnoringContinuation):
+
+            Remove the old continuation from the chain. splitFlow() will add it back into the right place.
+
+        (WebCore::RenderInline::splitInlines):
+        (WebCore::RenderInline::addChildToContinuation):
+        (WebCore::RenderInline::childBecameNonInline):
+
+            Remove the old continuation from the chain. splitFlow() will add it back into the right place.
+
+        * rendering/RenderInline.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::propagateRepaintToParentWithOutlineAutoIfNeeded const):
+        (WebCore::RenderObject::outputRenderObject const):
+        (WebCore::findDestroyRootIncludingAnonymous):
+
+            Allow anonymous continuations as destroy roots.
+
+        (WebCore::RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers):
+
+            Removing a continuation may leave behind unnecessary anonymous sibling wrappers.
+            Call removeAnonymousWrappersForInlinesIfNecessary() on parent after removal to get rid of them.
+            If takeChild/removeAnonymousWrappersForInlinesIfNecessary leaves us with empty anonymous parent destroy that too.
+
+        * rendering/RenderRubyRun.cpp:
+        (WebCore::RenderRubyRun::takeChild):
+
+            Similar to RenderBlock::takeChild, remove the code that would make the renderer destroy itself.
+            Cleaning up RenderRubyRuns is now handled by removeFromParentAndDestroyCleaningUpAnonymousWrappers.
+
 2017-11-02  Ryosuke Niwa  <[email protected]>
 
         REGRESSION(r224053): Crash in WebCore::Node::moveTreeToNewScope

Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (224326 => 224327)


--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -163,7 +163,7 @@
 
 static inline RenderObject* firstChildInContinuation(RenderInline& renderer)
 {
-    auto continuation = renderer.continuation();
+    auto* continuation = renderer.continuation();
 
     while (continuation) {
         if (is<RenderBlock>(*continuation))

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -435,14 +435,10 @@
         adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
 
     auto& newStyle = style();
-    if (!isAnonymousBlock()) {
+    if (!isAnonymousBlock() && !isContinuation()) {
         // Ensure that all of our continuation blocks pick up the new style.
-        for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
-            RenderBoxModelObject* nextCont = currCont->continuation();
-            currCont->setContinuation(0);
+        for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation())
             currCont->setStyle(RenderStyle::clone(newStyle));
-            currCont->setContinuation(nextCont);
-        }
     }
 
     propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
@@ -818,14 +814,14 @@
     return true;
 }
 
-void RenderBlock::dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child)
+void RenderBlock::dropAnonymousBoxChild(RenderBlock& child)
 {
-    parent.setNeedsLayoutAndPrefWidthsRecalc();
-    parent.setChildrenInline(child.childrenInline());
+    setNeedsLayoutAndPrefWidthsRecalc();
+    setChildrenInline(child.childrenInline());
     RenderObject* nextSibling = child.nextSibling();
 
-    auto toBeDeleted = parent.takeChildInternal(child, child.hasLayer() ? NotifyChildren : DontNotifyChildren);
-    child.moveAllChildrenTo(&parent, nextSibling, child.hasLayer());
+    auto toBeDeleted = takeChildInternal(child, child.hasLayer() ? NotifyChildren : DontNotifyChildren);
+    child.moveAllChildrenTo(this, nextSibling, child.hasLayer());
     // Delete the now-empty block's lines and nuke it.
     child.deleteLines();
 }
@@ -893,7 +889,7 @@
     if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canDropAnonymousBlockChild()) {
         // The removal has knocked us down to containing only a single anonymous
         // box. We can pull the content right back up into our box.
-        dropAnonymousBoxChild(*this, downcast<RenderBlock>(*child));
+        dropAnonymousBoxChild(downcast<RenderBlock>(*child));
     } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canDropAnonymousBlockChild()) {
         // It's possible that the removal has knocked us down to a single anonymous
         // block with floating siblings.
@@ -909,7 +905,7 @@
                 }
             }
             if (dropAnonymousBlock)
-                dropAnonymousBoxChild(*this, anonBlock);
+                dropAnonymousBoxChild(anonBlock);
         }
     }
 
@@ -917,31 +913,6 @@
         // If this was our last child be sure to clear out our line boxes.
         if (childrenInline())
             deleteLines();
-
-        // If we are an empty anonymous block in the continuation chain,
-        // we need to remove ourself and fix the continuation chain.
-        if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild.isListMarker()) {
-            auto containingBlockIgnoringAnonymous = containingBlock();
-            while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
-                containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
-            for (RenderObject* current = this; current; current = current->previousInPreOrder(containingBlockIgnoringAnonymous)) {
-                if (!is<RenderBoxModelObject>(current) || downcast<RenderBoxModelObject>(*current).continuation() != this)
-                    continue;
-                // Found our previous continuation. We just need to point it to
-                // |this|'s next continuation.
-                auto* nextContinuation = continuation();
-                if (is<RenderInline>(*current))
-                    downcast<RenderInline>(*current).setContinuation(nextContinuation);
-                else if (is<RenderBlock>(*current))
-                    downcast<RenderBlock>(*current).setContinuation(nextContinuation);
-                else
-                    ASSERT_NOT_REACHED();
-                break;
-            }
-            setContinuation(nullptr);
-            // FIXME: This is dangerous.
-            removeFromParentAndDestroy();
-        }
     }
     return takenChild;
 }

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2017-11-02 11:31:06 UTC (rev 224327)
@@ -192,12 +192,9 @@
     WEBCORE_EXPORT RenderInline* inlineElementContinuation() const;
     RenderBlock* blockElementContinuation() const;
 
-    using RenderBoxModelObject::continuation;
-    using RenderBoxModelObject::setContinuation;
-
     static RenderPtr<RenderBlock> createAnonymousWithParentRendererAndDisplay(const RenderBox& parent, EDisplay = BLOCK);
     RenderPtr<RenderBlock> createAnonymousBlock(EDisplay = BLOCK) const;
-    static void dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child);
+    void dropAnonymousBoxChild(RenderBlock& child);
 
     RenderPtr<RenderBox> createAnonymousBoxWithSameTypeAs(const RenderBox&) const override;
 

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -77,10 +77,55 @@
 // an anonymous block (that houses other blocks) or it will be an inline flow.
 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
 // its continuation but the <b> will just have an inline as its continuation.
-typedef HashMap<const RenderBoxModelObject*, WeakPtr<RenderBoxModelObject>> ContinuationMap;
-static ContinuationMap& continuationMap()
+
+struct RenderBoxModelObject::ContinuationChainNode {
+    WeakPtr<RenderBoxModelObject> renderer;
+    ContinuationChainNode* previous { nullptr };
+    ContinuationChainNode* next { nullptr };
+
+    ContinuationChainNode(RenderBoxModelObject&);
+    ~ContinuationChainNode();
+
+    void insertAfter(ContinuationChainNode&);
+
+    WTF_MAKE_FAST_ALLOCATED;
+};
+
+RenderBoxModelObject::ContinuationChainNode::ContinuationChainNode(RenderBoxModelObject& renderer)
+    : renderer(makeWeakPtr(renderer))
 {
-    static NeverDestroyed<ContinuationMap> map;
+}
+
+RenderBoxModelObject::ContinuationChainNode::~ContinuationChainNode()
+{
+    if (next) {
+        ASSERT(previous);
+        ASSERT(next->previous == this);
+        next->previous = previous;
+    }
+    if (previous) {
+        ASSERT(previous->next == this);
+        previous->next = next;
+    }
+}
+
+void RenderBoxModelObject::ContinuationChainNode::insertAfter(ContinuationChainNode& after)
+{
+    ASSERT(!previous);
+    ASSERT(!next);
+    if ((next = after.next)) {
+        ASSERT(next->previous == &after);
+        next->previous = this;
+    }
+    previous = &after;
+    after.next = this;
+}
+
+using ContinuationChainNodeMap = HashMap<const RenderBoxModelObject*, std::unique_ptr<RenderBoxModelObject::ContinuationChainNode>>;
+
+static ContinuationChainNodeMap& continuationChainNodeMap()
+{
+    static NeverDestroyed<ContinuationChainNodeMap> map;
     return map;
 }
 
@@ -190,10 +235,12 @@
 
 void RenderBoxModelObject::willBeDestroyed()
 {
-    if (hasContinuation()) {
-        continuation()->removeFromParentAndDestroy();
-        setContinuation(nullptr);
+    if (continuation() && !isContinuation()) {
+        removeAndDestroyAllContinuations();
+        ASSERT(!continuation());
     }
+    if (hasContinuationChainNode())
+        removeFromContinuationChain();
 
     if (isFirstLetter())
         clearFirstLetterRemainingText();
@@ -2448,21 +2495,53 @@
 
 RenderBoxModelObject* RenderBoxModelObject::continuation() const
 {
-    if (!hasContinuation())
+    if (!hasContinuationChainNode())
         return nullptr;
-    return continuationMap().get(this).get();
+
+    auto& continuationChainNode = *continuationChainNodeMap().get(this);
+    if (!continuationChainNode.next)
+        return nullptr;
+    return continuationChainNode.next->renderer.get();
 }
 
-void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation)
+void RenderBoxModelObject::insertIntoContinuationChainAfter(RenderBoxModelObject& afterRenderer)
 {
-    ASSERT(!continuation || continuation->isContinuation());
-    if (continuation)
-        continuationMap().set(this, makeWeakPtr(continuation));
-    else if (hasContinuation())
-        continuationMap().remove(this);
-    setHasContinuation(!!continuation);
+    ASSERT(isContinuation());
+    ASSERT(!continuationChainNodeMap().contains(this));
+
+    auto& after = afterRenderer.ensureContinuationChainNode();
+    ensureContinuationChainNode().insertAfter(after);
 }
 
+void RenderBoxModelObject::removeFromContinuationChain()
+{
+    ASSERT(hasContinuationChainNode());
+    ASSERT(continuationChainNodeMap().contains(this));
+    setHasContinuationChainNode(false);
+    continuationChainNodeMap().remove(this);
+}
+
+auto RenderBoxModelObject::ensureContinuationChainNode() -> ContinuationChainNode&
+{
+    setHasContinuationChainNode(true);
+    return *continuationChainNodeMap().ensure(this, [&] {
+        return std::make_unique<ContinuationChainNode>(*this);
+    }).iterator->value;
+}
+
+void RenderBoxModelObject::removeAndDestroyAllContinuations()
+{
+    ASSERT(!isContinuation());
+    ASSERT(hasContinuationChainNode());
+    ASSERT(continuationChainNodeMap().contains(this));
+    auto& continuationChainNode = *continuationChainNodeMap().get(this);
+    while (continuationChainNode.next) {
+        ASSERT(!continuationChainNode.next->renderer->firstChild());
+        continuationChainNode.next->renderer->removeFromParentAndDestroy();
+    }
+    removeFromContinuationChain();
+}
+
 RenderTextFragment* RenderBoxModelObject::firstLetterRemainingText() const
 {
     if (!isFirstLetter())

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.h (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.h	2017-11-02 11:31:06 UTC (rev 224327)
@@ -235,6 +235,9 @@
     void suspendAnimations(double time = 0);
 
     RenderBoxModelObject* continuation() const;
+    
+    void insertIntoContinuationChainAfter(RenderBoxModelObject&);
+    void removeFromContinuationChain();
 
     virtual LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) { return LayoutRect(); };
     
@@ -256,8 +259,6 @@
 
     InterpolationQuality chooseInterpolationQuality(GraphicsContext&, Image&, const void*, const LayoutSize&);
 
-    void setContinuation(RenderBoxModelObject*);
-
     LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
 
     static bool shouldAntialiasLines(GraphicsContext&);
@@ -302,7 +303,12 @@
 
     RenderBlock* containingBlockForAutoHeightDetection(Length logicalHeight) const;
 
+    struct ContinuationChainNode;
+
 private:
+    ContinuationChainNode& ensureContinuationChainNode();
+    void removeAndDestroyAllContinuations();
+
     LayoutUnit computedCSSPadding(const Length&) const;
     
     virtual LayoutRect frameRectForStickyPositioning() const = 0;

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -101,7 +101,7 @@
     , m_renderBoxNeedsLazyRepaint(false)
     , m_hasPausedImageAnimations(false)
     , m_hasCounterNodeMap(false)
-    , m_hasContinuation(false)
+    , m_hasContinuationChainNode(false)
     , m_isContinuation(false)
     , m_isFirstLetter(false)
     , m_hasValidCachedFirstLineStyle(false)
@@ -962,9 +962,12 @@
 
 void RenderElement::removeAnonymousWrappersForInlinesIfNecessary()
 {
-    RenderBlock& parentBlock = downcast<RenderBlock>(*parent());
-    if (!parentBlock.canDropAnonymousBlockChild())
+    // FIXME: Move to RenderBlock.
+    if (!is<RenderBlock>(*this))
         return;
+    RenderBlock& thisBlock = downcast<RenderBlock>(*this);
+    if (!thisBlock.canDropAnonymousBlockChild())
+        return;
 
     // We have changed to floated or out-of-flow positioning so maybe all our parent's
     // children can be inline now. Bail if there are any block children left on the line,
@@ -971,8 +974,8 @@
     // otherwise we can proceed to stripping solitary anonymous wrappers from the inlines.
     // FIXME: We should also handle split inlines here - we exclude them at the moment by returning
     // if we find a continuation.
-    RenderObject* current = parent()->firstChild();
-    while (current && ((current->isAnonymousBlock() && !downcast<RenderBlock>(*current).isAnonymousBlockContinuation()) || current->style().isFloating() || current->style().hasOutOfFlowPosition()))
+    RenderObject* current = firstChild();
+    while (current && ((current->isAnonymousBlock() && !downcast<RenderBlock>(*current).isContinuation()) || current->style().isFloating() || current->style().hasOutOfFlowPosition()))
         current = current->nextSibling();
 
     if (current)
@@ -979,10 +982,10 @@
         return;
 
     RenderObject* next;
-    for (current = parent()->firstChild(); current; current = next) {
+    for (current = firstChild(); current; current = next) {
         next = current->nextSibling();
         if (current->isAnonymousBlock())
-            parentBlock.dropAnonymousBoxChild(parentBlock, downcast<RenderBlock>(*current));
+            thisBlock.dropAnonymousBoxChild(downcast<RenderBlock>(*current));
     }
 }
 
@@ -1011,7 +1014,7 @@
         handleDynamicFloatPositionChange();
 
     if (s_noLongerAffectsParentBlock)
-        removeAnonymousWrappersForInlinesIfNecessary();
+        parent()->removeAnonymousWrappersForInlinesIfNecessary();
 
     SVGRenderSupport::styleChanged(*this, oldStyle);
 
@@ -2153,8 +2156,10 @@
             continue;
         downcast<RenderElement>(child).updateOutlineAutoAncestor(hasOutlineAuto);
     }
-    if (hasContinuation())
-        downcast<RenderBoxModelObject>(*this).continuation()->updateOutlineAutoAncestor(hasOutlineAuto);
+    if (is<RenderBoxModelObject>(*this)) {
+        if (auto* continuation = downcast<RenderBoxModelObject>(*this).continuation())
+            continuation->updateOutlineAutoAncestor(hasOutlineAuto);
+    }
 }
 
 bool RenderElement::hasOutlineAnnotation() const

Modified: trunk/Source/WebCore/rendering/RenderElement.h (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderElement.h	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderElement.h	2017-11-02 11:31:06 UTC (rev 224327)
@@ -221,7 +221,9 @@
     // the child.
     virtual void updateAnonymousChildStyle(const RenderObject&, RenderStyle&) const { };
 
-    bool hasContinuation() const { return m_hasContinuation; }
+    void removeAnonymousWrappersForInlinesIfNecessary();
+
+    bool hasContinuationChainNode() const { return m_hasContinuationChainNode; }
     bool isContinuation() const { return m_isContinuation; }
     void setIsContinuation() { m_isContinuation = true; }
     bool isElementContinuation() const { return isContinuation() && !isAnonymous(); }
@@ -266,7 +268,7 @@
     void setRenderInlineAlwaysCreatesLineBoxes(bool b) { m_renderInlineAlwaysCreatesLineBoxes = b; }
     bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; }
 
-    void setHasContinuation(bool b) { m_hasContinuation = b; }
+    void setHasContinuationChainNode(bool b) { m_hasContinuationChainNode = b; }
 
     void setRenderBlockHasMarginBeforeQuirk(bool b) { m_renderBlockHasMarginBeforeQuirk = b; }
     void setRenderBlockHasMarginAfterQuirk(bool b) { m_renderBlockHasMarginAfterQuirk = b; }
@@ -305,7 +307,6 @@
     // again.  We have to make sure the render tree updates as needed to accommodate the new
     // normal flow object.
     void handleDynamicFloatPositionChange();
-    void removeAnonymousWrappersForInlinesIfNecessary();
 
     bool shouldRepaintForStyleDifference(StyleDifference) const;
     bool hasImmediateNonWhitespaceTextChildOrBorderOrOutline() const;
@@ -338,7 +339,7 @@
     unsigned m_renderBoxNeedsLazyRepaint : 1;
     unsigned m_hasPausedImageAnimations : 1;
     unsigned m_hasCounterNodeMap : 1;
-    unsigned m_hasContinuation : 1;
+    unsigned m_hasContinuationChainNode : 1;
     unsigned m_isContinuation : 1;
     unsigned m_isFirstLetter : 1;
     mutable unsigned m_hasValidCachedFirstLineStyle : 1;

Modified: trunk/Source/WebCore/rendering/RenderInline.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderInline.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderInline.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -189,13 +189,9 @@
     // need to pass its style on to anyone else.
     auto& newStyle = style();
     RenderInline* continuation = inlineElementContinuation();
-    if (continuation) {
-        for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
-            RenderBoxModelObject* nextCont = currCont->continuation();
-            currCont->setContinuation(nullptr);
+    if (continuation && !isContinuation()) {
+        for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation())
             currCont->setStyle(RenderStyle::clone(newStyle));
-            currCont->setContinuation(nextCont);
-        }
         // If an inline's in-flow positioning has changed and it is part of an active continuation as a descendant of an anonymous containing block,
         // then any descendant blocks will need to change their in-flow positioning accordingly.
         // Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
@@ -344,7 +340,9 @@
         newBox->initializeStyle();
         newBox->setIsContinuation();
         RenderBoxModelObject* oldContinuation = continuation();
-        setContinuation(newBox.get());
+        if (oldContinuation)
+            oldContinuation->removeFromContinuationChain();
+        newBox->insertIntoContinuationChainAfter(*this);
 
         splitFlow(beforeChild, WTFMove(newBox), WTFMove(newChild), oldContinuation);
         return;
@@ -417,9 +415,10 @@
         rendererToMove->setNeedsLayoutAndPrefWidthsRecalc();
         rendererToMove = nextSibling;
     }
-    cloneInline->setContinuation(oldCont);
     // Hook |clone| up as the continuation of the middle block.
-    middleBlock->setContinuation(cloneInline.get());
+    cloneInline->insertIntoContinuationChainAfter(*middleBlock);
+    if (oldCont)
+        oldCont->insertIntoContinuationChainAfter(*cloneInline);
 
     // We have been reparented and are now under the fromBlock.  We need
     // to walk up our inline parent chain until we hit the containing block.
@@ -443,19 +442,16 @@
             cloneInline->addChildIgnoringContinuation(WTFMove(cloneChild));
 
             // Hook the clone up as a continuation of |curr|.
-            RenderInline& currentInline = downcast<RenderInline>(*current);
-            oldCont = currentInline.continuation();
-            currentInline.setContinuation(cloneInline.get());
-            cloneInline->setContinuation(oldCont);
+            cloneInline->insertIntoContinuationChainAfter(*current);
 
             // Now we need to take all of the children starting from the first child
             // *after* currentChild and append them all to the clone.
-            for (auto* current = currentChild->nextSibling(); current;) {
-                auto* next = current->nextSibling();
-                auto childToMove = currentInline.takeChildInternal(*current, NotifyChildren);
+            for (auto* sibling = currentChild->nextSibling(); sibling;) {
+                auto* next = sibling->nextSibling();
+                auto childToMove = current->takeChildInternal(*sibling, NotifyChildren);
                 cloneInline->addChildIgnoringContinuation(WTFMove(childToMove));
-                current->setNeedsLayoutAndPrefWidthsRecalc();
-                current = next;
+                sibling->setNeedsLayoutAndPrefWidthsRecalc();
+                sibling = next;
             }
         }
         
@@ -576,7 +572,7 @@
         auto* parent = beforeChild->parent();
         while (parent && parent->parent() && parent->parent()->isAnonymous()) {
             // The ancestor candidate needs to be inside the continuation.
-            if (parent->hasContinuation())
+            if (parent->isContinuation())
                 break;
             parent = parent->parent();
         }
@@ -1379,7 +1375,9 @@
     auto newBox = containingBlock()->createAnonymousBlock();
     newBox->setIsContinuation();
     RenderBoxModelObject* oldContinuation = continuation();
-    setContinuation(newBox.get());
+    if (oldContinuation)
+        oldContinuation->removeFromContinuationChain();
+    newBox->insertIntoContinuationChainAfter(*this);
     RenderObject* beforeChild = child.nextSibling();
     auto removedChild = takeChildInternal(child, NotifyChildren);
     splitFlow(beforeChild, WTFMove(newBox), WTFMove(removedChild), oldContinuation);

Modified: trunk/Source/WebCore/rendering/RenderInline.h (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderInline.h	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderInline.h	2017-11-02 11:31:06 UTC (rev 224327)
@@ -87,9 +87,6 @@
     void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) final;
     void paintOutline(PaintInfo&, const LayoutPoint&);
 
-    using RenderBoxModelObject::continuation;
-    using RenderBoxModelObject::setContinuation;
-
     bool alwaysCreateLineBoxes() const { return renderInlineAlwaysCreatesLineBoxes(); }
     void setAlwaysCreateLineBoxes() { setRenderInlineAlwaysCreatesLineBoxes(true); }
     void updateAlwaysCreateLineBoxes(bool fullLayout);

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -824,7 +824,7 @@
         bool rendererHasOutlineAutoAncestor = renderer->hasOutlineAutoAncestor();
         ASSERT(rendererHasOutlineAutoAncestor
             || renderer->outlineStyleForRepaint().outlineStyleIsAuto()
-            || (is<RenderElement>(*renderer) && downcast<RenderElement>(*renderer).hasContinuation()));
+            || (is<RenderBoxModelObject>(*renderer) && downcast<RenderBoxModelObject>(*renderer).isContinuation()));
         if (renderer == &repaintContainer && rendererHasOutlineAutoAncestor)
             repaintRectNeedsConverting = true;
         if (rendererHasOutlineAutoAncestor)
@@ -1175,7 +1175,7 @@
     }
     if (is<RenderBoxModelObject>(*this)) {
         auto& renderer = downcast<RenderBoxModelObject>(*this);
-        if (renderer.hasContinuation())
+        if (renderer.continuation())
             stream << " continuation->(" << renderer.continuation() << ")";
     }
     outputRegionsInformation(stream);
@@ -1455,24 +1455,26 @@
     parent()->setNeedsBoundariesUpdate();
 }
 
+static bool isAnonymousAndSafeToDelete(RenderElement& element)
+{
+    if (!element.isAnonymous())
+        return false;
+    if (element.isRenderView() || element.isRenderFragmentedFlow())
+        return false;
+    return true;
+}
+
 static RenderObject& findDestroyRootIncludingAnonymous(RenderObject& renderer)
 {
     auto* destroyRoot = &renderer;
     while (true) {
-        auto* destroyRootParent = destroyRoot->parent();
-        if (!destroyRootParent->isAnonymous())
+        auto& destroyRootParent = *destroyRoot->parent();
+        if (!isAnonymousAndSafeToDelete(destroyRootParent))
             break;
-        if (destroyRootParent->isRenderView())
-            break;
-        if (destroyRootParent->isRenderFragmentedFlow())
-            break;
-        // FIXME: Destroy continuations here too.
-        if (destroyRootParent->isContinuation())
-            break;
-        bool destroyingOnlyChild = destroyRootParent->firstChild() == destroyRoot && destroyRootParent->lastChild() == destroyRoot;
+        bool destroyingOnlyChild = destroyRootParent.firstChild() == destroyRoot && destroyRootParent.lastChild() == destroyRoot;
         if (!destroyingOnlyChild)
             break;
-        destroyRoot = destroyRootParent;
+        destroyRoot = &destroyRootParent;
     }
     return *destroyRoot;
 }
@@ -1490,7 +1492,14 @@
     if (is<RenderTableRow>(destroyRoot))
         downcast<RenderTableRow>(destroyRoot).collapseAndDestroyAnonymousSiblingRows();
 
-    destroyRoot.removeFromParentAndDestroy();
+    auto& destroyRootParent = *destroyRoot.parent();
+    destroyRootParent.removeAndDestroyChild(destroyRoot);
+    destroyRootParent.removeAnonymousWrappersForInlinesIfNecessary();
+
+    // Anonymous parent might have become empty, try to delete it too.
+    if (isAnonymousAndSafeToDelete(destroyRootParent) && !destroyRootParent.firstChild())
+        destroyRootParent.removeFromParentAndDestroyCleaningUpAnonymousWrappers();
+
     // WARNING: |this| is deleted here.
 }
 

Modified: trunk/Source/WebCore/rendering/RenderRubyRun.cpp (224326 => 224327)


--- trunk/Source/WebCore/rendering/RenderRubyRun.cpp	2017-11-02 09:53:13 UTC (rev 224326)
+++ trunk/Source/WebCore/rendering/RenderRubyRun.cpp	2017-11-02 11:31:06 UTC (rev 224327)
@@ -181,12 +181,6 @@
             auto takenBase = RenderBlockFlow::takeChild(*base);
             base->deleteLines();
         }
-
-        // If any of the above leaves the run empty, destroy it as well.
-        if (!hasRubyText() && !hasRubyBase()) {
-            auto takenThis = parent()->takeChild(*this);
-            deleteLines();
-        }
     }
 
     return takenChild;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to