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