[Web Animations] Refactor cancelDeclarativeAnimationsForElement and willDestroyRender...
[WebKit-https.git] / Source / WebCore / rendering / updating / RenderTreeUpdater.cpp
1 /*
2  * Copyright (C) 2016-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 "RenderTreeUpdater.h"
28
29 #include "AXObjectCache.h"
30 #include "CSSAnimationController.h"
31 #include "ComposedTreeAncestorIterator.h"
32 #include "ComposedTreeIterator.h"
33 #include "Document.h"
34 #include "DocumentTimeline.h"
35 #include "Element.h"
36 #include "FullscreenManager.h"
37 #include "HTMLParserIdioms.h"
38 #include "HTMLSlotElement.h"
39 #include "InspectorInstrumentation.h"
40 #include "NodeRenderStyle.h"
41 #include "PseudoElement.h"
42 #include "RenderDescendantIterator.h"
43 #include "RenderFullScreen.h"
44 #include "RenderInline.h"
45 #include "RenderMultiColumnFlow.h"
46 #include "RenderMultiColumnSet.h"
47 #include "RenderTreeUpdaterGeneratedContent.h"
48 #include "RenderView.h"
49 #include "RuntimeEnabledFeatures.h"
50 #include "StyleResolver.h"
51 #include "StyleTreeResolver.h"
52 #include "TextManipulationController.h"
53 #include <wtf/SystemTracing.h>
54
55 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
56 #include "FrameView.h"
57 #include "FrameViewLayoutContext.h"
58 #include "LayoutState.h"
59 #include "LayoutTreeBuilder.h"
60 #endif
61
62 #if PLATFORM(IOS_FAMILY)
63 #include "ContentChangeObserver.h"
64 #endif
65
66 namespace WebCore {
67
68 RenderTreeUpdater::Parent::Parent(ContainerNode& root)
69     : element(is<Document>(root) ? nullptr : downcast<Element>(&root))
70     , renderTreePosition(RenderTreePosition(*root.renderer()))
71 {
72 }
73
74 RenderTreeUpdater::Parent::Parent(Element& element, const Style::ElementUpdates* updates)
75     : element(&element)
76     , updates(updates)
77     , renderTreePosition(element.renderer() ? makeOptional(RenderTreePosition(*element.renderer())) : WTF::nullopt)
78 {
79 }
80
81 RenderTreeUpdater::RenderTreeUpdater(Document& document)
82     : m_document(document)
83     , m_generatedContent(makeUnique<GeneratedContent>(*this))
84     , m_builder(renderView())
85 {
86 }
87
88 RenderTreeUpdater::~RenderTreeUpdater() = default;
89
90 static ContainerNode* findRenderingRoot(ContainerNode& node)
91 {
92     if (node.renderer())
93         return &node;
94     for (auto& ancestor : composedTreeAncestors(node)) {
95         if (ancestor.renderer())
96             return &ancestor;
97         if (!ancestor.hasDisplayContents())
98             return nullptr;
99     }
100     return &node.document();
101 }
102
103 static ListHashSet<ContainerNode*> findRenderingRoots(const Style::Update& update)
104 {
105     ListHashSet<ContainerNode*> renderingRoots;
106     for (auto* root : update.roots()) {
107         auto* renderingRoot = findRenderingRoot(*root);
108         if (!renderingRoot)
109             continue;
110         renderingRoots.add(renderingRoot);
111     }
112     return renderingRoots;
113 }
114
115 void RenderTreeUpdater::commit(std::unique_ptr<const Style::Update> styleUpdate)
116 {
117     ASSERT(&m_document == &styleUpdate->document());
118
119     if (!m_document.shouldCreateRenderers() || !m_document.renderView())
120         return;
121     
122     TraceScope scope(RenderTreeBuildStart, RenderTreeBuildEnd);
123
124     Style::PostResolutionCallbackDisabler callbackDisabler(m_document);
125
126     m_styleUpdate = WTFMove(styleUpdate);
127
128     for (auto* root : findRenderingRoots(*m_styleUpdate))
129         updateRenderTree(*root);
130
131     generatedContent().updateRemainingQuotes();
132
133     m_builder.updateAfterDescendants(renderView());
134
135     m_styleUpdate = nullptr;
136 }
137
138 static bool shouldCreateRenderer(const Element& element, const RenderElement& parentRenderer)
139 {
140     if (!parentRenderer.canHaveChildren() && !(element.isPseudoElement() && parentRenderer.canHaveGeneratedChildren()))
141         return false;
142     if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(element))
143         return false;
144     return true;
145 }
146
147 void RenderTreeUpdater::updateRenderTree(ContainerNode& root)
148 {
149     ASSERT(root.renderer());
150     ASSERT(m_parentStack.isEmpty());
151
152     m_parentStack.append(Parent(root));
153
154     auto descendants = composedTreeDescendants(root);
155     auto it = descendants.begin();
156     auto end = descendants.end();
157
158     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156172
159     it.dropAssertions();
160
161     while (it != end) {
162         popParentsToDepth(it.depth());
163
164         auto& node = *it;
165
166         if (auto* renderer = node.renderer())
167             renderTreePosition().invalidateNextSibling(*renderer);
168         else if (is<Element>(node) && downcast<Element>(node).hasDisplayContents())
169             renderTreePosition().invalidateNextSibling();
170
171         if (is<Text>(node)) {
172             auto& text = downcast<Text>(node);
173             auto* textUpdate = m_styleUpdate->textUpdate(text);
174             bool didCreateParent = parent().updates && parent().updates->update.change == Style::Detach;
175             bool mayNeedUpdateWhitespaceOnlyRenderer = renderingParent().didCreateOrDestroyChildRenderer && text.data().isAllSpecialCharacters<isHTMLSpace>();
176             if (didCreateParent || textUpdate || mayNeedUpdateWhitespaceOnlyRenderer)
177                 updateTextRenderer(text, textUpdate);
178
179             storePreviousRenderer(text);
180             it.traverseNextSkippingChildren();
181             continue;
182         }
183
184         auto& element = downcast<Element>(node);
185
186         auto* elementUpdates = m_styleUpdate->elementUpdates(element);
187
188         // We hop through display: contents elements in findRenderingRoot, so
189         // there may be other updates down the tree.
190         if (!elementUpdates && !element.hasDisplayContents()) {
191             storePreviousRenderer(element);
192             it.traverseNextSkippingChildren();
193             continue;
194         }
195
196         if (elementUpdates)
197             updateElementRenderer(element, elementUpdates->update);
198
199         storePreviousRenderer(element);
200
201         bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent()));
202         if (!mayHaveRenderedDescendants) {
203             it.traverseNextSkippingChildren();
204             continue;
205         }
206
207         pushParent(element, elementUpdates);
208
209         it.traverseNext();
210     }
211
212     popParentsToDepth(0);
213 }
214
215 auto RenderTreeUpdater::renderingParent() -> Parent&
216 {
217     for (unsigned i = m_parentStack.size(); i--;) {
218         if (m_parentStack[i].renderTreePosition)
219             return m_parentStack[i];
220     }
221     ASSERT_NOT_REACHED();
222     return m_parentStack.last();
223 }
224
225 RenderTreePosition& RenderTreeUpdater::renderTreePosition()
226 {
227     return *renderingParent().renderTreePosition;
228 }
229
230 void RenderTreeUpdater::pushParent(Element& element, const Style::ElementUpdates* updates)
231 {
232     m_parentStack.append(Parent(element, updates));
233
234     updateBeforeDescendants(element, updates);
235 }
236
237 void RenderTreeUpdater::popParent()
238 {
239     auto& parent = m_parentStack.last();
240     if (parent.element)
241         updateAfterDescendants(*parent.element, parent.updates);
242
243     m_parentStack.removeLast();
244 }
245
246 void RenderTreeUpdater::popParentsToDepth(unsigned depth)
247 {
248     ASSERT(m_parentStack.size() >= depth);
249
250     while (m_parentStack.size() > depth)
251         popParent();
252 }
253
254 void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates)
255 {
256     if (updates)
257         generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, PseudoId::Before);
258 }
259
260 void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates)
261 {
262     if (updates)
263         generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, PseudoId::After);
264
265     auto* renderer = element.renderer();
266     if (!renderer)
267         return;
268
269     m_builder.updateAfterDescendants(*renderer);
270
271     if (element.hasCustomStyleResolveCallbacks() && updates && updates->update.change == Style::Detach)
272         element.didAttachRenderers();
273 }
274
275 static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
276 {
277     const RenderStyle& currentStyle = renderer->style();
278
279     const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles();
280     if (!pseudoStyleCache)
281         return false;
282
283     for (auto& cache : *pseudoStyleCache) {
284         PseudoId pseudoId = cache->styleType();
285         std::unique_ptr<RenderStyle> newPseudoStyle = renderer->getUncachedPseudoStyle({ pseudoId }, newStyle, newStyle);
286         if (!newPseudoStyle)
287             return true;
288         if (*newPseudoStyle != *cache) {
289             newStyle->addCachedPseudoStyle(WTFMove(newPseudoStyle));
290             return true;
291         }
292     }
293     return false;
294 }
295
296 void RenderTreeUpdater::updateRendererStyle(RenderElement& renderer, RenderStyle&& newStyle, StyleDifference minimalStyleDifference)
297 {
298     auto oldStyle = RenderStyle::clone(renderer.style());
299     renderer.setStyle(WTFMove(newStyle), minimalStyleDifference);
300     m_builder.normalizeTreeAfterStyleChange(renderer, oldStyle);
301 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
302     if (RuntimeEnabledFeatures::sharedFeatures().layoutFormattingContextEnabled()) {
303         if (!m_document.view() || !m_document.view()->layoutContext().layoutTreeContent())
304             return;
305         auto& layoutContext = m_document.view()->layoutContext();
306         if (minimalStyleDifference >= StyleDifference::LayoutPositionedMovementOnly || renderer.needsLayout())
307             layoutContext.invalidateLayoutState();
308         if (auto* layoutBox = layoutContext.layoutTreeContent()->layoutBoxForRenderer(renderer))
309             layoutBox->updateStyle(renderer.style());
310     }
311 #endif
312 }
313
314 void RenderTreeUpdater::updateElementRenderer(Element& element, const Style::ElementUpdate& update)
315 {
316 #if PLATFORM(IOS_FAMILY)
317     ContentChangeObserver::StyleChangeScope observingScope(m_document, element);
318 #endif
319
320     bool shouldTearDownRenderers = update.change == Style::Detach && (element.renderer() || element.hasDisplayContents());
321     if (shouldTearDownRenderers) {
322         if (!element.renderer()) {
323             // We may be tearing down a descendant renderer cached in renderTreePosition.
324             renderTreePosition().invalidateNextSibling();
325         }
326
327         // display:none cancels animations.
328         auto teardownType = update.style->display() == DisplayType::None ? TeardownType::RendererUpdateCancelingAnimations : TeardownType::RendererUpdate;
329         tearDownRenderers(element, teardownType, m_builder);
330
331         renderingParent().didCreateOrDestroyChildRenderer = true;
332     }
333
334     bool hasDisplayContents = update.style->display() == DisplayType::Contents;
335     if (hasDisplayContents)
336         element.storeDisplayContentsStyle(RenderStyle::clonePtr(*update.style));
337     else
338         element.resetComputedStyle();
339
340     bool shouldCreateNewRenderer = !element.renderer() && !hasDisplayContents;
341     if (shouldCreateNewRenderer) {
342         if (element.hasCustomStyleResolveCallbacks())
343             element.willAttachRenderers();
344         createRenderer(element, RenderStyle::clone(*update.style));
345
346         renderingParent().didCreateOrDestroyChildRenderer = true;
347         return;
348     }
349
350     if (!element.renderer())
351         return;
352     auto& renderer = *element.renderer();
353
354     if (update.recompositeLayer) {
355         updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::RecompositeLayer);
356         return;
357     }
358
359     if (update.change == Style::NoChange) {
360         if (pseudoStyleCacheIsInvalid(&renderer, update.style.get())) {
361             updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
362             return;
363         }
364         return;
365     }
366
367     updateRendererStyle(renderer, RenderStyle::clone(*update.style), StyleDifference::Equal);
368 }
369
370 void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style)
371 {
372     auto computeInsertionPosition = [this, &element] () {
373         renderTreePosition().computeNextSibling(element);
374         return renderTreePosition();
375     };
376     
377     if (!shouldCreateRenderer(element, renderTreePosition().parent()))
378         return;
379
380     if (!element.rendererIsNeeded(style))
381         return;
382
383     RenderTreePosition insertionPosition = computeInsertionPosition();
384     auto newRenderer = element.createElementRenderer(WTFMove(style), insertionPosition);
385     if (!newRenderer)
386         return;
387
388     if (!insertionPosition.parent().isChildAllowed(*newRenderer, newRenderer->style()))
389         return;
390
391     element.setRenderer(newRenderer.get());
392
393     newRenderer->initializeStyle();
394
395 #if ENABLE(FULLSCREEN_API)
396     if (m_document.fullscreenManager().isFullscreen() && m_document.fullscreenManager().currentFullscreenElement() == &element) {
397         newRenderer = RenderFullScreen::wrapNewRenderer(m_builder, WTFMove(newRenderer), insertionPosition.parent(), m_document);
398         if (!newRenderer)
399             return;
400     }
401 #endif
402
403     m_builder.attach(insertionPosition.parent(), WTFMove(newRenderer), insertionPosition.nextSibling());
404
405     auto* textManipulationController = m_document.textManipulationControllerIfExists();
406     if (UNLIKELY(textManipulationController))
407         textManipulationController->didCreateRendererForElement(element);
408
409     if (AXObjectCache* cache = m_document.axObjectCache())
410         cache->updateCacheAfterNodeIsAttached(&element);
411 }
412
413 bool RenderTreeUpdater::textRendererIsNeeded(const Text& textNode)
414 {
415     auto& renderingParent = this->renderingParent();
416     auto& parentRenderer = renderingParent.renderTreePosition->parent();
417     if (!parentRenderer.canHaveChildren())
418         return false;
419     if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(textNode))
420         return false;
421     if (textNode.isEditingText())
422         return true;
423     if (!textNode.length())
424         return false;
425     if (!textNode.data().isAllSpecialCharacters<isHTMLSpace>())
426         return true;
427     if (is<RenderText>(renderingParent.previousChildRenderer))
428         return true;
429     // This text node has nothing but white space. We may still need a renderer in some cases.
430     if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet())
431         return false;
432     if (parentRenderer.isFlexibleBox() && !parentRenderer.isRenderButton())
433         return false;
434     if (parentRenderer.style().preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
435         return true;
436
437     auto* previousRenderer = renderingParent.previousChildRenderer;
438     if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
439         return false;
440
441     if (parentRenderer.isRenderInline()) {
442         // <span><div/> <div/></span>
443         if (previousRenderer && !previousRenderer->isInline())
444             return false;
445     } else {
446         if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline()))
447             return false;
448         
449         RenderObject* first = parentRenderer.firstChild();
450         while (first && first->isFloatingOrOutOfFlowPositioned())
451             first = first->nextSibling();
452         RenderObject* nextRenderer = textNode.renderer() ? textNode.renderer() :  renderTreePosition().nextSiblingRenderer(textNode);
453         if (!first || nextRenderer == first) {
454             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
455             return false;
456         }
457     }
458     return true;
459 }
460
461 void RenderTreeUpdater::createTextRenderer(Text& textNode, const Style::TextUpdate* textUpdate)
462 {
463     ASSERT(!textNode.renderer());
464
465     auto& renderTreePosition = this->renderTreePosition();
466     auto textRenderer = textNode.createTextRenderer(renderTreePosition.parent().style());
467
468     renderTreePosition.computeNextSibling(textNode);
469
470     if (!renderTreePosition.parent().isChildAllowed(*textRenderer, renderTreePosition.parent().style()))
471         return;
472
473     textNode.setRenderer(textRenderer.get());
474
475     if (textUpdate && textUpdate->inheritedDisplayContentsStyle && *textUpdate->inheritedDisplayContentsStyle) {
476         // Wrap text renderer into anonymous inline so we can give it a style.
477         // This is to support "<div style='display:contents;color:green'>text</div>" type cases
478         auto newDisplayContentsAnonymousWrapper = WebCore::createRenderer<RenderInline>(textNode.document(), RenderStyle::clone(**textUpdate->inheritedDisplayContentsStyle));
479         newDisplayContentsAnonymousWrapper->initializeStyle();
480         auto& displayContentsAnonymousWrapper = *newDisplayContentsAnonymousWrapper;
481         m_builder.attach(renderTreePosition.parent(), WTFMove(newDisplayContentsAnonymousWrapper), renderTreePosition.nextSibling());
482
483         textRenderer->setInlineWrapperForDisplayContents(&displayContentsAnonymousWrapper);
484         m_builder.attach(displayContentsAnonymousWrapper, WTFMove(textRenderer));
485         return;
486     }
487
488     m_builder.attach(renderTreePosition.parent(), WTFMove(textRenderer), renderTreePosition.nextSibling());
489 }
490
491 void RenderTreeUpdater::updateTextRenderer(Text& text, const Style::TextUpdate* textUpdate)
492 {
493     auto* existingRenderer = text.renderer();
494     bool needsRenderer = textRendererIsNeeded(text);
495
496     if (existingRenderer && textUpdate && textUpdate->inheritedDisplayContentsStyle) {
497         if (existingRenderer->inlineWrapperForDisplayContents() || *textUpdate->inheritedDisplayContentsStyle) {
498             // FIXME: We could update without teardown.
499             tearDownTextRenderer(text, m_builder);
500             existingRenderer = nullptr;
501         }
502     }
503
504     if (existingRenderer) {
505         if (needsRenderer) {
506             if (textUpdate)
507                 existingRenderer->setTextWithOffset(text.data(), textUpdate->offset, textUpdate->length);
508             return;
509         }
510         tearDownTextRenderer(text, m_builder);
511         renderingParent().didCreateOrDestroyChildRenderer = true;
512         return;
513     }
514     if (!needsRenderer)
515         return;
516     createTextRenderer(text, textUpdate);
517     renderingParent().didCreateOrDestroyChildRenderer = true;
518 }
519
520 void RenderTreeUpdater::storePreviousRenderer(Node& node)
521 {
522     auto* renderer = node.renderer();
523     if (!renderer)
524         return;
525     ASSERT(renderingParent().previousChildRenderer != renderer);
526     renderingParent().previousChildRenderer = renderer;
527 }
528
529 void RenderTreeUpdater::tearDownRenderers(Element& root)
530 {
531     auto* view = root.document().renderView();
532     if (!view)
533         return;
534     RenderTreeBuilder builder(*view);
535     tearDownRenderers(root, TeardownType::Full, builder);
536 }
537
538 void RenderTreeUpdater::tearDownRenderer(Text& text)
539 {
540     auto* view = text.document().renderView();
541     if (!view)
542         return;
543     RenderTreeBuilder builder(*view);
544     tearDownTextRenderer(text, builder);
545 }
546
547 void RenderTreeUpdater::tearDownRenderers(Element& root, TeardownType teardownType, RenderTreeBuilder& builder)
548 {
549     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
550
551     Vector<Element*, 30> teardownStack;
552
553     auto push = [&] (Element& element) {
554         if (element.hasCustomStyleResolveCallbacks())
555             element.willDetachRenderers();
556         teardownStack.append(&element);
557     };
558
559     auto& document = root.document();
560     auto* timeline = document.existingTimeline();
561     auto& animationController = document.frame()->animation();    
562
563     auto pop = [&] (unsigned depth) {
564         while (teardownStack.size() > depth) {
565             auto& element = *teardownStack.takeLast();
566
567             // Make sure we don't leave any renderers behind in nodes outside the composed tree.
568             if (element.shadowRoot())
569                 tearDownLeftoverShadowHostChildren(element, builder);
570
571             switch (teardownType) {
572             case TeardownType::Full:
573             case TeardownType::RendererUpdateCancelingAnimations:
574                 if (timeline) {
575                     if (document.renderTreeBeingDestroyed())
576                         timeline->cancelDeclarativeAnimationsForElement(element, WebAnimation::Silently::Yes);
577                     else if (teardownType == TeardownType::RendererUpdateCancelingAnimations)
578                         timeline->cancelDeclarativeAnimationsForElement(element, WebAnimation::Silently::No);
579                 }
580                 animationController.cancelAnimations(element);
581                 break;
582             case TeardownType::RendererUpdate:
583                 if (timeline)
584                     timeline->willChangeRendererForElement(element);
585                 break;
586             }
587
588             if (teardownType == TeardownType::Full)
589                 element.clearHoverAndActiveStatusBeforeDetachingRenderer();
590
591             GeneratedContent::removeBeforePseudoElement(element, builder);
592             GeneratedContent::removeAfterPseudoElement(element, builder);
593
594             if (auto* renderer = element.renderer()) {
595                 builder.destroyAndCleanUpAnonymousWrappers(*renderer);
596                 element.setRenderer(nullptr);
597             }
598
599             if (element.hasCustomStyleResolveCallbacks())
600                 element.didDetachRenderers();
601         }
602     };
603
604     push(root);
605
606     auto descendants = composedTreeDescendants(root);
607     for (auto it = descendants.begin(), end = descendants.end(); it != end; ++it) {
608         pop(it.depth());
609
610         if (is<Text>(*it)) {
611             tearDownTextRenderer(downcast<Text>(*it), builder);
612             continue;
613         }
614
615         push(downcast<Element>(*it));
616     }
617
618     pop(0);
619
620     tearDownLeftoverPaginationRenderersIfNeeded(root, builder);
621 }
622
623 void RenderTreeUpdater::tearDownTextRenderer(Text& text, RenderTreeBuilder& builder)
624 {
625     auto* renderer = text.renderer();
626     if (!renderer)
627         return;
628     builder.destroyAndCleanUpAnonymousWrappers(*renderer);
629     text.setRenderer(nullptr);
630 }
631
632 void RenderTreeUpdater::tearDownLeftoverPaginationRenderersIfNeeded(Element& root, RenderTreeBuilder& builder)
633 {
634     if (&root != root.document().documentElement())
635         return;
636     for (auto* child = root.document().renderView()->firstChild(); child;) {
637         auto* nextSibling = child->nextSibling();
638         if (is<RenderMultiColumnFlow>(*child) || is<RenderMultiColumnSet>(*child))
639             builder.destroyAndCleanUpAnonymousWrappers(*child);
640         child = nextSibling;
641     }
642 }
643
644 void RenderTreeUpdater::tearDownLeftoverShadowHostChildren(Element& host, RenderTreeBuilder& builder)
645 {
646     for (auto* hostChild = host.firstChild(); hostChild; hostChild = hostChild->nextSibling()) {
647         if (!hostChild->renderer())
648             continue;
649         if (is<Text>(*hostChild)) {
650             tearDownTextRenderer(downcast<Text>(*hostChild), builder);
651             continue;
652         }
653         if (is<Element>(*hostChild))
654             tearDownRenderers(downcast<Element>(*hostChild), TeardownType::Full, builder);
655     }
656 }
657
658 RenderView& RenderTreeUpdater::renderView()
659 {
660     return *m_document.renderView();
661 }
662
663 }