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