Title: [226516] trunk/Source/WebCore
Revision
226516
Author
[email protected]
Date
2018-01-08 09:40:21 -0800 (Mon, 08 Jan 2018)

Log Message

[RenderTreeBuilder] Move RenderBlock addChild logic to RenderTreeBuilder
https://bugs.webkit.org/show_bug.cgi?id=181319
<rdar://problem/36313464>

Reviewed by Antti Koivisto.

This is about moving the code, no cleanup and/or normalization (unfortunately it also means
some temporary changes).

No change in functionality.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::addChild):
(WebCore::RenderBlock::addChildIgnoringContinuation):
(WebCore::RenderBlock::childBecameNonInline):
(WebCore::RenderBlock::continuationBefore): Deleted.
(WebCore::RenderBlock::addChildToContinuation): Deleted.
(WebCore::getInlineRun): Deleted.
(WebCore::RenderBlock::makeChildrenNonInline): Deleted.
* rendering/RenderBlock.h:
* rendering/RenderBox.cpp:
(WebCore::markBoxForRelayoutAfterSplit): Deleted.
(WebCore::RenderBox::splitAnonymousBoxesAroundChild): Deleted.
* rendering/RenderBox.h:
* rendering/RenderRubyBase.cpp:
(WebCore::RenderRubyBase::moveChildren):
(WebCore::RenderRubyBase::moveBlockChildren):
* rendering/RenderTable.cpp:
(WebCore::RenderTable::addChild):
* rendering/RenderTableRow.cpp:
(WebCore::RenderTableRow::addChild):
* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::addChild):
* rendering/updating/RenderTreeBuilder.cpp:
(WebCore::markBoxForRelayoutAfterSplit):
(WebCore::getInlineRun):
(WebCore::RenderTreeBuilder::RenderTreeBuilder):
(WebCore::RenderTreeBuilder::insertChildToRenderBlock):
(WebCore::RenderTreeBuilder::insertChildToRenderBlockIgnoringContinuation):
(WebCore::RenderTreeBuilder::makeChildrenNonInline):
(WebCore::RenderTreeBuilder::splitAnonymousBoxesAroundChild):
* rendering/updating/RenderTreeBuilder.h:
(WebCore::RenderTreeBuilder::blockBuilder):
* rendering/updating/RenderTreeBuilderBlock.cpp: Added.
(WebCore::continuationBefore):
(WebCore::RenderTreeBuilder::Block::Block):
(WebCore::RenderTreeBuilder::Block::insertChild):
(WebCore::RenderTreeBuilder::Block::insertChildToContinuation):
(WebCore::RenderTreeBuilder::Block::insertChildIgnoringContinuation):
* rendering/updating/RenderTreeBuilderBlock.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (226515 => 226516)


--- trunk/Source/WebCore/ChangeLog	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/ChangeLog	2018-01-08 17:40:21 UTC (rev 226516)
@@ -1,3 +1,58 @@
+2018-01-08  Zalan Bujtas  <[email protected]>
+
+        [RenderTreeBuilder] Move RenderBlock addChild logic to RenderTreeBuilder
+        https://bugs.webkit.org/show_bug.cgi?id=181319
+        <rdar://problem/36313464>
+
+        Reviewed by Antti Koivisto.
+
+        This is about moving the code, no cleanup and/or normalization (unfortunately it also means
+        some temporary changes).  
+
+        No change in functionality.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::addChild):
+        (WebCore::RenderBlock::addChildIgnoringContinuation):
+        (WebCore::RenderBlock::childBecameNonInline):
+        (WebCore::RenderBlock::continuationBefore): Deleted.
+        (WebCore::RenderBlock::addChildToContinuation): Deleted.
+        (WebCore::getInlineRun): Deleted.
+        (WebCore::RenderBlock::makeChildrenNonInline): Deleted.
+        * rendering/RenderBlock.h:
+        * rendering/RenderBox.cpp:
+        (WebCore::markBoxForRelayoutAfterSplit): Deleted.
+        (WebCore::RenderBox::splitAnonymousBoxesAroundChild): Deleted.
+        * rendering/RenderBox.h:
+        * rendering/RenderRubyBase.cpp:
+        (WebCore::RenderRubyBase::moveChildren):
+        (WebCore::RenderRubyBase::moveBlockChildren):
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::addChild):
+        * rendering/RenderTableRow.cpp:
+        (WebCore::RenderTableRow::addChild):
+        * rendering/RenderTableSection.cpp:
+        (WebCore::RenderTableSection::addChild):
+        * rendering/updating/RenderTreeBuilder.cpp:
+        (WebCore::markBoxForRelayoutAfterSplit):
+        (WebCore::getInlineRun):
+        (WebCore::RenderTreeBuilder::RenderTreeBuilder):
+        (WebCore::RenderTreeBuilder::insertChildToRenderBlock):
+        (WebCore::RenderTreeBuilder::insertChildToRenderBlockIgnoringContinuation):
+        (WebCore::RenderTreeBuilder::makeChildrenNonInline):
+        (WebCore::RenderTreeBuilder::splitAnonymousBoxesAroundChild):
+        * rendering/updating/RenderTreeBuilder.h:
+        (WebCore::RenderTreeBuilder::blockBuilder):
+        * rendering/updating/RenderTreeBuilderBlock.cpp: Added.
+        (WebCore::continuationBefore):
+        (WebCore::RenderTreeBuilder::Block::Block):
+        (WebCore::RenderTreeBuilder::Block::insertChild):
+        (WebCore::RenderTreeBuilder::Block::insertChildToContinuation):
+        (WebCore::RenderTreeBuilder::Block::insertChildIgnoringContinuation):
+        * rendering/updating/RenderTreeBuilderBlock.h: Added.
+        
 2018-01-08  Jeremy Jones  <[email protected]>
 
         Standard controls sometimes say video is in pip when it isnt.

Modified: trunk/Source/WebCore/Sources.txt (226515 => 226516)


--- trunk/Source/WebCore/Sources.txt	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/Sources.txt	2018-01-08 17:40:21 UTC (rev 226516)
@@ -1984,6 +1984,7 @@
 rendering/svg/SVGTextQuery.cpp
 
 rendering/updating/RenderTreeBuilder.cpp
+rendering/updating/RenderTreeBuilderBlock.cpp
 rendering/updating/RenderTreeBuilderFirstLetter.cpp
 rendering/updating/RenderTreeBuilderFormControls.cpp
 rendering/updating/RenderTreeBuilderList.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226515 => 226516)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-08 17:40:21 UTC (rev 226516)
@@ -393,6 +393,7 @@
 		119340791FE8B92300935F1E /* RenderTreeBuilderTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */; };
 		1193408A1FEB355D00935F1E /* RenderTreeBuilderRuby.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340881FEB355D00935F1E /* RenderTreeBuilderRuby.h */; };
 		119340971FED715500935F1E /* RenderTreeBuilderFormControls.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340951FED715500935F1E /* RenderTreeBuilderFormControls.h */; };
+		119340A31FEE024000935F1E /* RenderTreeBuilderBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 119340A11FEE024000935F1E /* RenderTreeBuilderBlock.h */; };
 		11E067EE1E6246E500162D16 /* SimpleLineLayoutCoverage.h in Headers */ = {isa = PBXBuildFile; fileRef = 11E067ED1E6246E500162D16 /* SimpleLineLayoutCoverage.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1400D7A817136EA70077CE05 /* ScriptWrappableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400D7A717136EA70077CE05 /* ScriptWrappableInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1403B99709EB13AF00797C7F /* DOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 1403B99509EB13AF00797C7F /* DOMWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -5588,6 +5589,8 @@
 		119340881FEB355D00935F1E /* RenderTreeBuilderRuby.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderRuby.h; sourceTree = "<group>"; };
 		119340941FED715500935F1E /* RenderTreeBuilderFormControls.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderFormControls.cpp; sourceTree = "<group>"; };
 		119340951FED715500935F1E /* RenderTreeBuilderFormControls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderFormControls.h; sourceTree = "<group>"; };
+		119340A01FEE024000935F1E /* RenderTreeBuilderBlock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderBlock.cpp; sourceTree = "<group>"; };
+		119340A11FEE024000935F1E /* RenderTreeBuilderBlock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderBlock.h; sourceTree = "<group>"; };
 		11E067EB1E62461300162D16 /* SimpleLineLayoutCoverage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleLineLayoutCoverage.cpp; sourceTree = "<group>"; };
 		11E067ED1E6246E500162D16 /* SimpleLineLayoutCoverage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLineLayoutCoverage.h; sourceTree = "<group>"; };
 		1400D7A717136EA70077CE05 /* ScriptWrappableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptWrappableInlines.h; sourceTree = "<group>"; };
@@ -24626,6 +24629,8 @@
 			children = (
 				E47C39201FE6E0D900BBBC6B /* RenderTreeBuilder.cpp */,
 				E47C392A1FE6E0DE00BBBC6B /* RenderTreeBuilder.h */,
+				119340A01FEE024000935F1E /* RenderTreeBuilderBlock.cpp */,
+				119340A11FEE024000935F1E /* RenderTreeBuilderBlock.h */,
 				E47C39211FE6E0DA00BBBC6B /* RenderTreeBuilderFirstLetter.cpp */,
 				E47C39261FE6E0DC00BBBC6B /* RenderTreeBuilderFirstLetter.h */,
 				119340941FED715500935F1E /* RenderTreeBuilderFormControls.cpp */,
@@ -29053,6 +29058,7 @@
 				BCEA4887097D93020094C9E4 /* RenderThemeMac.h in Headers */,
 				93F1998C08245E59001E9ABC /* RenderTreeAsText.h in Headers */,
 				E47C392D1FE6E0F300BBBC6B /* RenderTreeBuilder.h in Headers */,
+				119340A31FEE024000935F1E /* RenderTreeBuilderBlock.h in Headers */,
 				E47C39301FE6E0FD00BBBC6B /* RenderTreeBuilderFirstLetter.h in Headers */,
 				119340971FED715500935F1E /* RenderTreeBuilderFormControls.h in Headers */,
 				E47C39321FE6E10500BBBC6B /* RenderTreeBuilderList.h in Headers */,

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -446,71 +446,6 @@
     setShouldForceRelayoutChildren(oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(*oldStyle, style()));
 }
 
-RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
-{
-    if (beforeChild && beforeChild->parent() == this)
-        return this;
-
-    RenderBlock* nextToLast = this;
-    RenderBlock* last = this;
-    for (auto* current = downcast<RenderBlock>(continuation()); current; current = downcast<RenderBlock>(current->continuation())) {
-        if (beforeChild && beforeChild->parent() == current) {
-            if (current->firstChild() == beforeChild)
-                return last;
-            return current;
-        }
-
-        nextToLast = last;
-        last = current;
-    }
-
-    if (!beforeChild && !last->firstChild())
-        return nextToLast;
-    return last;
-}
-
-void RenderBlock::addChildToContinuation(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
-{
-    RenderBlock* flow = continuationBefore(beforeChild);
-    ASSERT(!beforeChild || is<RenderBlock>(*beforeChild->parent()));
-    RenderBoxModelObject* beforeChildParent = nullptr;
-    if (beforeChild)
-        beforeChildParent = downcast<RenderBoxModelObject>(beforeChild->parent());
-    else {
-        RenderBoxModelObject* continuation = flow->continuation();
-        if (continuation)
-            beforeChildParent = continuation;
-        else
-            beforeChildParent = flow;
-    }
-
-    if (newChild->isFloatingOrOutOfFlowPositioned()) {
-        beforeChildParent->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-        return;
-    }
-
-    bool childIsNormal = newChild->isInline() || !newChild->style().columnSpan();
-    bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style().columnSpan();
-    bool flowIsNormal = flow->isInline() || !flow->style().columnSpan();
-
-    if (flow == beforeChildParent) {
-        flow->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-        return;
-    }
-    
-    // The goal here is to match up if we can, so that we can coalesce and create the
-    // minimal # of continuations needed for the inline.
-    if (childIsNormal == bcpIsNormal) {
-        beforeChildParent->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-        return;
-    }
-    if (flowIsNormal == childIsNormal) {
-        flow->addChildIgnoringContinuation(builder, WTFMove(newChild), 0); // Just treat like an append.
-        return;
-    }
-    beforeChildParent->addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
-}
-
 RenderPtr<RenderBlock> RenderBlock::clone() const
 {
     RenderPtr<RenderBlock> cloneBlock;
@@ -533,140 +468,14 @@
 
 void RenderBlock::addChild(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
 {
-    if (continuation() && !isAnonymousBlock())
-        addChildToContinuation(builder, WTFMove(newChild), beforeChild);
-    else
-        addChildIgnoringContinuation(builder, WTFMove(newChild), beforeChild);
+    builder.insertChildToRenderBlock(*this, WTFMove(newChild), beforeChild);
 }
 
 void RenderBlock::addChildIgnoringContinuation(RenderTreeBuilder& builder, RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
 {
-    if (beforeChild && beforeChild->parent() != this) {
-        RenderElement* beforeChildContainer = beforeChild->parent();
-        while (beforeChildContainer->parent() != this)
-            beforeChildContainer = beforeChildContainer->parent();
-        ASSERT(beforeChildContainer);
-
-        if (beforeChildContainer->isAnonymous()) {
-            RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!beforeChildContainer->isInline());
-
-            // If the requested beforeChild is not one of our children, then this is because
-            // there is an anonymous container within this object that contains the beforeChild.
-            RenderElement* beforeChildAnonymousContainer = beforeChildContainer;
-            if (beforeChildAnonymousContainer->isAnonymousBlock()
-#if ENABLE(FULLSCREEN_API)
-                // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
-                || beforeChildAnonymousContainer->isRenderFullScreen()
-                || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
-#endif
-                ) {
-                // Insert the child into the anonymous block box instead of here.
-                if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
-                    builder.insertChild(*beforeChild->parent(), WTFMove(newChild), beforeChild);
-                else
-                    builder.insertChild(*this, WTFMove(newChild), beforeChild->parent());
-                return;
-            }
-
-            ASSERT(beforeChildAnonymousContainer->isTable());
-
-            if (newChild->isTablePart()) {
-                // Insert into the anonymous table.
-                builder.insertChild(*beforeChildAnonymousContainer, WTFMove(newChild), beforeChild);
-                return;
-            }
-
-            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
-
-            RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(beforeChild->parent() == this);
-        }
-    }
-
-    bool madeBoxesNonInline = false;
-
-    // A block has to either have all of its children inline, or all of its children as blocks.
-    // So, if our children are currently inline and a block child has to be inserted, we move all our
-    // inline children into anonymous block boxes.
-    if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
-        // This is a block with inline content. Wrap the inline content in anonymous blocks.
-        makeChildrenNonInline(beforeChild);
-        madeBoxesNonInline = true;
-
-        if (beforeChild && beforeChild->parent() != this) {
-            beforeChild = beforeChild->parent();
-            ASSERT(beforeChild->isAnonymousBlock());
-            ASSERT(beforeChild->parent() == this);
-        }
-    } else if (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || newChild->isInline())) {
-        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
-        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
-        // a new one is created and inserted into our list of children in the appropriate position.
-        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
-
-        if (afterChild && afterChild->isAnonymousBlock()) {
-            builder.insertChild(downcast<RenderBlock>(*afterChild), WTFMove(newChild));
-            return;
-        }
-
-        if (newChild->isInline()) {
-            // No suitable existing anonymous box - create a new one.
-            auto newBox = createAnonymousBlock();
-            auto& box = *newBox;
-            RenderBox::addChild(builder, WTFMove(newBox), beforeChild);
-            builder.insertChild(box, WTFMove(newChild));
-            return;
-        }
-    }
-
-    invalidateLineLayoutPath();
-
-    RenderBox::addChild(builder, WTFMove(newChild), beforeChild);
- 
-    if (madeBoxesNonInline && is<RenderBlock>(parent()) && isAnonymousBlock())
-        downcast<RenderBlock>(*parent()).removeLeftoverAnonymousBlock(this);
-    // this object may be dead here
+    builder.insertChildToRenderBlockIgnoringContinuation(*this, WTFMove(newChild), beforeChild);
 }
 
-static void getInlineRun(RenderObject* start, RenderObject* boundary,
-                         RenderObject*& inlineRunStart,
-                         RenderObject*& inlineRunEnd)
-{
-    // Beginning at |start| we find the largest contiguous run of inlines that
-    // we can.  We denote the run with start and end points, |inlineRunStart|
-    // and |inlineRunEnd|.  Note that these two values may be the same if
-    // we encounter only one inline.
-    //
-    // We skip any non-inlines we encounter as long as we haven't found any
-    // inlines yet.
-    //
-    // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
-    // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
-    // a non-inline.
-    
-    // Start by skipping as many non-inlines as we can.
-    RenderObject * curr = start;
-    bool sawInline;
-    do {
-        while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
-            curr = curr->nextSibling();
-        
-        inlineRunStart = inlineRunEnd = curr;
-        
-        if (!curr)
-            return; // No more inline children to be found.
-        
-        sawInline = curr->isInline();
-        
-        curr = curr->nextSibling();
-        while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
-            inlineRunEnd = curr;
-            if (curr->isInline())
-                sawInline = true;
-            curr = curr->nextSibling();
-        }
-    } while (!sawInline);
-}
-
 void RenderBlock::deleteLines()
 {
     if (AXObjectCache* cache = document().existingAXObjectCache())
@@ -673,50 +482,6 @@
         cache->deferRecomputeIsIgnored(element());
 }
 
-void RenderBlock::makeChildrenNonInline(RenderObject* insertionPoint)
-{    
-    // makeChildrenNonInline takes a block whose children are *all* inline and it
-    // makes sure that inline children are coalesced under anonymous
-    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
-    // the new block child that is causing us to have to wrap all the inlines.  This
-    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
-    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
-    // splitting them.
-    ASSERT(isInlineBlockOrInlineTable() || !isInline());
-    ASSERT(!insertionPoint || insertionPoint->parent() == this);
-
-    setChildrenInline(false);
-
-    RenderObject* child = firstChild();
-    if (!child)
-        return;
-
-    deleteLines();
-
-    while (child) {
-        RenderObject* inlineRunStart;
-        RenderObject* inlineRunEnd;
-        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
-
-        if (!inlineRunStart)
-            break;
-
-        child = inlineRunEnd->nextSibling();
-
-        auto newBlock = createAnonymousBlock();
-        auto& block = *newBlock;
-        insertChildInternal(WTFMove(newBlock), inlineRunStart);
-        moveChildrenTo(&block, inlineRunStart, child, RenderBoxModelObject::NormalizeAfterInsertion::No);
-    }
-
-#ifndef NDEBUG
-    for (RenderObject* c = firstChild(); c; c = c->nextSibling())
-        ASSERT(!c->isInline());
-#endif
-
-    repaint();
-}
-
 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
 {
     ASSERT(child->isAnonymousBlock());
@@ -3212,7 +2977,7 @@
 
 void RenderBlock::childBecameNonInline(RenderElement&)
 {
-    makeChildrenNonInline();
+    RenderTreeBuilder::current()->makeChildrenNonInline(*this);
     if (isAnonymousBlock() && is<RenderBlock>(parent()))
         downcast<RenderBlock>(*parent()).removeLeftoverAnonymousBlock(this);
     // |this| may be dead here

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2018-01-08 17:40:21 UTC (rev 226516)
@@ -395,7 +395,10 @@
     
     void adjustBorderBoxRectForPainting(LayoutRect&) override;
     LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) override;
-    
+    void addChildIgnoringContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild) override;
+    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+    bool isInlineBlockOrInlineTable() const final { return isInline() && isReplaced(); }
+
 protected:
     virtual void addOverflowFromChildren();
     // FIXME-BLOCKFLOW: Remove virtualization when all callers have moved to RenderBlockFlow
@@ -432,17 +435,9 @@
 
     const char* renderName() const override;
 
-    bool isInlineBlockOrInlineTable() const final { return isInline() && isReplaced(); }
-
-    void makeChildrenNonInline(RenderObject* insertionPoint = nullptr);
-    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-
     // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
     virtual void moveAllChildrenIncludingFloatsTo(RenderBlock& toBlock, RenderBoxModelObject::NormalizeAfterInsertion normalizeAfterInsertion) { moveAllChildrenTo(&toBlock, normalizeAfterInsertion); }
 
-    void addChildToContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild);
-    void addChildIgnoringContinuation(RenderTreeBuilder&, RenderPtr<RenderObject> newChild, RenderObject* beforeChild) override;
-
     bool isSelfCollapsingBlock() const override;
     virtual bool childrenPreventSelfCollapsing() const;
     
@@ -502,7 +497,6 @@
     virtual VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&, const RenderFragmentContainer*);
 
     RenderPtr<RenderBlock> clone() const;
-    RenderBlock* continuationBefore(RenderObject* beforeChild);
 
     RenderFragmentedFlow* updateCachedEnclosingFragmentedFlow(RenderFragmentedFlow*) const;
 

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -4904,57 +4904,6 @@
         || style().logicalMaxWidth().isPercentOrCalculated();
 }
 
-static void markBoxForRelayoutAfterSplit(RenderBox& box)
-{
-    // FIXME: The table code should handle that automatically. If not,
-    // we should fix it and remove the table part checks.
-    if (is<RenderTable>(box)) {
-        // Because we may have added some sections with already computed column structures, we need to
-        // sync the table structure with them now. This avoids crashes when adding new cells to the table.
-        downcast<RenderTable>(box).forceSectionsRecalc();
-    } else if (is<RenderTableSection>(box))
-        downcast<RenderTableSection>(box).setNeedsCellRecalc();
-
-    box.setNeedsLayoutAndPrefWidthsRecalc();
-}
-
-RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
-{
-    bool didSplitParentAnonymousBoxes = false;
-
-    while (beforeChild->parent() != this) {
-        auto& boxToSplit = downcast<RenderBox>(*beforeChild->parent());
-        if (boxToSplit.firstChild() != beforeChild && boxToSplit.isAnonymous()) {
-            didSplitParentAnonymousBoxes = true;
-
-            // We have to split the parent box into two boxes and move children
-            // from |beforeChild| to end into the new post box.
-            auto newPostBox = boxToSplit.createAnonymousBoxWithSameTypeAs(*this);
-            auto& postBox = *newPostBox;
-            postBox.setChildrenInline(boxToSplit.childrenInline());
-            RenderBox* parentBox = downcast<RenderBox>(boxToSplit.parent());
-            // We need to invalidate the |parentBox| before inserting the new node
-            // so that the table repainting logic knows the structure is dirty.
-            // See for example RenderTableCell:clippedOverflowRectForRepaint.
-            markBoxForRelayoutAfterSplit(*parentBox);
-            parentBox->insertChildInternal(WTFMove(newPostBox), boxToSplit.nextSibling());
-            boxToSplit.moveChildrenTo(&postBox, beforeChild, nullptr, RenderBoxModelObject::NormalizeAfterInsertion::Yes);
-
-            markBoxForRelayoutAfterSplit(boxToSplit);
-            markBoxForRelayoutAfterSplit(postBox);
-
-            beforeChild = &postBox;
-        } else
-            beforeChild = &boxToSplit;
-    }
-
-    if (didSplitParentAnonymousBoxes)
-        markBoxForRelayoutAfterSplit(*this);
-
-    ASSERT(beforeChild->parent() == this);
-    return beforeChild;
-}
-
 LayoutUnit RenderBox::offsetFromLogicalTopOfFirstPage() const
 {
     auto* layoutState = view().frameView().layoutContext().layoutState();

Modified: trunk/Source/WebCore/rendering/RenderBox.h (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderBox.h	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderBox.h	2018-01-08 17:40:21 UTC (rev 226516)
@@ -665,8 +665,6 @@
 
     void paintRootBoxFillLayers(const PaintInfo&);
 
-    RenderObject* splitAnonymousBoxesAroundChild(RenderObject* beforeChild);
-
     bool skipContainingBlockForPercentHeightCalculation(const RenderBox& containingBlock, bool isPerpendicularWritingMode) const;
 
 private:

Modified: trunk/Source/WebCore/rendering/RenderRubyBase.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderRubyBase.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderRubyBase.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -61,7 +61,7 @@
     ASSERT_ARG(toBase, toBase);
 
     if (beforeChild && beforeChild->parent() != this)
-        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+        beforeChild = RenderTreeBuilder::current()->splitAnonymousBoxesAroundChild(*this, beforeChild);
 
     if (childrenInline())
         moveInlineChildren(toBase, beforeChild);
@@ -115,7 +115,7 @@
         return;
 
     if (toBase->childrenInline())
-        toBase->makeChildrenNonInline();
+        RenderTreeBuilder::current()->makeChildrenNonInline(*toBase);
 
     // If an anonymous block would be put next to another such block, then merge those.
     RenderObject* firstChildHere = firstChild();

Modified: trunk/Source/WebCore/rendering/RenderTable.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderTable.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderTable.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -170,7 +170,7 @@
         setNeedsSectionRecalc();
 
     if (beforeChild && beforeChild->parent() != this)
-        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+        beforeChild = builder.splitAnonymousBoxesAroundChild(*this, beforeChild);
 
     RenderBox::addChild(builder, WTFMove(child), beforeChild);
 }

Modified: trunk/Source/WebCore/rendering/RenderTableRow.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderTableRow.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderTableRow.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -114,7 +114,7 @@
 void RenderTableRow::addChild(RenderTreeBuilder& builder, RenderPtr<RenderObject> child, RenderObject* beforeChild)
 {
     if (beforeChild && beforeChild->parent() != this)
-        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);    
+        beforeChild = builder.splitAnonymousBoxesAroundChild(*this, beforeChild);    
 
     // Generated content can result in us having a null section so make sure to null check our parent.
     if (auto* section = this->section())

Modified: trunk/Source/WebCore/rendering/RenderTableSection.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/RenderTableSection.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/RenderTableSection.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -140,7 +140,7 @@
         setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
 
     if (beforeChild && beforeChild->parent() != this)
-        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+        beforeChild = builder.splitAnonymousBoxesAroundChild(*this, beforeChild);
 
     ASSERT(!beforeChild || is<RenderTableRow>(*beforeChild));
     RenderBox::addChild(builder, WTFMove(child), beforeChild);

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (226515 => 226516)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -33,6 +33,7 @@
 #include "RenderRubyRun.h"
 #include "RenderTableRow.h"
 #include "RenderText.h"
+#include "RenderTreeBuilderBlock.h"
 #include "RenderTreeBuilderFirstLetter.h"
 #include "RenderTreeBuilderFormControls.h"
 #include "RenderTreeBuilderList.h"
@@ -44,6 +45,59 @@
 
 RenderTreeBuilder* RenderTreeBuilder::s_current;
 
+static void markBoxForRelayoutAfterSplit(RenderBox& box)
+{
+    // FIXME: The table code should handle that automatically. If not,
+    // we should fix it and remove the table part checks.
+    if (is<RenderTable>(box)) {
+        // Because we may have added some sections with already computed column structures, we need to
+        // sync the table structure with them now. This avoids crashes when adding new cells to the table.
+        downcast<RenderTable>(box).forceSectionsRecalc();
+    } else if (is<RenderTableSection>(box))
+        downcast<RenderTableSection>(box).setNeedsCellRecalc();
+
+    box.setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+static void getInlineRun(RenderObject* start, RenderObject* boundary, RenderObject*& inlineRunStart, RenderObject*& inlineRunEnd)
+{
+    // Beginning at |start| we find the largest contiguous run of inlines that
+    // we can. We denote the run with start and end points, |inlineRunStart|
+    // and |inlineRunEnd|. Note that these two values may be the same if
+    // we encounter only one inline.
+    //
+    // We skip any non-inlines we encounter as long as we haven't found any
+    // inlines yet.
+    //
+    // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary|
+    // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
+    // a non-inline.
+
+    // Start by skipping as many non-inlines as we can.
+    auto* curr = start;
+    bool sawInline;
+    do {
+        while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
+            curr = curr->nextSibling();
+
+        inlineRunStart = inlineRunEnd = curr;
+
+        if (!curr)
+            return; // No more inline children to be found.
+
+        sawInline = curr->isInline();
+
+        curr = curr->nextSibling();
+        while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
+            inlineRunEnd = curr;
+            if (curr->isInline())
+                sawInline = true;
+            curr = curr->nextSibling();
+        }
+    } while (!sawInline);
+}
+
+
 RenderTreeBuilder::RenderTreeBuilder(RenderView& view)
     : m_view(view)
     , m_firstLetterBuilder(std::make_unique<FirstLetter>(*this))
@@ -52,6 +106,7 @@
     , m_tableBuilder(std::make_unique<Table>(*this))
     , m_rubyBuilder(std::make_unique<Ruby>(*this))
     , m_formControlsBuilder(std::make_unique<FormControls>(*this))
+    , m_blockBuilder(std::make_unique<Block>(*this))
 {
     RELEASE_ASSERT(!s_current || &m_view != &s_current->m_view);
     m_previous = s_current;
@@ -128,6 +183,95 @@
     insertChild(position.parent(), WTFMove(child), position.nextSibling());
 }
 
+void RenderTreeBuilder::insertChildToRenderBlock(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+    blockBuilder().insertChild(parent, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::insertChildToRenderBlockIgnoringContinuation(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+    blockBuilder().insertChildIgnoringContinuation(parent, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::makeChildrenNonInline(RenderBlock& parent, RenderObject* insertionPoint)
+{
+    // makeChildrenNonInline takes a block whose children are *all* inline and it
+    // makes sure that inline children are coalesced under anonymous
+    // blocks. If |insertionPoint| is defined, then it represents the insertion point for
+    // the new block child that is causing us to have to wrap all the inlines. This
+    // means that we cannot coalesce inlines before |insertionPoint| with inlines following
+    // |insertionPoint|, because the new child is going to be inserted in between the inlines,
+    // splitting them.
+    ASSERT(parent.isInlineBlockOrInlineTable() || !parent.isInline());
+    ASSERT(!insertionPoint || insertionPoint->parent() == &parent);
+
+    parent.setChildrenInline(false);
+
+    auto* child = parent.firstChild();
+    if (!child)
+        return;
+
+    parent.deleteLines();
+
+    while (child) {
+        RenderObject* inlineRunStart = nullptr;
+        RenderObject* inlineRunEnd = nullptr;
+        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
+
+        if (!inlineRunStart)
+            break;
+
+        child = inlineRunEnd->nextSibling();
+
+        auto newBlock = parent.createAnonymousBlock();
+        auto& block = *newBlock;
+        parent.insertChildInternal(WTFMove(newBlock), inlineRunStart);
+        parent.moveChildrenTo(&block, inlineRunStart, child, RenderBoxModelObject::NormalizeAfterInsertion::No);
+    }
+#ifndef NDEBUG
+    for (RenderObject* c = parent.firstChild(); c; c = c->nextSibling())
+        ASSERT(!c->isInline());
+#endif
+    parent.repaint();
+}
+
+RenderObject* RenderTreeBuilder::splitAnonymousBoxesAroundChild(RenderBox& parent, RenderObject* beforeChild)
+{
+    bool didSplitParentAnonymousBoxes = false;
+
+    while (beforeChild->parent() != &parent) {
+        auto& boxToSplit = downcast<RenderBox>(*beforeChild->parent());
+        if (boxToSplit.firstChild() != beforeChild && boxToSplit.isAnonymous()) {
+            didSplitParentAnonymousBoxes = true;
+
+            // We have to split the parent box into two boxes and move children
+            // from |beforeChild| to end into the new post box.
+            auto newPostBox = boxToSplit.createAnonymousBoxWithSameTypeAs(parent);
+            auto& postBox = *newPostBox;
+            postBox.setChildrenInline(boxToSplit.childrenInline());
+            RenderBox* parentBox = downcast<RenderBox>(boxToSplit.parent());
+            // We need to invalidate the |parentBox| before inserting the new node
+            // so that the table repainting logic knows the structure is dirty.
+            // See for example RenderTableCell:clippedOverflowRectForRepaint.
+            markBoxForRelayoutAfterSplit(*parentBox);
+            parentBox->insertChildInternal(WTFMove(newPostBox), boxToSplit.nextSibling());
+            boxToSplit.moveChildrenTo(&postBox, beforeChild, nullptr, RenderBoxModelObject::NormalizeAfterInsertion::Yes);
+
+            markBoxForRelayoutAfterSplit(boxToSplit);
+            markBoxForRelayoutAfterSplit(postBox);
+
+            beforeChild = &postBox;
+        } else
+            beforeChild = &boxToSplit;
+    }
+
+    if (didSplitParentAnonymousBoxes)
+        markBoxForRelayoutAfterSplit(parent);
+
+    ASSERT(beforeChild->parent() == &parent);
+    return beforeChild;
+}
+
 void RenderTreeBuilder::updateAfterDescendants(RenderElement& renderer)
 {
     if (is<RenderBlock>(renderer))

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h (226515 => 226516)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h	2018-01-08 17:02:33 UTC (rev 226515)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h	2018-01-08 17:40:21 UTC (rev 226516)
@@ -46,6 +46,12 @@
     // FIXME: Remove.
     static RenderTreeBuilder* current() { return s_current; }
 
+    // These functions are temporary until after all block/inline/continuation code is moved over.
+    void insertChildToRenderBlock(RenderBlock& parent, RenderPtr<RenderObject>, RenderObject* beforeChild = nullptr);
+    void insertChildToRenderBlockIgnoringContinuation(RenderBlock& parent, RenderPtr<RenderObject>, RenderObject* beforeChild = nullptr);
+    void makeChildrenNonInline(RenderBlock& parent, RenderObject* insertionPoint = nullptr);
+    RenderObject* splitAnonymousBoxesAroundChild(RenderBox& parent, RenderObject* beforeChild);
+
 private:
     class FirstLetter;
     class List;
@@ -53,6 +59,7 @@
     class Table;
     class Ruby;
     class FormControls;
+    class Block;
 
     FirstLetter& firstLetterBuilder() { return *m_firstLetterBuilder; }
     List& listBuilder() { return *m_listBuilder; }
@@ -60,6 +67,7 @@
     Table& tableBuilder() { return *m_tableBuilder; }
     Ruby& rubyBuilder() { return *m_rubyBuilder; }
     FormControls& formControlsBuilder() { return *m_formControlsBuilder; }
+    Block& blockBuilder() { return *m_blockBuilder; }
 
     RenderView& m_view;
 
@@ -72,6 +80,7 @@
     std::unique_ptr<Table> m_tableBuilder;
     std::unique_ptr<Ruby> m_rubyBuilder;
     std::unique_ptr<FormControls> m_formControlsBuilder;
+    std::unique_ptr<Block> m_blockBuilder;
 };
 
 }

Added: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp (0 => 226516)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp	                        (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp	2018-01-08 17:40:21 UTC (rev 226516)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderTreeBuilderBlock.h"
+
+#include "RenderChildIterator.h"
+#include "RenderFullScreen.h"
+
+namespace WebCore {
+
+static RenderBlock* continuationBefore(RenderBlock& parent, RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() == &parent)
+        return &parent;
+
+    RenderBlock* nextToLast = &parent;
+    RenderBlock* last = &parent;
+    for (auto* current = downcast<RenderBlock>(parent.continuation()); current; current = downcast<RenderBlock>(current->continuation())) {
+        if (beforeChild && beforeChild->parent() == current) {
+            if (current->firstChild() == beforeChild)
+                return last;
+            return current;
+        }
+
+        nextToLast = last;
+        last = current;
+    }
+
+    if (!beforeChild && !last->firstChild())
+        return nextToLast;
+    return last;
+}
+
+RenderTreeBuilder::Block::Block(RenderTreeBuilder& builder)
+    : m_builder(builder)
+{
+}
+
+void RenderTreeBuilder::Block::insertChild(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+    if (parent.continuation() && !parent.isAnonymousBlock())
+        insertChildToContinuation(parent, WTFMove(child), beforeChild);
+    else
+        insertChildIgnoringContinuation(parent, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::Block::insertChildToContinuation(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+    RenderBlock* flow = continuationBefore(parent, beforeChild);
+    ASSERT(!beforeChild || is<RenderBlock>(*beforeChild->parent()));
+    RenderBoxModelObject* beforeChildParent = nullptr;
+    if (beforeChild)
+        beforeChildParent = downcast<RenderBoxModelObject>(beforeChild->parent());
+    else {
+        RenderBoxModelObject* continuation = flow->continuation();
+        if (continuation)
+            beforeChildParent = continuation;
+        else
+            beforeChildParent = flow;
+    }
+
+    if (child->isFloatingOrOutOfFlowPositioned()) {
+        beforeChildParent->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+        return;
+    }
+
+    bool childIsNormal = child->isInline() || !child->style().columnSpan();
+    bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style().columnSpan();
+    bool flowIsNormal = flow->isInline() || !flow->style().columnSpan();
+
+    if (flow == beforeChildParent) {
+        flow->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+        return;
+    }
+
+    // The goal here is to match up if we can, so that we can coalesce and create the
+    // minimal # of continuations needed for the inline.
+    if (childIsNormal == bcpIsNormal) {
+        beforeChildParent->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+        return;
+    }
+    if (flowIsNormal == childIsNormal) {
+        flow->addChildIgnoringContinuation(m_builder, WTFMove(child), nullptr); // Just treat like an append.
+        return;
+    }
+    beforeChildParent->addChildIgnoringContinuation(m_builder, WTFMove(child), beforeChild);
+}
+
+void RenderTreeBuilder::Block::insertChildIgnoringContinuation(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() != &parent) {
+        RenderElement* beforeChildContainer = beforeChild->parent();
+        while (beforeChildContainer->parent() != &parent)
+            beforeChildContainer = beforeChildContainer->parent();
+        ASSERT(beforeChildContainer);
+
+        if (beforeChildContainer->isAnonymous()) {
+            RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!beforeChildContainer->isInline());
+
+            // If the requested beforeChild is not one of our children, then this is because
+            // there is an anonymous container within this object that contains the beforeChild.
+            RenderElement* beforeChildAnonymousContainer = beforeChildContainer;
+            if (beforeChildAnonymousContainer->isAnonymousBlock()
+#if ENABLE(FULLSCREEN_API)
+                // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
+                || beforeChildAnonymousContainer->isRenderFullScreen()
+                || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
+#endif
+                ) {
+                // Insert the child into the anonymous block box instead of here.
+                if (child->isInline() || beforeChild->parent()->firstChild() != beforeChild)
+                    m_builder.insertChild(*beforeChild->parent(), WTFMove(child), beforeChild);
+                else
+                    m_builder.insertChild(parent, WTFMove(child), beforeChild->parent());
+                return;
+            }
+
+            ASSERT(beforeChildAnonymousContainer->isTable());
+
+            if (child->isTablePart()) {
+                // Insert into the anonymous table.
+                m_builder.insertChild(*beforeChildAnonymousContainer, WTFMove(child), beforeChild);
+                return;
+            }
+
+            beforeChild = m_builder.splitAnonymousBoxesAroundChild(parent, beforeChild);
+
+            RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(beforeChild->parent() == &parent);
+        }
+    }
+
+    bool madeBoxesNonInline = false;
+
+    // A block has to either have all of its children inline, or all of its children as blocks.
+    // So, if our children are currently inline and a block child has to be inserted, we move all our
+    // inline children into anonymous block boxes.
+    if (parent.childrenInline() && !child->isInline() && !child->isFloatingOrOutOfFlowPositioned()) {
+        // This is a block with inline content. Wrap the inline content in anonymous blocks.
+        m_builder.makeChildrenNonInline(parent, beforeChild);
+        madeBoxesNonInline = true;
+
+        if (beforeChild && beforeChild->parent() != &parent) {
+            beforeChild = beforeChild->parent();
+            ASSERT(beforeChild->isAnonymousBlock());
+            ASSERT(beforeChild->parent() == &parent);
+        }
+    } else if (!parent.childrenInline() && (child->isFloatingOrOutOfFlowPositioned() || child->isInline())) {
+        // If we're inserting an inline child but all of our children are blocks, then we have to make sure
+        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
+        // a new one is created and inserted into our list of children in the appropriate position.
+        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : parent.lastChild();
+
+        if (afterChild && afterChild->isAnonymousBlock()) {
+            m_builder.insertChild(downcast<RenderBlock>(*afterChild), WTFMove(child));
+            return;
+        }
+
+        if (child->isInline()) {
+            // No suitable existing anonymous box - create a new one.
+            auto newBox = parent.createAnonymousBlock();
+            auto& box = *newBox;
+            parent.RenderBox::addChild(m_builder, WTFMove(newBox), beforeChild);
+            m_builder.insertChild(box, WTFMove(child));
+            return;
+        }
+    }
+
+    parent.invalidateLineLayoutPath();
+
+    parent.RenderBox::addChild(m_builder, WTFMove(child), beforeChild);
+
+    if (madeBoxesNonInline && is<RenderBlock>(parent.parent()) && parent.isAnonymousBlock())
+        downcast<RenderBlock>(*parent.parent()).removeLeftoverAnonymousBlock(&parent);
+    // parent object may be dead here
+}
+
+}

Added: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.h (0 => 226516)


--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.h	2018-01-08 17:40:21 UTC (rev 226516)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "RenderTreeBuilder.h"
+
+namespace WebCore {
+
+class RenderTreeBuilder::Block {
+public:
+    Block(RenderTreeBuilder&);
+
+    void insertChild(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+    void insertChildIgnoringContinuation(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+
+private:
+    void insertChildToContinuation(RenderBlock& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+
+    RenderTreeBuilder& m_builder;
+};
+
+}
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to