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