RenderNamedFlowThread should only support RenderElement children.
[WebKit-https.git] / Source / WebCore / style / StyleResolveTree.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  *           (C) 2007 David Smith (catfish.man@gmail.com)
7  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8  *           (C) 2007 Eric Seidel (eric@webkit.org)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "StyleResolveTree.h"
28
29 #include "AXObjectCache.h"
30 #include "AnimationController.h"
31 #include "CSSFontSelector.h"
32 #include "Element.h"
33 #include "ElementIterator.h"
34 #include "ElementRareData.h"
35 #include "FlowThreadController.h"
36 #include "InsertionPoint.h"
37 #include "NodeRenderStyle.h"
38 #include "NodeRenderingTraversal.h"
39 #include "NodeTraversal.h"
40 #include "RenderElement.h"
41 #include "RenderFullScreen.h"
42 #include "RenderNamedFlowThread.h"
43 #include "RenderText.h"
44 #include "RenderView.h"
45 #include "RenderWidget.h"
46 #include "Settings.h"
47 #include "ShadowRoot.h"
48 #include "StyleResolveForDocument.h"
49 #include "StyleResolver.h"
50 #include "Text.h"
51
52 #if PLATFORM(IOS)
53 #include "CSSFontSelector.h"
54 #include "WKContentObservation.h"
55 #endif
56
57 namespace WebCore {
58
59 namespace Style {
60
61 enum DetachType { NormalDetach, ReattachDetach };
62
63 static void attachRenderTree(Element&, PassRefPtr<RenderStyle>);
64 static void attachTextRenderer(Text&);
65 static void detachRenderTree(Element&, DetachType);
66 static void resolveTree(Element&, Change);
67
68 Change determineChange(const RenderStyle* s1, const RenderStyle* s2)
69 {
70     if (!s1 || !s2)
71         return Detach;
72     if (s1->display() != s2->display())
73         return Detach;
74     if (s1->hasPseudoStyle(FIRST_LETTER) != s2->hasPseudoStyle(FIRST_LETTER))
75         return Detach;
76     // We just detach if a renderer acquires or loses a column-span, since spanning elements
77     // typically won't contain much content.
78     if (s1->columnSpan() != s2->columnSpan())
79         return Detach;
80     if (!s1->contentDataEquivalent(s2))
81         return Detach;
82     // When text-combine property has been changed, we need to prepare a separate renderer object.
83     // When text-combine is on, we use RenderCombineText, otherwise RenderText.
84     // https://bugs.webkit.org/show_bug.cgi?id=55069
85     if (s1->hasTextCombine() != s2->hasTextCombine())
86         return Detach;
87     // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
88     if (s1->flowThread() != s2->flowThread())
89         return Detach;
90     // When the region thread has changed, we need to prepare a separate render region object.
91     if (s1->regionThread() != s2->regionThread())
92         return Detach;
93
94     if (*s1 != *s2) {
95         if (s1->inheritedNotEqual(s2))
96             return Inherit;
97         if (s1->hasExplicitlyInheritedProperties() || s2->hasExplicitlyInheritedProperties())
98             return Inherit;
99
100         return NoInherit;
101     }
102     // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
103     // because setStyle will do the right thing with anything else.
104     if (s1->hasAnyPublicPseudoStyles()) {
105         for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
106             if (s1->hasPseudoStyle(pseudoId)) {
107                 RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
108                 if (!ps2)
109                     return NoInherit;
110                 RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
111                 if (!ps1 || *ps1 != *ps2)
112                     return NoInherit;
113             }
114         }
115     }
116
117     return NoChange;
118 }
119
120 static bool isRendererReparented(const RenderObject* renderer)
121 {
122     if (!renderer->node()->isElementNode())
123         return false;
124     if (!renderer->style().flowThread().isEmpty())
125         return true;
126     return false;
127 }
128
129 static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
130 {
131     // Avoid an O(N^2) problem with this function by not checking for
132     // nextRenderer() when the parent element hasn't attached yet.
133     // FIXME: Why would we get here anyway if parent is not attached?
134     if (renderingParentNode && !renderingParentNode->renderer())
135         return nullptr;
136     for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
137         RenderObject* renderer = sibling->renderer();
138         if (renderer && !isRendererReparented(renderer))
139             return renderer;
140     }
141     return nullptr;
142 }
143
144 static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
145 {
146     if (!element.document().shouldCreateRenderers())
147         return false;
148     if (!renderingParent)
149         return false;
150     RenderObject* parentRenderer = renderingParent->renderer();
151     if (!parentRenderer)
152         return false;
153     if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
154         return false;
155     if (!renderingParent->childShouldCreateRenderer(element))
156         return false;
157     return true;
158 }
159
160 // Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
161 static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
162 {
163 #if ENABLE(CSS_REGIONS)
164     // The parent of a region should always be an element.
165     const RenderElement* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
166
167     bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderNamedFlowFragmentContainer();
168     bool parentIsNonRenderedInsideRegion = !parentRenderer && element.parentElement() && element.parentElement()->isInsideRegion();
169     if (!parentIsRegion && !parentIsNonRenderedInsideRegion)
170         return false;
171
172     if (!style)
173         style = element.styleForRenderer();
174
175     // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
176     if (element.rendererIsNeeded(*style))
177         element.setIsInsideRegion(true);
178
179     if (element.shouldMoveToFlowThread(*style))
180         return true;
181 #else
182     UNUSED_PARAM(element);
183     UNUSED_PARAM(renderingParentNode);
184     UNUSED_PARAM(style);
185 #endif
186     return false;
187 }
188
189 #if ENABLE(CSS_REGIONS)
190 static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
191 {
192     if (!element.shouldMoveToFlowThread(style))
193         return 0;
194     FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController();
195     RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
196     flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer);
197     return &parentFlowRenderer;
198 }
199 #endif
200
201 static void createRendererIfNeeded(Element& element, PassRefPtr<RenderStyle> resolvedStyle)
202 {
203     ASSERT(!element.renderer());
204
205     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
206
207     RefPtr<RenderStyle> style = resolvedStyle;
208
209     element.setIsInsideRegion(false);
210
211     if (!shouldCreateRenderer(element, renderingParentNode) && !elementInsideRegionNeedsRenderer(element, renderingParentNode, style))
212         return;
213
214     if (!style)
215         style = element.styleForRenderer();
216
217     RenderNamedFlowThread* parentFlowRenderer = 0;
218 #if ENABLE(CSS_REGIONS)
219     parentFlowRenderer = moveToFlowThreadIfNeeded(element, *style);
220 #endif
221
222     if (!element.rendererIsNeeded(*style))
223         return;
224
225     RenderElement* parentRenderer;
226     RenderObject* nextRenderer;
227     if (parentFlowRenderer) {
228         parentRenderer = parentFlowRenderer;
229         nextRenderer = parentFlowRenderer->nextRendererForElement(element);
230     } else {
231         // FIXME: Make this path Element only, handle the root special case separately.
232         parentRenderer = renderingParentNode->renderer();
233         nextRenderer = nextSiblingRenderer(element, renderingParentNode);
234     }
235
236     RenderElement* newRenderer = element.createElementRenderer(style.releaseNonNull()).leakPtr();
237     if (!newRenderer)
238         return;
239     if (!parentRenderer->isChildAllowed(*newRenderer, newRenderer->style())) {
240         newRenderer->destroy();
241         return;
242     }
243
244     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
245     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
246     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
247
248     // Code below updateAnimations() can depend on Element::renderer() already being set.
249     element.setRenderer(newRenderer);
250
251     // FIXME: There's probably a better way to factor this.
252     // This just does what setAnimatedStyle() does, except with setStyleInternal() instead of setStyle().
253     newRenderer->setStyleInternal(newRenderer->animation().updateAnimations(*newRenderer, newRenderer->style()));
254
255     newRenderer->initializeStyle();
256
257 #if ENABLE(FULLSCREEN_API)
258     Document& document = element.document();
259     if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
260         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
261         if (!newRenderer)
262             return;
263     }
264 #endif
265     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
266     parentRenderer->addChild(newRenderer, nextRenderer);
267 }
268
269 static RenderObject* previousSiblingRenderer(const Text& textNode)
270 {
271     if (textNode.renderer())
272         return textNode.renderer()->previousSibling();
273     for (Node* sibling = NodeRenderingTraversal::previousSibling(&textNode); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
274         RenderObject* renderer = sibling->renderer();
275         if (renderer && !isRendererReparented(renderer))
276             return renderer;
277     }
278     return 0;
279 }
280
281 static RenderObject* nextSiblingRenderer(const Text& textNode)
282 {
283     if (textNode.renderer())
284         return textNode.renderer()->nextSibling();
285     for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
286         RenderObject* renderer = sibling->renderer();
287         if (renderer && !isRendererReparented(renderer))
288             return renderer;
289     }
290     return 0;
291 }
292
293 static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current)
294 {
295     if (isInsertionPoint(current))
296         return;
297     // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
298     // the current node gaining or losing the renderer. This can only affect white space text nodes.
299     for (Node* sibling = NodeRenderingTraversal::nextSibling(&current); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
300         // Siblings haven't been attached yet. They will be handled normally when they are.
301         if (sibling->styleChangeType() == ReconstructRenderTree)
302             return;
303         if (sibling->isElementNode()) {
304             // Text renderers beyond rendered elements can't be affected.
305             if (!sibling->renderer() || isRendererReparented(sibling->renderer()))
306                 continue;
307             return;
308         }
309         if (!sibling->isTextNode())
310             continue;
311         Text& textSibling = *toText(sibling);
312         if (!textSibling.length() || !textSibling.containsOnlyWhitespace())
313             return;
314         Text& whitespaceTextSibling = textSibling;
315         bool hadRenderer = whitespaceTextSibling.renderer();
316         detachTextRenderer(whitespaceTextSibling);
317         attachTextRenderer(whitespaceTextSibling);
318         // No changes, futher renderers can't be affected.
319         if (hadRenderer == !!whitespaceTextSibling.renderer())
320             return;
321     }
322 }
323
324 static bool textRendererIsNeeded(const Text& textNode, const RenderObject& parentRenderer, const RenderStyle& style)
325 {
326     if (textNode.isEditingText())
327         return true;
328     if (!textNode.length())
329         return false;
330     if (style.display() == NONE)
331         return false;
332     if (!textNode.containsOnlyWhitespace())
333         return true;
334     // This text node has nothing but white space. We may still need a renderer in some cases.
335     if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet())
336         return false;
337     if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
338         return true;
339
340     RenderObject* previousRenderer = previousSiblingRenderer(textNode);
341     if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
342         return false;
343         
344     if (parentRenderer.isRenderInline()) {
345         // <span><div/> <div/></span>
346         if (previousRenderer && !previousRenderer->isInline())
347             return false;
348     } else {
349         if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline()))
350             return false;
351         
352         RenderObject* first = toRenderElement(parentRenderer).firstChild();
353         while (first && first->isFloatingOrOutOfFlowPositioned())
354             first = first->nextSibling();
355         RenderObject* nextRenderer = nextSiblingRenderer(textNode);
356         if (!first || nextRenderer == first) {
357             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
358             return false;
359         }
360     }
361     return true;
362 }
363
364 static void createTextRendererIfNeeded(Text& textNode)
365 {
366     ASSERT(!textNode.renderer());
367
368     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
369     if (!renderingParentNode)
370         return;
371     RenderElement* parentRenderer = renderingParentNode->renderer();
372     if (!parentRenderer || !parentRenderer->canHaveChildren())
373         return;
374     if (!renderingParentNode->childShouldCreateRenderer(textNode))
375         return;
376
377     const auto& style = parentRenderer->style();
378
379     if (!textRendererIsNeeded(textNode, *parentRenderer, style))
380         return;
381
382     auto newRenderer = textNode.createTextRenderer(style);
383     ASSERT(newRenderer);
384
385     if (!parentRenderer->isChildAllowed(*newRenderer, style))
386         return;
387
388     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
389     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
390     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
391
392     RenderObject* nextRenderer = nextSiblingRenderer(textNode);
393     textNode.setRenderer(newRenderer.get());
394     // Parent takes care of the animations, no need to call setAnimatableStyle.
395     parentRenderer->addChild(newRenderer.leakPtr(), nextRenderer);
396 }
397
398 void attachTextRenderer(Text& textNode)
399 {
400     createTextRendererIfNeeded(textNode);
401
402     textNode.clearNeedsStyleRecalc();
403 }
404
405 void detachTextRenderer(Text& textNode)
406 {
407     if (textNode.renderer())
408         textNode.renderer()->destroyAndCleanupAnonymousWrappers();
409     textNode.setRenderer(0);
410 }
411
412 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
413 {
414     RenderText* textRenderer = textNode.renderer();
415     if (!textRenderer) {
416         attachTextRenderer(textNode);
417         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
418         return;
419     }
420     RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer();
421     if (!textRendererIsNeeded(textNode, *parentRenderer, textRenderer->style())) {
422         detachTextRenderer(textNode);
423         attachTextRenderer(textNode);
424         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
425         return;
426     }
427     textRenderer->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
428 }
429
430 static void attachDistributedChildren(InsertionPoint& insertionPoint)
431 {
432     if (ShadowRoot* shadowRoot = insertionPoint.containingShadowRoot())
433         ContentDistributor::ensureDistribution(shadowRoot);
434     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
435         if (current->isTextNode()) {
436             if (current->renderer())
437                 continue;
438             attachTextRenderer(*toText(current));
439             continue;
440         }
441         if (current->isElementNode()) {
442             if (current->renderer())
443                 detachRenderTree(*toElement(current));
444             attachRenderTree(*toElement(current), nullptr);
445         }
446     }
447 }
448
449 static void attachChildren(ContainerNode& current)
450 {
451     if (isInsertionPoint(current))
452         attachDistributedChildren(toInsertionPoint(current));
453
454     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
455         ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot() || isInsertionPoint(current));
456         if (child->renderer())
457             continue;
458         if (child->isTextNode()) {
459             attachTextRenderer(*toText(child));
460             continue;
461         }
462         if (child->isElementNode())
463             attachRenderTree(*toElement(child), nullptr);
464     }
465 }
466
467 static void attachShadowRoot(ShadowRoot& shadowRoot)
468 {
469     attachChildren(shadowRoot);
470
471     shadowRoot.clearNeedsStyleRecalc();
472     shadowRoot.clearChildNeedsStyleRecalc();
473 }
474
475 static PseudoElement* beforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
476 {
477     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
478     if (pseudoId == BEFORE)
479         return current.beforePseudoElement();
480     return current.afterPseudoElement();
481 }
482
483 static void setBeforeOrAfterPseudoElement(Element& current, PassRefPtr<PseudoElement> pseudoElement, PseudoId pseudoId)
484 {
485     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
486     if (pseudoId == BEFORE) {
487         current.setBeforePseudoElement(pseudoElement);
488         return;
489     }
490     current.setAfterPseudoElement(pseudoElement);
491 }
492
493 static void clearBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
494 {
495     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
496     if (pseudoId == BEFORE) {
497         current.clearBeforePseudoElement();
498         return;
499     }
500     current.clearAfterPseudoElement();
501 }
502
503 static bool needsPseudeElement(Element& current, PseudoId pseudoId)
504 {
505     if (!current.document().styleSheetCollection().usesBeforeAfterRules())
506         return false;
507     if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren())
508         return false;
509     if (current.isPseudoElement())
510         return false;
511     if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId)))
512         return false;
513     return true;
514 }
515
516 static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId pseudoId)
517 {
518     if (!needsPseudeElement(current, pseudoId))
519         return;
520     RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
521     setBeforeOrAfterPseudoElement(current, pseudoElement, pseudoId);
522     attachRenderTree(*pseudoElement, nullptr);
523 }
524
525 static void attachRenderTree(Element& current, PassRefPtr<RenderStyle> resolvedStyle)
526 {
527     PostAttachCallbackDisabler callbackDisabler(current.document());
528     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
529
530     if (current.hasCustomStyleResolveCallbacks())
531         current.willAttachRenderers();
532
533     createRendererIfNeeded(current, resolvedStyle);
534
535     if (current.parentElement() && current.parentElement()->isInCanvasSubtree())
536         current.setIsInCanvasSubtree(true);
537
538     attachBeforeOrAfterPseudoElementIfNeeded(current, BEFORE);
539
540     StyleResolverParentPusher parentPusher(&current);
541
542     // When a shadow root exists, it does the work of attaching the children.
543     if (ShadowRoot* shadowRoot = current.shadowRoot()) {
544         parentPusher.push();
545         attachShadowRoot(*shadowRoot);
546     } else if (current.firstChild())
547         parentPusher.push();
548
549     attachChildren(current);
550
551     current.clearNeedsStyleRecalc();
552     current.clearChildNeedsStyleRecalc();
553
554     if (AXObjectCache* cache = current.document().axObjectCache())
555         cache->updateCacheAfterNodeIsAttached(&current);
556
557     attachBeforeOrAfterPseudoElementIfNeeded(current, AFTER);
558
559     current.updateFocusAppearanceAfterAttachIfNeeded();
560     
561     if (current.hasCustomStyleResolveCallbacks())
562         current.didAttachRenderers();
563 }
564
565 static void detachDistributedChildren(InsertionPoint& insertionPoint)
566 {
567     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
568         if (current->isTextNode()) {
569             detachTextRenderer(*toText(current));
570             continue;
571         }
572         if (current->isElementNode())
573             detachRenderTree(*toElement(current));
574     }
575 }
576
577 static void detachChildren(ContainerNode& current, DetachType detachType)
578 {
579     if (isInsertionPoint(current))
580         detachDistributedChildren(toInsertionPoint(current));
581
582     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
583         if (child->isTextNode()) {
584             Style::detachTextRenderer(*toText(child));
585             continue;
586         }
587         if (child->isElementNode())
588             detachRenderTree(*toElement(child), detachType);
589     }
590     current.clearChildNeedsStyleRecalc();
591 }
592
593 static void detachShadowRoot(ShadowRoot& shadowRoot, DetachType detachType)
594 {
595     detachChildren(shadowRoot, detachType);
596 }
597
598 static void detachRenderTree(Element& current, DetachType detachType)
599 {
600     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
601
602     if (current.hasCustomStyleResolveCallbacks())
603         current.willDetachRenderers();
604
605     current.clearStyleDerivedDataBeforeDetachingRenderer();
606
607     // Do not remove the element's hovered and active status
608     // if performing a reattach.
609     if (detachType != ReattachDetach)
610         current.clearHoverAndActiveStatusBeforeDetachingRenderer();
611
612     if (ShadowRoot* shadowRoot = current.shadowRoot())
613         detachShadowRoot(*shadowRoot, detachType);
614
615     detachChildren(current, detachType);
616
617     if (current.renderer())
618         current.renderer()->destroyAndCleanupAnonymousWrappers();
619     current.setRenderer(0);
620
621     if (current.hasCustomStyleResolveCallbacks())
622         current.didDetachRenderers();
623 }
624
625 static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
626 {
627     const RenderStyle& currentStyle = renderer->style();
628
629     const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles();
630     if (!pseudoStyleCache)
631         return false;
632
633     size_t cacheSize = pseudoStyleCache->size();
634     for (size_t i = 0; i < cacheSize; ++i) {
635         RefPtr<RenderStyle> newPseudoStyle;
636         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
637         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
638             newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
639         else
640             newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
641         if (!newPseudoStyle)
642             return true;
643         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
644             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
645                 newStyle->setHasPseudoStyle(pseudoId);
646             newStyle->addCachedPseudoStyle(newPseudoStyle);
647             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
648                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
649                 // is needed, but for now just assume a layout will be required. The diff code
650                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
651                 renderer->setNeedsLayoutAndPrefWidthsRecalc();
652             }
653             return true;
654         }
655     }
656     return false;
657 }
658
659 static Change resolveLocal(Element& current, Change inheritedChange)
660 {
661     Change localChange = Detach;
662     RefPtr<RenderStyle> newStyle;
663     RefPtr<RenderStyle> currentStyle = current.renderStyle();
664
665     Document& document = current.document();
666     if (currentStyle && current.styleChangeType() != ReconstructRenderTree) {
667         newStyle = current.styleForRenderer();
668         localChange = determineChange(currentStyle.get(), newStyle.get());
669     }
670     if (localChange == Detach) {
671         if (current.renderer() || current.inNamedFlow())
672             detachRenderTree(current, ReattachDetach);
673         attachRenderTree(current, newStyle.release());
674         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current);
675
676         return Detach;
677     }
678
679     if (RenderElement* renderer = current.renderer()) {
680         if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (inheritedChange == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
681             renderer->setAnimatableStyle(*newStyle);
682         else if (current.needsStyleRecalc()) {
683             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
684             // fooled into believing this style is the same.
685             renderer->setStyleInternal(*newStyle);
686         }
687     }
688
689     // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
690     // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
691     if (document.styleSheetCollection().usesRemUnits() && document.documentElement() == &current && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
692         // Cached RenderStyles may depend on the re units.
693         if (StyleResolver* styleResolver = document.styleResolverIfExists())
694             styleResolver->invalidateMatchedPropertiesCache();
695         return Force;
696     }
697     if (inheritedChange == Force)
698         return Force;
699     if (current.styleChangeType() >= FullStyleChange)
700         return Force;
701
702     return localChange;
703 }
704
705 static void updateTextStyle(Text& text)
706 {
707     RenderText* renderer = text.renderer();
708
709     if (!text.needsStyleRecalc())
710         return;
711     if (renderer)
712         renderer->setText(text.dataImpl());
713     else {
714         attachTextRenderer(text);
715         reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text);
716     }
717     text.clearNeedsStyleRecalc();
718 }
719
720 static void resolveShadowTree(ShadowRoot* shadowRoot, Style::Change change)
721 {
722     if (!shadowRoot)
723         return;
724
725     for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) {
726         if (child->isTextNode()) {
727             updateTextStyle(*toText(child));
728             continue;
729         }
730         if (child->isElementNode())
731             resolveTree(*toElement(child), change);
732     }
733
734     shadowRoot->clearNeedsStyleRecalc();
735     shadowRoot->clearChildNeedsStyleRecalc();
736 }
737
738 static void updateBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId)
739 {
740     if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
741         if (needsPseudeElement(current, pseudoId))
742             resolveTree(*existingPseudoElement, current.needsStyleRecalc() ? Force : change);
743         else
744             clearBeforeOrAfterPseudoElement(current, pseudoId);
745         return;
746     }
747     attachBeforeOrAfterPseudoElementIfNeeded(current, pseudoId);
748 }
749
750 #if PLATFORM(IOS)
751 static EVisibility elementImplicitVisibility(const Element* element)
752 {
753     RenderObject* renderer = element->renderer();
754     if (!renderer)
755         return VISIBLE;
756
757     RenderStyle& style = renderer->style();
758
759     Length width(style.width());
760     Length height(style.height());
761     if ((width.isFixed() && width.value() <= 0) || (height.isFixed() && height.value() <= 0))
762         return HIDDEN;
763
764     Length top(style.top());
765     Length left(style.left());
766     if (left.isFixed() && width.isFixed() && -left.value() >= width.value())
767         return HIDDEN;
768
769     if (top.isFixed() && height.isFixed() && -top.value() >= height.value())
770         return HIDDEN;
771     return VISIBLE;
772 }
773
774 class CheckForVisibilityChangeOnRecalcStyle {
775 public:
776     CheckForVisibilityChangeOnRecalcStyle(Element* element, RenderStyle* currentStyle)
777         : m_element(element)
778         , m_previousDisplay(currentStyle ? currentStyle->display() : NONE)
779         , m_previousVisibility(currentStyle ? currentStyle->visibility() : HIDDEN)
780         , m_previousImplicitVisibility(WKObservingContentChanges() && WKContentChange() != WKContentVisibilityChange ? elementImplicitVisibility(element) : VISIBLE)
781     {
782     }
783     ~CheckForVisibilityChangeOnRecalcStyle()
784     {
785         if (!WKObservingContentChanges())
786             return;
787         RenderStyle* style = m_element->renderStyle();
788         if (!style)
789             return;
790         if ((m_previousDisplay == NONE && style->display() != NONE) || (m_previousVisibility == HIDDEN && style->visibility() != HIDDEN)
791             || (m_previousImplicitVisibility == HIDDEN && elementImplicitVisibility(m_element.get()) == VISIBLE))
792             WKSetObservedContentChange(WKContentVisibilityChange);
793     }
794 private:
795     RefPtr<Element> m_element;
796     EDisplay m_previousDisplay;
797     EVisibility m_previousVisibility;
798     EVisibility m_previousImplicitVisibility;
799 };
800 #endif // PLATFORM(IOS)
801
802 void resolveTree(Element& current, Change change)
803 {
804     ASSERT(change != Detach);
805
806     if (current.hasCustomStyleResolveCallbacks()) {
807         if (!current.willRecalcStyle(change))
808             return;
809     }
810
811     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&current);
812     bool hasParentStyle = renderingParentNode && renderingParentNode->renderStyle();
813     bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
814     bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
815
816 #if PLATFORM(IOS)
817     CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&current, current.renderStyle());
818 #endif
819
820     if (change > NoChange || current.needsStyleRecalc())
821         current.resetComputedStyle();
822
823     if (hasParentStyle && (change >= Inherit || current.needsStyleRecalc()))
824         change = resolveLocal(current, change);
825
826     if (change != Detach) {
827         StyleResolverParentPusher parentPusher(&current);
828
829         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
830             if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
831                 parentPusher.push();
832                 resolveShadowTree(shadowRoot, change);
833             }
834         }
835
836         updateBeforeOrAfterPseudoElement(current, change, BEFORE);
837
838         // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
839         // For now we will just worry about the common case, since it's a lot trickier to get the second case right
840         // without doing way too much re-resolution.
841         bool forceCheckOfNextElementSibling = false;
842         bool forceCheckOfAnyElementSibling = false;
843         for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
844             if (child->isTextNode()) {
845                 updateTextStyle(*toText(child));
846                 continue;
847             }
848             if (!child->isElementNode())
849                 continue;
850             Element* childElement = toElement(child);
851             bool childRulesChanged = childElement->needsStyleRecalc() && childElement->styleChangeType() == FullStyleChange;
852             if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
853                 childElement->setNeedsStyleRecalc();
854             if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
855                 parentPusher.push();
856                 resolveTree(*childElement, change);
857             }
858             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
859             forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
860         }
861
862         updateBeforeOrAfterPseudoElement(current, change, AFTER);
863     }
864
865     current.clearNeedsStyleRecalc();
866     current.clearChildNeedsStyleRecalc();
867     
868     if (current.hasCustomStyleResolveCallbacks())
869         current.didRecalcStyle(change);
870 }
871
872 void resolveTree(Document& document, Change change)
873 {
874     if (change == Force) {
875         auto documentStyle = resolveForDocument(document);
876
877         // Inserting the pictograph font at the end of the font fallback list is done by the
878         // font selector, so set a font selector if needed.
879         if (Settings* settings = document.settings()) {
880             StyleResolver* styleResolver = document.styleResolverIfExists();
881             if (settings->fontFallbackPrefersPictographs() && styleResolver)
882                 documentStyle.get().font().update(styleResolver->fontSelector());
883         }
884
885         Style::Change documentChange = determineChange(&documentStyle.get(), &document.renderView()->style());
886         if (documentChange != NoChange)
887             document.renderView()->setStyle(std::move(documentStyle));
888         else
889             documentStyle.dropRef();
890     }
891
892     Element* documentElement = document.documentElement();
893     if (!documentElement)
894         return;
895     if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
896         return;
897     resolveTree(*documentElement, change);
898 }
899
900 void detachRenderTree(Element& element)
901 {
902     detachRenderTree(element, NormalDetach);
903 }
904
905 }
906 }