[RenderTreeBuilder] Move RenderElement::insertChildInternal() to RenderTreeBuilder
[WebKit-https.git] / Source / WebCore / rendering / updating / RenderTreeBuilder.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RenderTreeBuilder.h"
28
29 #include "AXObjectCache.h"
30 #include "Frame.h"
31 #include "FrameSelection.h"
32 #include "RenderButton.h"
33 #include "RenderCounter.h"
34 #include "RenderElement.h"
35 #include "RenderGrid.h"
36 #include "RenderLineBreak.h"
37 #include "RenderMathMLFenced.h"
38 #include "RenderMenuList.h"
39 #include "RenderRuby.h"
40 #include "RenderRubyBase.h"
41 #include "RenderRubyRun.h"
42 #include "RenderSVGContainer.h"
43 #include "RenderSVGInline.h"
44 #include "RenderSVGRoot.h"
45 #include "RenderTable.h"
46 #include "RenderTableRow.h"
47 #include "RenderTableSection.h"
48 #include "RenderText.h"
49 #include "RenderTreeBuilderBlock.h"
50 #include "RenderTreeBuilderBlockFlow.h"
51 #include "RenderTreeBuilderFirstLetter.h"
52 #include "RenderTreeBuilderFormControls.h"
53 #include "RenderTreeBuilderInline.h"
54 #include "RenderTreeBuilderList.h"
55 #include "RenderTreeBuilderMathML.h"
56 #include "RenderTreeBuilderMultiColumn.h"
57 #include "RenderTreeBuilderRuby.h"
58 #include "RenderTreeBuilderSVG.h"
59 #include "RenderTreeBuilderTable.h"
60
61 namespace WebCore {
62
63 RenderTreeBuilder* RenderTreeBuilder::s_current;
64
65 static void markBoxForRelayoutAfterSplit(RenderBox& box)
66 {
67     // FIXME: The table code should handle that automatically. If not,
68     // we should fix it and remove the table part checks.
69     if (is<RenderTable>(box)) {
70         // Because we may have added some sections with already computed column structures, we need to
71         // sync the table structure with them now. This avoids crashes when adding new cells to the table.
72         downcast<RenderTable>(box).forceSectionsRecalc();
73     } else if (is<RenderTableSection>(box))
74         downcast<RenderTableSection>(box).setNeedsCellRecalc();
75
76     box.setNeedsLayoutAndPrefWidthsRecalc();
77 }
78
79 static void getInlineRun(RenderObject* start, RenderObject* boundary, RenderObject*& inlineRunStart, RenderObject*& inlineRunEnd)
80 {
81     // Beginning at |start| we find the largest contiguous run of inlines that
82     // we can. We denote the run with start and end points, |inlineRunStart|
83     // and |inlineRunEnd|. Note that these two values may be the same if
84     // we encounter only one inline.
85     //
86     // We skip any non-inlines we encounter as long as we haven't found any
87     // inlines yet.
88     //
89     // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary|
90     // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
91     // a non-inline.
92
93     // Start by skipping as many non-inlines as we can.
94     auto* curr = start;
95     bool sawInline;
96     do {
97         while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
98             curr = curr->nextSibling();
99
100         inlineRunStart = inlineRunEnd = curr;
101
102         if (!curr)
103             return; // No more inline children to be found.
104
105         sawInline = curr->isInline();
106
107         curr = curr->nextSibling();
108         while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
109             inlineRunEnd = curr;
110             if (curr->isInline())
111                 sawInline = true;
112             curr = curr->nextSibling();
113         }
114     } while (!sawInline);
115 }
116
117 RenderTreeBuilder::RenderTreeBuilder(RenderView& view)
118     : m_view(view)
119     , m_firstLetterBuilder(std::make_unique<FirstLetter>(*this))
120     , m_listBuilder(std::make_unique<List>(*this))
121     , m_multiColumnBuilder(std::make_unique<MultiColumn>(*this))
122     , m_tableBuilder(std::make_unique<Table>(*this))
123     , m_rubyBuilder(std::make_unique<Ruby>(*this))
124     , m_formControlsBuilder(std::make_unique<FormControls>(*this))
125     , m_blockBuilder(std::make_unique<Block>(*this))
126     , m_blockFlowBuilder(std::make_unique<BlockFlow>(*this))
127     , m_inlineBuilder(std::make_unique<Inline>(*this))
128     , m_svgBuilder(std::make_unique<SVG>(*this))
129     , m_mathMLBuilder(std::make_unique<MathML>(*this))
130 {
131     RELEASE_ASSERT(!s_current || &m_view != &s_current->m_view);
132     m_previous = s_current;
133     s_current = this;
134 }
135
136 RenderTreeBuilder::~RenderTreeBuilder()
137 {
138     s_current = m_previous;
139 }
140
141 void RenderTreeBuilder::insertChild(RenderElement& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
142 {
143     auto insertRecursiveIfNeeded = [&](RenderElement& parentCandidate) {
144         if (&parent == &parentCandidate) {
145             insertChildToRenderElement(parent, WTFMove(child), beforeChild);
146             return;
147         }
148         insertChild(parentCandidate, WTFMove(child), beforeChild);
149     };
150
151     ASSERT(&parent.view() == &m_view);
152
153     if (is<RenderText>(beforeChild)) {
154         if (auto* wrapperInline = downcast<RenderText>(*beforeChild).inlineWrapperForDisplayContents())
155             beforeChild = wrapperInline;
156     }
157
158     if (is<RenderTableRow>(parent)) {
159         auto& parentCandidate = tableBuilder().findOrCreateParentForChild(downcast<RenderTableRow>(parent), *child, beforeChild);
160         if (&parentCandidate == &parent) {
161             tableBuilder().insertChild(downcast<RenderTableRow>(parentCandidate), WTFMove(child), beforeChild);
162             return;
163         }
164         insertRecursiveIfNeeded(parentCandidate);
165         return;
166     }
167
168     if (is<RenderTableSection>(parent)) {
169         auto& parentCandidate = tableBuilder().findOrCreateParentForChild(downcast<RenderTableSection>(parent), *child, beforeChild);
170         if (&parent == &parentCandidate) {
171             tableBuilder().insertChild(downcast<RenderTableSection>(parent), WTFMove(child), beforeChild);
172             return;
173         }
174         insertRecursiveIfNeeded(parentCandidate);
175         return;
176     }
177
178     if (is<RenderTable>(parent)) {
179         auto& parentCandidate = tableBuilder().findOrCreateParentForChild(downcast<RenderTable>(parent), *child, beforeChild);
180         if (&parentCandidate == &parent) {
181             tableBuilder().insertChild(downcast<RenderTable>(parentCandidate), WTFMove(child), beforeChild);
182             return;
183         }
184         insertRecursiveIfNeeded(parentCandidate);
185         return;
186     }
187
188     if (is<RenderRubyAsBlock>(parent)) {
189         insertRecursiveIfNeeded(rubyBuilder().findOrCreateParentForChild(downcast<RenderRubyAsBlock>(parent), *child, beforeChild));
190         return;
191     }
192
193     if (is<RenderRubyAsInline>(parent)) {
194         insertRecursiveIfNeeded(rubyBuilder().findOrCreateParentForChild(downcast<RenderRubyAsInline>(parent), *child, beforeChild));
195         return;
196     }
197
198     if (is<RenderRubyRun>(parent)) {
199         rubyBuilder().insertChild(downcast<RenderRubyRun>(parent), WTFMove(child), beforeChild);
200         return;
201     }
202
203     if (is<RenderButton>(parent)) {
204         formControlsBuilder().insertChild(downcast<RenderButton>(parent), WTFMove(child), beforeChild);
205         return;
206     }
207
208     if (is<RenderMenuList>(parent)) {
209         formControlsBuilder().insertChild(downcast<RenderMenuList>(parent), WTFMove(child), beforeChild);
210         return;
211     }
212
213     if (is<RenderSVGContainer>(parent)) {
214         svgBuilder().insertChild(downcast<RenderSVGContainer>(parent), WTFMove(child), beforeChild);
215         return;
216     }
217
218     if (is<RenderSVGInline>(parent)) {
219         svgBuilder().insertChild(downcast<RenderSVGInline>(parent), WTFMove(child), beforeChild);
220         return;
221     }
222
223     if (is<RenderSVGRoot>(parent)) {
224         svgBuilder().insertChild(downcast<RenderSVGRoot>(parent), WTFMove(child), beforeChild);
225         return;
226     }
227
228     if (is<RenderSVGText>(parent)) {
229         svgBuilder().insertChild(downcast<RenderSVGText>(parent), WTFMove(child), beforeChild);
230         return;
231     }
232
233     if (is<RenderMathMLFenced>(parent)) {
234         mathMLBuilder().insertChild(downcast<RenderMathMLFenced>(parent), WTFMove(child), beforeChild);
235         return;
236     }
237
238     if (is<RenderGrid>(parent)) {
239         insertChildToRenderGrid(downcast<RenderGrid>(parent), WTFMove(child), beforeChild);
240         return;
241     }
242
243     if (is<RenderBlockFlow>(parent)) {
244         blockFlowBuilder().insertChild(downcast<RenderBlockFlow>(parent), WTFMove(child), beforeChild);
245         return;
246     }
247
248     if (is<RenderBlock>(parent)) {
249         blockBuilder().insertChild(downcast<RenderBlock>(parent), WTFMove(child), beforeChild);
250         return;
251     }
252
253     if (is<RenderInline>(parent)) {
254         inlineBuilder().insertChild(downcast<RenderInline>(parent), WTFMove(child), beforeChild);
255         return;
256     }
257
258     insertChildToRenderElement(parent, WTFMove(child), beforeChild);
259 }
260
261 void RenderTreeBuilder::insertChildIgnoringContinuation(RenderElement& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
262 {
263     if (is<RenderInline>(parent)) {
264         inlineBuilder().insertChildIgnoringContinuation(downcast<RenderInline>(parent), WTFMove(child), beforeChild);
265         return;
266     }
267
268     if (is<RenderBlock>(parent)) {
269         blockBuilder().insertChildIgnoringContinuation(downcast<RenderBlock>(parent), WTFMove(child), beforeChild);
270         return;
271     }
272
273     insertChild(parent, WTFMove(child), beforeChild);
274 }
275
276 RenderPtr<RenderObject> RenderTreeBuilder::takeChild(RenderElement& parent, RenderObject& child)
277 {
278     if (is<RenderRubyAsInline>(parent))
279         return rubyBuilder().takeChild(downcast<RenderRubyAsInline>(parent), child);
280
281     if (is<RenderRubyAsBlock>(parent))
282         return rubyBuilder().takeChild(downcast<RenderRubyAsBlock>(parent), child);
283
284     if (is<RenderRubyRun>(parent))
285         return rubyBuilder().takeChild(downcast<RenderRubyRun>(parent), child);
286
287     if (is<RenderMenuList>(parent))
288         return takeChildFromRenderMenuList(downcast<RenderMenuList>(parent), child);
289
290     if (is<RenderButton>(parent))
291         return takeChildFromRenderButton(downcast<RenderButton>(parent), child);
292
293     if (is<RenderGrid>(parent))
294         return takeChildFromRenderGrid(downcast<RenderGrid>(parent), child);
295
296     if (is<RenderSVGText>(parent))
297         return svgBuilder().takeChild(downcast<RenderSVGText>(parent), child);
298
299     if (is<RenderSVGInline>(parent))
300         return svgBuilder().takeChild(downcast<RenderSVGInline>(parent), child);
301
302     if (is<RenderSVGContainer>(parent))
303         return svgBuilder().takeChild(downcast<RenderSVGContainer>(parent), child);
304
305     if (is<RenderSVGRoot>(parent))
306         return svgBuilder().takeChild(downcast<RenderSVGRoot>(parent), child);
307
308     if (is<RenderBlockFlow>(parent))
309         return blockBuilder().takeChild(downcast<RenderBlockFlow>(parent), child);
310
311     if (is<RenderBlock>(parent))
312         return blockBuilder().takeChild(downcast<RenderBlock>(parent), child);
313
314     return takeChildFromRenderElement(parent, child);
315 }
316
317 void RenderTreeBuilder::insertChild(RenderTreePosition& position, RenderPtr<RenderObject> child)
318 {
319     insertChild(position.parent(), WTFMove(child), position.nextSibling());
320 }
321
322 void RenderTreeBuilder::insertChildToRenderElement(RenderElement& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
323 {
324     if (tableBuilder().childRequiresTable(parent, *child)) {
325         RenderTable* table;
326         RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : parent.lastChild();
327         if (afterChild && afterChild->isAnonymous() && is<RenderTable>(*afterChild) && !afterChild->isBeforeContent())
328             table = downcast<RenderTable>(afterChild);
329         else {
330             auto newTable = RenderTable::createAnonymousWithParentRenderer(parent);
331             table = newTable.get();
332             insertChild(parent, WTFMove(newTable), beforeChild);
333         }
334
335         insertChild(*table, WTFMove(child));
336         return;
337     }
338     auto& newChild = *child.get();
339     insertChildToRenderElementInternal(parent, WTFMove(child), beforeChild);
340     parent.didInsertChild(newChild, beforeChild);
341 }
342
343 void RenderTreeBuilder::insertChildToRenderElementInternal(RenderElement& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
344 {
345     RELEASE_ASSERT_WITH_MESSAGE(!parent.view().frameView().layoutContext().layoutState(), "Layout must not mutate render tree");
346     ASSERT(parent.canHaveChildren() || parent.canHaveGeneratedChildren());
347     ASSERT(!child->parent());
348     ASSERT(!parent.isRenderBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
349
350     while (beforeChild && beforeChild->parent() && beforeChild->parent() != &parent)
351     beforeChild = beforeChild->parent();
352
353     ASSERT(!beforeChild || beforeChild->parent() == &parent);
354     ASSERT(!is<RenderText>(beforeChild) || !downcast<RenderText>(*beforeChild).inlineWrapperForDisplayContents());
355
356     // Take the ownership.
357     auto* newChild = parent.attachRendererInternal(WTFMove(child), beforeChild);
358
359     newChild->initializeFragmentedFlowStateOnInsertion();
360     if (!parent.renderTreeBeingDestroyed()) {
361         newChild->insertedIntoTree();
362         if (is<RenderElement>(*newChild))
363         RenderCounter::rendererSubtreeAttached(downcast<RenderElement>(*newChild));
364     }
365
366     newChild->setNeedsLayoutAndPrefWidthsRecalc();
367     parent.setPreferredLogicalWidthsDirty(true);
368     if (!parent.normalChildNeedsLayout())
369     parent.setChildNeedsLayout(); // We may supply the static position for an absolute positioned child.
370
371     if (AXObjectCache* cache = parent.document().axObjectCache())
372     cache->childrenChanged(&parent, newChild);
373     if (is<RenderBlockFlow>(parent))
374     downcast<RenderBlockFlow>(parent).invalidateLineLayoutPath();
375     if (parent.hasOutlineAutoAncestor() || parent.outlineStyleForRepaint().outlineStyleIsAuto())
376     newChild->setHasOutlineAutoAncestor();
377 }
378
379 void RenderTreeBuilder::makeChildrenNonInline(RenderBlock& parent, RenderObject* insertionPoint)
380 {
381     // makeChildrenNonInline takes a block whose children are *all* inline and it
382     // makes sure that inline children are coalesced under anonymous
383     // blocks. If |insertionPoint| is defined, then it represents the insertion point for
384     // the new block child that is causing us to have to wrap all the inlines. This
385     // means that we cannot coalesce inlines before |insertionPoint| with inlines following
386     // |insertionPoint|, because the new child is going to be inserted in between the inlines,
387     // splitting them.
388     ASSERT(parent.isInlineBlockOrInlineTable() || !parent.isInline());
389     ASSERT(!insertionPoint || insertionPoint->parent() == &parent);
390
391     parent.setChildrenInline(false);
392
393     auto* child = parent.firstChild();
394     if (!child)
395         return;
396
397     parent.deleteLines();
398
399     while (child) {
400         RenderObject* inlineRunStart = nullptr;
401         RenderObject* inlineRunEnd = nullptr;
402         getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
403
404         if (!inlineRunStart)
405             break;
406
407         child = inlineRunEnd->nextSibling();
408
409         auto newBlock = parent.createAnonymousBlock();
410         auto& block = *newBlock;
411         insertChildToRenderElementInternal(parent, WTFMove(newBlock), inlineRunStart);
412         parent.moveChildrenTo(*this, &block, inlineRunStart, child, RenderBoxModelObject::NormalizeAfterInsertion::No);
413     }
414 #ifndef NDEBUG
415     for (RenderObject* c = parent.firstChild(); c; c = c->nextSibling())
416         ASSERT(!c->isInline());
417 #endif
418     parent.repaint();
419 }
420
421 RenderObject* RenderTreeBuilder::splitAnonymousBoxesAroundChild(RenderBox& parent, RenderObject* beforeChild)
422 {
423     bool didSplitParentAnonymousBoxes = false;
424
425     while (beforeChild->parent() != &parent) {
426         auto& boxToSplit = downcast<RenderBox>(*beforeChild->parent());
427         if (boxToSplit.firstChild() != beforeChild && boxToSplit.isAnonymous()) {
428             didSplitParentAnonymousBoxes = true;
429
430             // We have to split the parent box into two boxes and move children
431             // from |beforeChild| to end into the new post box.
432             auto newPostBox = boxToSplit.createAnonymousBoxWithSameTypeAs(parent);
433             auto& postBox = *newPostBox;
434             postBox.setChildrenInline(boxToSplit.childrenInline());
435             RenderBox* parentBox = downcast<RenderBox>(boxToSplit.parent());
436             // We need to invalidate the |parentBox| before inserting the new node
437             // so that the table repainting logic knows the structure is dirty.
438             // See for example RenderTableCell:clippedOverflowRectForRepaint.
439             markBoxForRelayoutAfterSplit(*parentBox);
440             insertChildToRenderElementInternal(*parentBox, WTFMove(newPostBox), boxToSplit.nextSibling());
441             boxToSplit.moveChildrenTo(*this, &postBox, beforeChild, nullptr, RenderBoxModelObject::NormalizeAfterInsertion::Yes);
442
443             markBoxForRelayoutAfterSplit(boxToSplit);
444             markBoxForRelayoutAfterSplit(postBox);
445
446             beforeChild = &postBox;
447         } else
448             beforeChild = &boxToSplit;
449     }
450
451     if (didSplitParentAnonymousBoxes)
452         markBoxForRelayoutAfterSplit(parent);
453
454     ASSERT(beforeChild->parent() == &parent);
455     return beforeChild;
456 }
457
458 void RenderTreeBuilder::childFlowStateChangesAndAffectsParentBlock(RenderElement& child)
459 {
460     auto* parent = child.parent();
461     if (!child.isInline()) {
462         if (is<RenderBlock>(parent))
463             blockBuilder().childBecameNonInline(downcast<RenderBlock>(*parent), child);
464         else if (is<RenderInline>(*parent))
465             inlineBuilder().childBecameNonInline(downcast<RenderInline>(*parent), child);
466     } else {
467         // An anonymous block must be made to wrap this inline.
468         auto newBlock = downcast<RenderBlock>(*parent).createAnonymousBlock();
469         auto& block = *newBlock;
470         insertChildToRenderElementInternal(*parent, WTFMove(newBlock), &child);
471         auto thisToMove = takeChildFromRenderElement(*parent, child);
472         insertChildToRenderElementInternal(block, WTFMove(thisToMove));
473     }
474 }
475
476 void RenderTreeBuilder::removeAnonymousWrappersForInlineChildrenIfNeeded(RenderElement& parent)
477 {
478     if (!is<RenderBlock>(parent))
479         return;
480     auto& blockParent = downcast<RenderBlock>(parent);
481     if (!blockParent.canDropAnonymousBlockChild())
482         return;
483
484     // We have changed to floated or out-of-flow positioning so maybe all our parent's
485     // children can be inline now. Bail if there are any block children left on the line,
486     // otherwise we can proceed to stripping solitary anonymous wrappers from the inlines.
487     // FIXME: We should also handle split inlines here - we exclude them at the moment by returning
488     // if we find a continuation.
489     auto* current = blockParent.firstChild();
490     while (current && ((current->isAnonymousBlock() && !downcast<RenderBlock>(*current).isContinuation()) || current->style().isFloating() || current->style().hasOutOfFlowPosition()))
491         current = current->nextSibling();
492
493     if (current)
494         return;
495
496     RenderObject* next;
497     for (current = blockParent.firstChild(); current; current = next) {
498         next = current->nextSibling();
499         if (current->isAnonymousBlock())
500             blockBuilder().dropAnonymousBoxChild(blockParent, downcast<RenderBlock>(*current));
501     }
502 }
503
504 void RenderTreeBuilder::childFlowStateChangesAndNoLongerAffectsParentBlock(RenderElement& child)
505 {
506     ASSERT(child.parent());
507     removeAnonymousWrappersForInlineChildrenIfNeeded(*child.parent());
508 }
509
510 void RenderTreeBuilder::multiColumnDescendantInserted(RenderMultiColumnFlow& flow, RenderObject& newDescendant)
511 {
512     multiColumnBuilder().multiColumnDescendantInserted(flow, newDescendant);
513 }
514
515 static bool isAnonymousAndSafeToDelete(RenderElement& element)
516 {
517     if (!element.isAnonymous())
518         return false;
519     if (element.isRenderView() || element.isRenderFragmentedFlow())
520         return false;
521     return true;
522 }
523
524 static RenderObject& findDestroyRootIncludingAnonymous(RenderObject& renderer)
525 {
526     auto* destroyRoot = &renderer;
527     while (true) {
528         auto& destroyRootParent = *destroyRoot->parent();
529         if (!isAnonymousAndSafeToDelete(destroyRootParent))
530             break;
531         bool destroyingOnlyChild = destroyRootParent.firstChild() == destroyRoot && destroyRootParent.lastChild() == destroyRoot;
532         if (!destroyingOnlyChild)
533             break;
534         destroyRoot = &destroyRootParent;
535     }
536     return *destroyRoot;
537 }
538
539 void RenderTreeBuilder::removeFromParentAndDestroyCleaningUpAnonymousWrappers(RenderObject& child)
540 {
541     // If the tree is destroyed, there is no need for a clean-up phase.
542     if (child.renderTreeBeingDestroyed()) {
543         child.removeFromParentAndDestroy(*this);
544         return;
545     }
546
547     // Remove intruding floats from sibling blocks before detaching.
548     if (is<RenderBox>(child) && child.isFloatingOrOutOfFlowPositioned())
549         downcast<RenderBox>(child).removeFloatingOrPositionedChildFromBlockLists();
550     auto& destroyRoot = findDestroyRootIncludingAnonymous(child);
551     if (is<RenderTableRow>(destroyRoot))
552         tableBuilder().collapseAndDestroyAnonymousSiblingRows(downcast<RenderTableRow>(destroyRoot));
553
554     auto& destroyRootParent = *destroyRoot.parent();
555     destroyRootParent.removeAndDestroyChild(*this, destroyRoot);
556     removeAnonymousWrappersForInlineChildrenIfNeeded(destroyRootParent);
557
558     // Anonymous parent might have become empty, try to delete it too.
559     if (isAnonymousAndSafeToDelete(destroyRootParent) && !destroyRootParent.firstChild())
560         removeFromParentAndDestroyCleaningUpAnonymousWrappers(destroyRootParent);
561     // WARNING: child is deleted here.
562 }
563
564 void RenderTreeBuilder::updateAfterDescendants(RenderElement& renderer)
565 {
566     if (is<RenderBlock>(renderer))
567         firstLetterBuilder().updateAfterDescendants(downcast<RenderBlock>(renderer));
568     if (is<RenderListItem>(renderer))
569         listBuilder().updateItemMarker(downcast<RenderListItem>(renderer));
570     if (is<RenderBlockFlow>(renderer))
571         multiColumnBuilder().updateAfterDescendants(downcast<RenderBlockFlow>(renderer));
572 }
573
574 RenderPtr<RenderObject> RenderTreeBuilder::takeChildFromRenderMenuList(RenderMenuList& parent, RenderObject& child)
575 {
576     auto* innerRenderer = parent.innerRenderer();
577     if (!innerRenderer || &child == innerRenderer)
578         return blockBuilder().takeChild(parent, child);
579     return takeChild(*innerRenderer, child);
580 }
581
582 RenderPtr<RenderObject> RenderTreeBuilder::takeChildFromRenderButton(RenderButton& parent, RenderObject& child)
583 {
584     auto* innerRenderer = parent.innerRenderer();
585     if (!innerRenderer || &child == innerRenderer || child.parent() == &parent) {
586         ASSERT(&child == innerRenderer || !innerRenderer);
587         return blockBuilder().takeChild(parent, child);
588     }
589     return takeChild(*innerRenderer, child);
590 }
591
592 RenderPtr<RenderObject> RenderTreeBuilder::takeChildFromRenderGrid(RenderGrid& parent, RenderObject& child)
593 {
594     auto takenChild = blockBuilder().takeChild(parent, child);
595     // Positioned grid items do not take up space or otherwise participate in the layout of the grid,
596     // for that reason we don't need to mark the grid as dirty when they are removed.
597     if (child.isOutOfFlowPositioned())
598         return takenChild;
599
600     // The grid needs to be recomputed as it might contain auto-placed items that will change their position.
601     parent.dirtyGrid();
602     return takenChild;
603 }
604
605 RenderPtr<RenderObject> RenderTreeBuilder::takeChildFromRenderElement(RenderElement& parent, RenderObject& child)
606 {
607     RELEASE_ASSERT_WITH_MESSAGE(!parent.view().frameView().layoutContext().layoutState(), "Layout must not mutate render tree");
608
609     ASSERT(parent.canHaveChildren() || parent.canHaveGeneratedChildren());
610     ASSERT(child.parent() == &parent);
611
612     if (child.isFloatingOrOutOfFlowPositioned())
613         downcast<RenderBox>(child).removeFloatingOrPositionedChildFromBlockLists();
614
615     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
616     // that a positioned child got yanked). We also repaint, so that the area exposed when the child
617     // disappears gets repainted properly.
618     if (!parent.renderTreeBeingDestroyed() && child.everHadLayout()) {
619         child.setNeedsLayoutAndPrefWidthsRecalc();
620         // We only repaint |child| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
621         if (child.isBody())
622             parent.view().repaintRootContents();
623         else
624             child.repaint();
625     }
626
627     // If we have a line box wrapper, delete it.
628     if (is<RenderBox>(child))
629         downcast<RenderBox>(child).deleteLineBoxWrapper();
630     else if (is<RenderLineBreak>(child))
631         downcast<RenderLineBreak>(child).deleteInlineBoxWrapper();
632
633     if (!parent.renderTreeBeingDestroyed() && is<RenderFlexibleBox>(parent) && !child.isFloatingOrOutOfFlowPositioned() && child.isBox())
634         downcast<RenderFlexibleBox>(parent).clearCachedChildIntrinsicContentLogicalHeight(downcast<RenderBox>(child));
635
636     // If child is the start or end of the selection, then clear the selection to
637     // avoid problems of invalid pointers.
638     if (!parent.renderTreeBeingDestroyed() && child.isSelectionBorder())
639         parent.frame().selection().setNeedsSelectionUpdate();
640
641     if (!parent.renderTreeBeingDestroyed())
642         child.willBeRemovedFromTree();
643
644     child.resetFragmentedFlowStateOnRemoval();
645
646     // WARNING: There should be no code running between willBeRemovedFromTree() and the actual removal below.
647     // This is needed to avoid race conditions where willBeRemovedFromTree() would dirty the tree's structure
648     // and the code running here would force an untimely rebuilding, leaving |child| dangling.
649     auto childToTake = parent.detachRendererInternal(child);
650
651     // rendererRemovedFromTree() walks the whole subtree. We can improve performance
652     // by skipping this step when destroying the entire tree.
653     if (!parent.renderTreeBeingDestroyed() && is<RenderElement>(*childToTake))
654         RenderCounter::rendererRemovedFromTree(downcast<RenderElement>(*childToTake));
655
656     if (!parent.renderTreeBeingDestroyed()) {
657         if (AXObjectCache* cache = parent.document().existingAXObjectCache())
658             cache->childrenChanged(&parent);
659     }
660
661     return childToTake;
662 }
663
664 void RenderTreeBuilder::insertChildToRenderGrid(RenderGrid& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
665 {
666     auto& newChild = *child;
667     blockBuilder().insertChild(parent, WTFMove(child), beforeChild);
668
669     // Positioned grid items do not take up space or otherwise participate in the layout of the grid,
670     // for that reason we don't need to mark the grid as dirty when they are added.
671     if (newChild.isOutOfFlowPositioned())
672         return;
673
674     // The grid needs to be recomputed as it might contain auto-placed items that
675     // will change their position.
676     parent.dirtyGrid();
677 }
678
679 }