[CSS Grid Layout] Upgrade align-self and align-items parsing to CSS 3
[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-2010, 2012-2014 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 "ElementIterator.h"
33 #include "ElementRareData.h"
34 #include "FlowThreadController.h"
35 #include "InsertionPoint.h"
36 #include "LoaderStrategy.h"
37 #include "MainFrame.h"
38 #include "NodeRenderStyle.h"
39 #include "NodeRenderingTraversal.h"
40 #include "NodeTraversal.h"
41 #include "PlatformStrategies.h"
42 #include "RenderFullScreen.h"
43 #include "RenderNamedFlowThread.h"
44 #include "RenderText.h"
45 #include "RenderView.h"
46 #include "RenderWidget.h"
47 #include "ResourceLoadScheduler.h"
48 #include "Settings.h"
49 #include "ShadowRoot.h"
50 #include "StyleResolveForDocument.h"
51 #include "StyleResolver.h"
52 #include "Text.h"
53
54 #if PLATFORM(IOS)
55 #include "CSSFontSelector.h"
56 #include "WKContentObservation.h"
57 #endif
58
59 namespace WebCore {
60
61 namespace Style {
62
63 enum DetachType { NormalDetach, ReattachDetach };
64
65 class RenderTreePosition {
66 public:
67     explicit RenderTreePosition(RenderView&);
68     explicit RenderTreePosition(RenderElement& parent);
69     RenderTreePosition(RenderElement& parent, RenderObject* nextSibling);
70
71     RenderElement& parent() { return m_parent; }
72     const RenderElement& parent() const { return m_parent; }
73
74     void insert(RenderObject&);
75     bool canInsert(RenderElement&) const;
76     bool canInsert(RenderText&) const;
77
78     void computeNextSibling(const Node&);
79     void invalidateNextSibling(const RenderObject&);
80
81 private:
82     RenderElement& m_parent;
83     RenderObject* m_nextSibling;
84     bool m_hasValidNextSibling;
85 #if !ASSERT_DISABLED
86     unsigned m_assertionLimitCounter;
87 #endif
88 };
89
90 static void attachRenderTree(Element&, RenderStyle& inheritedStyle, RenderTreePosition&, PassRefPtr<RenderStyle>);
91 static void attachTextRenderer(Text&, RenderTreePosition&);
92 static void detachRenderTree(Element&, DetachType);
93 static void resolveTextNode(Text&, RenderTreePosition&);
94 static void resolveTree(Element&, RenderStyle& inheritedStyle, RenderTreePosition&, Change);
95
96 Change determineChange(const RenderStyle& s1, const RenderStyle& s2)
97 {
98     if (s1.display() != s2.display())
99         return Detach;
100     if (s1.hasPseudoStyle(FIRST_LETTER) != s2.hasPseudoStyle(FIRST_LETTER))
101         return Detach;
102     // We just detach if a renderer acquires or loses a column-span, since spanning elements
103     // typically won't contain much content.
104     if (s1.columnSpan() != s2.columnSpan())
105         return Detach;
106     if (!s1.contentDataEquivalent(&s2))
107         return Detach;
108     // When text-combine property has been changed, we need to prepare a separate renderer object.
109     // When text-combine is on, we use RenderCombineText, otherwise RenderText.
110     // https://bugs.webkit.org/show_bug.cgi?id=55069
111     if (s1.hasTextCombine() != s2.hasTextCombine())
112         return Detach;
113     // We need to reattach the node, so that it is moved to the correct RenderFlowThread.
114     if (s1.flowThread() != s2.flowThread())
115         return Detach;
116     // When the region thread has changed, we need to prepare a separate render region object.
117     if (s1.regionThread() != s2.regionThread())
118         return Detach;
119     // FIXME: Multicolumn regions not yet supported (http://dev.w3.org/csswg/css-regions/#multi-column-regions)
120     // When the node has region style and changed its multicol style, we have to prepare
121     // a separate render region object.
122     if (s1.hasFlowFrom() && (s1.specifiesColumns() != s2.specifiesColumns()))
123         return Detach;
124     if (s1.alignItems() != s2.alignItems())
125         return Detach;
126
127     if (s1 != s2) {
128         if (s1.inheritedNotEqual(&s2))
129             return Inherit;
130         if (s1.hasExplicitlyInheritedProperties() || s2.hasExplicitlyInheritedProperties())
131             return Inherit;
132
133         return NoInherit;
134     }
135     // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
136     // because setStyle will do the right thing with anything else.
137     if (s1.hasAnyPublicPseudoStyles()) {
138         for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
139             if (s1.hasPseudoStyle(pseudoId)) {
140                 RenderStyle* ps2 = s2.getCachedPseudoStyle(pseudoId);
141                 if (!ps2)
142                     return NoInherit;
143                 RenderStyle* ps1 = s1.getCachedPseudoStyle(pseudoId);
144                 if (!ps1 || *ps1 != *ps2)
145                     return NoInherit;
146             }
147         }
148     }
149
150     return NoChange;
151 }
152
153 static bool isRendererReparented(const RenderObject* renderer)
154 {
155     if (!renderer->node()->isElementNode())
156         return false;
157     if (renderer->style().hasFlowInto())
158         return true;
159     return false;
160 }
161
162 static RenderObject* nextSiblingRenderer(const Node& node, const RenderElement& parentRenderer)
163 {
164     if (!parentRenderer.element())
165         return nullptr;
166     if (node.isAfterPseudoElement())
167         return nullptr;
168     Node* sibling = node.isBeforePseudoElement() ? NodeRenderingTraversal::firstChild(parentRenderer.element()) : NodeRenderingTraversal::nextSibling(&node);
169     for (; sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
170         RenderObject* renderer = sibling->renderer();
171         if (renderer && !isRendererReparented(renderer))
172             return renderer;
173     }
174     if (PseudoElement* after = parentRenderer.element()->afterPseudoElement())
175         return after->renderer();
176     return nullptr;
177 }
178
179 RenderTreePosition::RenderTreePosition(RenderView& root)
180     : m_parent(root)
181     , m_nextSibling(nullptr)
182     , m_hasValidNextSibling(true)
183 #if !ASSERT_DISABLED
184     , m_assertionLimitCounter(0)
185 #endif
186 {
187 }
188
189 RenderTreePosition::RenderTreePosition(RenderElement& parent)
190     : m_parent(parent)
191     , m_nextSibling(nullptr)
192     , m_hasValidNextSibling(false)
193 #if !ASSERT_DISABLED
194     , m_assertionLimitCounter(0)
195 #endif
196 {
197 }
198
199 RenderTreePosition::RenderTreePosition(RenderElement& parent, RenderObject* nextSibling)
200     : m_parent(parent)
201     , m_nextSibling(nextSibling)
202     , m_hasValidNextSibling(true)
203 #if !ASSERT_DISABLED
204     , m_assertionLimitCounter(0)
205 #endif
206 {
207 }
208
209 bool RenderTreePosition::canInsert(RenderElement& renderer) const
210 {
211     ASSERT(!renderer.parent());
212     return m_parent.isChildAllowed(renderer, renderer.style());
213 }
214
215 bool RenderTreePosition::canInsert(RenderText& renderer) const
216 {
217     ASSERT(!renderer.parent());
218     return m_parent.isChildAllowed(renderer, m_parent.style());
219 }
220
221 void RenderTreePosition::insert(RenderObject& renderer)
222 {
223     ASSERT(m_hasValidNextSibling);
224     m_parent.addChild(&renderer, m_nextSibling);
225 }
226
227 void RenderTreePosition::computeNextSibling(const Node& node)
228 {
229     ASSERT(!node.renderer());
230     if (m_hasValidNextSibling) {
231         // Stop validating at some point so the assert doesn't make us O(N^2) on debug builds.
232         ASSERT(m_parent.isRenderView() || ++m_assertionLimitCounter > 20 || nextSiblingRenderer(node, m_parent) == m_nextSibling);
233         return;
234     }
235     m_nextSibling = nextSiblingRenderer(node, m_parent);
236     m_hasValidNextSibling = true;
237 }
238
239 void RenderTreePosition::invalidateNextSibling(const RenderObject& siblingRenderer)
240 {
241     if (!m_hasValidNextSibling)
242         return;
243     if (m_nextSibling == &siblingRenderer)
244         m_hasValidNextSibling = false;
245 }
246
247 static bool shouldCreateRenderer(const Element& element, const RenderElement& parentRenderer)
248 {
249     if (!element.document().shouldCreateRenderers())
250         return false;
251     if (!parentRenderer.canHaveChildren() && !(element.isPseudoElement() && parentRenderer.canHaveGeneratedChildren()))
252         return false;
253     if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(element))
254         return false;
255     return true;
256 }
257
258 static PassRef<RenderStyle> styleForElement(Element& element, RenderStyle& inheritedStyle)
259 {
260     if (element.hasCustomStyleResolveCallbacks()) {
261         if (RefPtr<RenderStyle> style = element.customStyleForRenderer(inheritedStyle))
262             return style.releaseNonNull();
263     }
264     return element.document().ensureStyleResolver().styleForElement(&element, &inheritedStyle);
265 }
266
267 #if ENABLE(CSS_REGIONS)
268 static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
269 {
270     if (!element.shouldMoveToFlowThread(style))
271         return 0;
272
273     FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController();
274     RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
275     flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer);
276     return &parentFlowRenderer;
277 }
278 #endif
279
280 static void createRendererIfNeeded(Element& element, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, PassRefPtr<RenderStyle> resolvedStyle)
281 {
282     ASSERT(!element.renderer());
283
284     RefPtr<RenderStyle> style = resolvedStyle;
285
286     if (!shouldCreateRenderer(element, renderTreePosition.parent()))
287         return;
288
289     if (!style)
290         style = styleForElement(element, inheritedStyle);
291
292     RenderNamedFlowThread* parentFlowRenderer = 0;
293 #if ENABLE(CSS_REGIONS)
294     parentFlowRenderer = moveToFlowThreadIfNeeded(element, *style);
295 #endif
296
297     if (!element.rendererIsNeeded(*style))
298         return;
299
300     renderTreePosition.computeNextSibling(element);
301
302     RenderTreePosition insertionPosition = parentFlowRenderer
303         ? RenderTreePosition(*parentFlowRenderer, parentFlowRenderer->nextRendererForElement(element))
304         : renderTreePosition;
305
306     RenderElement* newRenderer = element.createElementRenderer(style.releaseNonNull()).leakPtr();
307     if (!newRenderer)
308         return;
309     if (!insertionPosition.canInsert(*newRenderer)) {
310         newRenderer->destroy();
311         return;
312     }
313
314     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
315     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
316     newRenderer->setFlowThreadState(insertionPosition.parent().flowThreadState());
317
318     // Code below updateAnimations() can depend on Element::renderer() already being set.
319     element.setRenderer(newRenderer);
320
321     // FIXME: There's probably a better way to factor this.
322     // This just does what setAnimatedStyle() does, except with setStyleInternal() instead of setStyle().
323     newRenderer->setStyleInternal(newRenderer->animation().updateAnimations(*newRenderer, newRenderer->style()));
324
325     newRenderer->initializeStyle();
326
327 #if ENABLE(FULLSCREEN_API)
328     Document& document = element.document();
329     if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
330         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, &insertionPosition.parent(), document);
331         if (!newRenderer)
332             return;
333     }
334 #endif
335     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
336     insertionPosition.insert(*newRenderer);
337 }
338
339 static RenderObject* previousSiblingRenderer(const Text& textNode)
340 {
341     if (textNode.renderer())
342         return textNode.renderer()->previousSibling();
343     for (Node* sibling = NodeRenderingTraversal::previousSibling(&textNode); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
344         RenderObject* renderer = sibling->renderer();
345         if (renderer && !isRendererReparented(renderer))
346             return renderer;
347     }
348     if (PseudoElement* before = textNode.parentElement()->beforePseudoElement())
349         return before->renderer();
350     return nullptr;
351 }
352
353 static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current)
354 {
355     if (is<InsertionPoint>(current))
356         return;
357     // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
358     // the current node gaining or losing the renderer. This can only affect white space text nodes.
359     for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) {
360         if (sibling->needsStyleRecalc())
361             return;
362         if (is<Element>(*sibling)) {
363             // Text renderers beyond rendered elements can't be affected.
364             if (!sibling->renderer() || isRendererReparented(sibling->renderer()))
365                 continue;
366             return;
367         }
368         if (!is<Text>(*sibling))
369             continue;
370         Text& textSibling = downcast<Text>(*sibling);
371         if (!textSibling.containsOnlyWhitespace())
372             continue;
373         textSibling.setNeedsStyleRecalc();
374     }
375 }
376
377 static bool textRendererIsNeeded(const Text& textNode, const RenderTreePosition& renderTreePosition)
378 {
379     const RenderElement& parentRenderer = renderTreePosition.parent();
380     if (!parentRenderer.canHaveChildren())
381         return false;
382     if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(textNode))
383         return false;
384     if (textNode.isEditingText())
385         return true;
386     if (!textNode.length())
387         return false;
388     if (!textNode.containsOnlyWhitespace())
389         return true;
390     // This text node has nothing but white space. We may still need a renderer in some cases.
391     if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet())
392         return false;
393     if (parentRenderer.style().preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
394         return true;
395
396     RenderObject* previousRenderer = previousSiblingRenderer(textNode);
397     if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
398         return false;
399         
400     if (parentRenderer.isRenderInline()) {
401         // <span><div/> <div/></span>
402         if (previousRenderer && !previousRenderer->isInline())
403             return false;
404     } else {
405         if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline()))
406             return false;
407         
408         RenderObject* first = parentRenderer.firstChild();
409         while (first && first->isFloatingOrOutOfFlowPositioned())
410             first = first->nextSibling();
411         RenderObject* nextRenderer = nextSiblingRenderer(textNode, parentRenderer);
412         if (!first || nextRenderer == first) {
413             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
414             return false;
415         }
416     }
417     return true;
418 }
419
420 static void createTextRendererIfNeeded(Text& textNode, RenderTreePosition& renderTreePosition)
421 {
422     ASSERT(!textNode.renderer());
423
424     if (!textRendererIsNeeded(textNode, renderTreePosition))
425         return;
426
427     auto newRenderer = textNode.createTextRenderer(renderTreePosition.parent().style());
428     ASSERT(newRenderer);
429
430     renderTreePosition.computeNextSibling(textNode);
431
432     if (!renderTreePosition.canInsert(*newRenderer))
433         return;
434
435     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
436     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
437     newRenderer->setFlowThreadState(renderTreePosition.parent().flowThreadState());
438
439     textNode.setRenderer(newRenderer.get());
440     // Parent takes care of the animations, no need to call setAnimatableStyle.
441     renderTreePosition.insert(*newRenderer.leakPtr());
442 }
443
444 void attachTextRenderer(Text& textNode, RenderTreePosition& renderTreePosition)
445 {
446     createTextRendererIfNeeded(textNode, renderTreePosition);
447
448     textNode.clearNeedsStyleRecalc();
449 }
450
451 void detachTextRenderer(Text& textNode)
452 {
453     if (textNode.renderer())
454         textNode.renderer()->destroyAndCleanupAnonymousWrappers();
455     textNode.setRenderer(0);
456 }
457
458 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
459 {
460     ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
461     if (!renderingParentNode || !renderingParentNode->renderer())
462         return;
463
464     bool hadRenderer = textNode.renderer();
465
466     RenderTreePosition renderTreePosition(*renderingParentNode->renderer());
467     resolveTextNode(textNode, renderTreePosition);
468
469     if (hadRenderer && textNode.renderer())
470         textNode.renderer()->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
471 }
472
473 static void attachChildren(ContainerNode& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition)
474 {
475     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
476         ASSERT((!child->renderer() || child->isNamedFlowContentNode()) || current.shadowRoot());
477         if (child->renderer()) {
478             renderTreePosition.invalidateNextSibling(*child->renderer());
479             continue;
480         }
481         if (is<Text>(*child)) {
482             attachTextRenderer(downcast<Text>(*child), renderTreePosition);
483             continue;
484         }
485         if (is<Element>(*child))
486             attachRenderTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
487     }
488 }
489
490 static void attachDistributedChildren(InsertionPoint& insertionPoint, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition)
491 {
492     if (ShadowRoot* shadowRoot = insertionPoint.containingShadowRoot())
493         ContentDistributor::ensureDistribution(shadowRoot);
494
495     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
496         if (current->renderer())
497             renderTreePosition.invalidateNextSibling(*current->renderer());
498         if (is<Text>(*current)) {
499             if (current->renderer())
500                 continue;
501             attachTextRenderer(downcast<Text>(*current), renderTreePosition);
502             continue;
503         }
504         if (is<Element>(*current)) {
505             Element& currentElement = downcast<Element>(*current);
506             if (currentElement.renderer())
507                 detachRenderTree(currentElement);
508             attachRenderTree(currentElement, inheritedStyle, renderTreePosition, nullptr);
509         }
510     }
511     // Use actual children as fallback content.
512     if (!insertionPoint.hasDistribution())
513         attachChildren(insertionPoint, inheritedStyle, renderTreePosition);
514 }
515
516 static void attachShadowRoot(ShadowRoot& shadowRoot)
517 {
518     ASSERT(shadowRoot.hostElement());
519     ASSERT(shadowRoot.hostElement()->renderer());
520
521     auto& renderer = *shadowRoot.hostElement()->renderer();
522     RenderTreePosition renderTreePosition(renderer);
523     attachChildren(shadowRoot, renderer.style(), renderTreePosition);
524
525     shadowRoot.clearNeedsStyleRecalc();
526     shadowRoot.clearChildNeedsStyleRecalc();
527 }
528
529 static PseudoElement* beforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
530 {
531     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
532     if (pseudoId == BEFORE)
533         return current.beforePseudoElement();
534     return current.afterPseudoElement();
535 }
536
537 static void setBeforeOrAfterPseudoElement(Element& current, PassRefPtr<PseudoElement> pseudoElement, PseudoId pseudoId)
538 {
539     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
540     if (pseudoId == BEFORE) {
541         current.setBeforePseudoElement(pseudoElement);
542         return;
543     }
544     current.setAfterPseudoElement(pseudoElement);
545 }
546
547 static void clearBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
548 {
549     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
550     if (pseudoId == BEFORE) {
551         current.clearBeforePseudoElement();
552         return;
553     }
554     current.clearAfterPseudoElement();
555 }
556
557 static void resetStyleForNonRenderedDescendants(Element& current)
558 {
559     ASSERT(!current.renderer());
560     bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
561     for (auto& child : childrenOfType<Element>(current)) {
562         ASSERT(!child.renderer());
563         if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
564             if (child.styleIsAffectedByPreviousSibling())
565                 child.setNeedsStyleRecalc();
566             elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
567         }
568
569         if (child.needsStyleRecalc()) {
570             child.resetComputedStyle();
571             child.clearNeedsStyleRecalc();
572             elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
573         }
574
575         if (child.childNeedsStyleRecalc()) {
576             resetStyleForNonRenderedDescendants(child);
577             child.clearChildNeedsStyleRecalc();
578         }
579     }
580 }
581
582 static bool needsPseudoElement(Element& current, PseudoId pseudoId)
583 {
584     if (!current.document().styleSheetCollection().usesBeforeAfterRules())
585         return false;
586     if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren())
587         return false;
588     if (current.isPseudoElement())
589         return false;
590     if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId)))
591         return false;
592     return true;
593 }
594
595 static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
596 {
597     if (!needsPseudoElement(current, pseudoId))
598         return;
599     RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
600     setBeforeOrAfterPseudoElement(current, pseudoElement, pseudoId);
601     attachRenderTree(*pseudoElement, *current.renderStyle(), renderTreePosition, nullptr);
602 }
603
604 static void attachRenderTree(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, PassRefPtr<RenderStyle> resolvedStyle)
605 {
606     PostResolutionCallbackDisabler callbackDisabler(current.document());
607     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
608
609     if (is<InsertionPoint>(current)) {
610         attachDistributedChildren(downcast<InsertionPoint>(current), inheritedStyle, renderTreePosition);
611         current.clearNeedsStyleRecalc();
612         current.clearChildNeedsStyleRecalc();
613         return;
614     }
615
616     if (current.hasCustomStyleResolveCallbacks())
617         current.willAttachRenderers();
618
619     createRendererIfNeeded(current, inheritedStyle, renderTreePosition, resolvedStyle);
620
621     if (auto* renderer = current.renderer()) {
622         StyleResolverParentPusher parentPusher(&current);
623
624         RenderTreePosition childRenderTreePosition(*renderer);
625         attachBeforeOrAfterPseudoElementIfNeeded(current, BEFORE, childRenderTreePosition);
626
627         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
628             parentPusher.push();
629             attachShadowRoot(*shadowRoot);
630         } else if (current.firstChild())
631             parentPusher.push();
632
633         attachChildren(current, renderer->style(), childRenderTreePosition);
634
635         if (AXObjectCache* cache = current.document().axObjectCache())
636             cache->updateCacheAfterNodeIsAttached(&current);
637
638         attachBeforeOrAfterPseudoElementIfNeeded(current, AFTER, childRenderTreePosition);
639
640         current.updateFocusAppearanceAfterAttachIfNeeded();
641     } else
642         resetStyleForNonRenderedDescendants(current);
643
644     current.clearNeedsStyleRecalc();
645     current.clearChildNeedsStyleRecalc();
646
647     if (current.hasCustomStyleResolveCallbacks())
648         current.didAttachRenderers();
649 }
650
651 static void detachDistributedChildren(InsertionPoint& insertionPoint)
652 {
653     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
654         if (is<Text>(*current)) {
655             detachTextRenderer(downcast<Text>(*current));
656             continue;
657         }
658         if (is<Element>(*current))
659             detachRenderTree(downcast<Element>(*current));
660     }
661 }
662
663 static void detachChildren(ContainerNode& current, DetachType detachType)
664 {
665     if (is<InsertionPoint>(current))
666         detachDistributedChildren(downcast<InsertionPoint>(current));
667
668     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
669         if (is<Text>(*child)) {
670             Style::detachTextRenderer(downcast<Text>(*child));
671             continue;
672         }
673         if (is<Element>(*child))
674             detachRenderTree(downcast<Element>(*child), detachType);
675     }
676     current.clearChildNeedsStyleRecalc();
677 }
678
679 static void detachShadowRoot(ShadowRoot& shadowRoot, DetachType detachType)
680 {
681     detachChildren(shadowRoot, detachType);
682 }
683
684 static void detachRenderTree(Element& current, DetachType detachType)
685 {
686     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
687
688     if (current.hasCustomStyleResolveCallbacks())
689         current.willDetachRenderers();
690
691     current.clearStyleDerivedDataBeforeDetachingRenderer();
692
693     // Do not remove the element's hovered and active status
694     // if performing a reattach.
695     if (detachType != ReattachDetach)
696         current.clearHoverAndActiveStatusBeforeDetachingRenderer();
697
698     if (ShadowRoot* shadowRoot = current.shadowRoot())
699         detachShadowRoot(*shadowRoot, detachType);
700
701     detachChildren(current, detachType);
702
703     if (current.renderer())
704         current.renderer()->destroyAndCleanupAnonymousWrappers();
705     current.setRenderer(0);
706
707     if (current.hasCustomStyleResolveCallbacks())
708         current.didDetachRenderers();
709 }
710
711 static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
712 {
713     const RenderStyle& currentStyle = renderer->style();
714
715     const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles();
716     if (!pseudoStyleCache)
717         return false;
718
719     size_t cacheSize = pseudoStyleCache->size();
720     for (size_t i = 0; i < cacheSize; ++i) {
721         RefPtr<RenderStyle> newPseudoStyle;
722         PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
723         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
724             newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
725         else
726             newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
727         if (!newPseudoStyle)
728             return true;
729         if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
730             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
731                 newStyle->setHasPseudoStyle(pseudoId);
732             newStyle->addCachedPseudoStyle(newPseudoStyle);
733             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
734                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
735                 // is needed, but for now just assume a layout will be required. The diff code
736                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
737                 renderer->setNeedsLayoutAndPrefWidthsRecalc();
738             }
739             return true;
740         }
741     }
742     return false;
743 }
744
745 static Change resolveLocal(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change inheritedChange)
746 {
747     Change localChange = Detach;
748     RefPtr<RenderStyle> newStyle;
749     RefPtr<RenderStyle> currentStyle = current.renderStyle();
750
751     Document& document = current.document();
752     if (currentStyle && current.styleChangeType() != ReconstructRenderTree) {
753         Ref<RenderStyle> style(styleForElement(current, inheritedStyle));
754         newStyle = style.ptr();
755         localChange = determineChange(*currentStyle, style);
756     }
757     if (localChange == Detach) {
758         if (current.renderer() || current.isNamedFlowContentNode())
759             detachRenderTree(current, ReattachDetach);
760         attachRenderTree(current, inheritedStyle, renderTreePosition, newStyle.release());
761         invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(current);
762
763         return Detach;
764     }
765
766     if (RenderElement* renderer = current.renderer()) {
767         if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (inheritedChange == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
768             renderer->setAnimatableStyle(*newStyle);
769         else if (current.needsStyleRecalc()) {
770             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
771             // fooled into believing this style is the same.
772             renderer->setStyleInternal(*newStyle);
773         }
774     }
775
776     // 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
777     // 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).
778     if (document.styleSheetCollection().usesRemUnits() && document.documentElement() == &current && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
779         // Cached RenderStyles may depend on the re units.
780         if (StyleResolver* styleResolver = document.styleResolverIfExists())
781             styleResolver->invalidateMatchedPropertiesCache();
782         return Force;
783     }
784     if (inheritedChange == Force)
785         return Force;
786     if (current.styleChangeType() >= FullStyleChange)
787         return Force;
788
789     return localChange;
790 }
791
792 void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition)
793 {
794     text.clearNeedsStyleRecalc();
795
796     bool hasRenderer = text.renderer();
797     bool needsRenderer = textRendererIsNeeded(text, renderTreePosition);
798     if (hasRenderer) {
799         if (needsRenderer)
800             return;
801         detachTextRenderer(text);
802         invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
803         return;
804     }
805     if (!needsRenderer)
806         return;
807     attachTextRenderer(text, renderTreePosition);
808     invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
809 }
810
811 static void resolveShadowTree(ShadowRoot& shadowRoot, Element& host, Style::Change change)
812 {
813     ASSERT(shadowRoot.hostElement() == &host);
814     ASSERT(host.renderer());
815     RenderTreePosition renderTreePosition(*host.renderer());
816     for (Node* child = shadowRoot.firstChild(); child; child = child->nextSibling()) {
817         if (child->renderer())
818             renderTreePosition.invalidateNextSibling(*child->renderer());
819         if (is<Text>(*child) && child->needsStyleRecalc()) {
820             resolveTextNode(downcast<Text>(*child), renderTreePosition);
821             continue;
822         }
823         if (is<Element>(*child))
824             resolveTree(downcast<Element>(*child), host.renderer()->style(), renderTreePosition, change);
825     }
826
827     shadowRoot.clearNeedsStyleRecalc();
828     shadowRoot.clearChildNeedsStyleRecalc();
829 }
830
831 static void updateBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
832 {
833     ASSERT(current.renderer());
834     if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
835         if (existingPseudoElement->renderer())
836             renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer());
837
838         if (needsPseudoElement(current, pseudoId))
839             resolveTree(*existingPseudoElement, current.renderer()->style(), renderTreePosition, current.needsStyleRecalc() ? Force : change);
840         else
841             clearBeforeOrAfterPseudoElement(current, pseudoId);
842         return;
843     }
844     attachBeforeOrAfterPseudoElementIfNeeded(current, pseudoId, renderTreePosition);
845 }
846
847 #if PLATFORM(IOS)
848 static EVisibility elementImplicitVisibility(const Element* element)
849 {
850     RenderObject* renderer = element->renderer();
851     if (!renderer)
852         return VISIBLE;
853
854     RenderStyle& style = renderer->style();
855
856     Length width(style.width());
857     Length height(style.height());
858     if ((width.isFixed() && width.value() <= 0) || (height.isFixed() && height.value() <= 0))
859         return HIDDEN;
860
861     Length top(style.top());
862     Length left(style.left());
863     if (left.isFixed() && width.isFixed() && -left.value() >= width.value())
864         return HIDDEN;
865
866     if (top.isFixed() && height.isFixed() && -top.value() >= height.value())
867         return HIDDEN;
868     return VISIBLE;
869 }
870
871 class CheckForVisibilityChangeOnRecalcStyle {
872 public:
873     CheckForVisibilityChangeOnRecalcStyle(Element* element, RenderStyle* currentStyle)
874         : m_element(element)
875         , m_previousDisplay(currentStyle ? currentStyle->display() : NONE)
876         , m_previousVisibility(currentStyle ? currentStyle->visibility() : HIDDEN)
877         , m_previousImplicitVisibility(WKObservingContentChanges() && WKContentChange() != WKContentVisibilityChange ? elementImplicitVisibility(element) : VISIBLE)
878     {
879     }
880     ~CheckForVisibilityChangeOnRecalcStyle()
881     {
882         if (!WKObservingContentChanges())
883             return;
884         RenderStyle* style = m_element->renderStyle();
885         if (!style)
886             return;
887         if ((m_previousDisplay == NONE && style->display() != NONE) || (m_previousVisibility == HIDDEN && style->visibility() != HIDDEN)
888             || (m_previousImplicitVisibility == HIDDEN && elementImplicitVisibility(m_element.get()) == VISIBLE))
889             WKSetObservedContentChange(WKContentVisibilityChange);
890     }
891 private:
892     RefPtr<Element> m_element;
893     EDisplay m_previousDisplay;
894     EVisibility m_previousVisibility;
895     EVisibility m_previousImplicitVisibility;
896 };
897 #endif // PLATFORM(IOS)
898
899 void resolveTree(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
900 {
901     ASSERT(change != Detach);
902
903     if (is<InsertionPoint>(current)) {
904         current.clearNeedsStyleRecalc();
905         current.clearChildNeedsStyleRecalc();
906         return;
907     }
908
909     if (current.hasCustomStyleResolveCallbacks()) {
910         if (!current.willRecalcStyle(change))
911             return;
912     }
913
914 #if PLATFORM(IOS)
915     CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&current, current.renderStyle());
916 #endif
917
918     if (change > NoChange || current.needsStyleRecalc())
919         current.resetComputedStyle();
920
921     if (change >= Inherit || current.needsStyleRecalc())
922         change = resolveLocal(current, inheritedStyle, renderTreePosition, change);
923
924     auto* renderer = current.renderer();
925
926     if (change != Detach && renderer) {
927         StyleResolverParentPusher parentPusher(&current);
928
929         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
930             if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
931                 parentPusher.push();
932                 resolveShadowTree(*shadowRoot, current, change);
933             }
934         }
935
936         RenderTreePosition childRenderTreePosition(*renderer);
937         updateBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition);
938
939         bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
940         for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
941             if (RenderObject* childRenderer = child->renderer())
942                 childRenderTreePosition.invalidateNextSibling(*childRenderer);
943             if (is<Text>(*child) && child->needsStyleRecalc()) {
944                 resolveTextNode(downcast<Text>(*child), childRenderTreePosition);
945                 continue;
946             }
947             if (!is<Element>(*child))
948                 continue;
949
950             Element& childElement = downcast<Element>(*child);
951             if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
952                 if (childElement.styleIsAffectedByPreviousSibling())
953                     childElement.setNeedsStyleRecalc();
954                 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
955             } else if (childElement.styleChangeType() >= FullStyleChange)
956                 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
957             if (change >= Inherit || childElement.childNeedsStyleRecalc() || childElement.needsStyleRecalc()) {
958                 parentPusher.push();
959                 resolveTree(childElement, renderer->style(), childRenderTreePosition, change);
960             }
961         }
962
963         updateBeforeOrAfterPseudoElement(current, change, AFTER, childRenderTreePosition);
964     }
965     if (change != Detach && !renderer)
966         resetStyleForNonRenderedDescendants(current);
967
968     current.clearNeedsStyleRecalc();
969     current.clearChildNeedsStyleRecalc();
970     
971     if (current.hasCustomStyleResolveCallbacks())
972         current.didRecalcStyle(change);
973 }
974
975 void resolveTree(Document& document, Change change)
976 {
977     if (change == Force) {
978         auto documentStyle = resolveForDocument(document);
979
980         // Inserting the pictograph font at the end of the font fallback list is done by the
981         // font selector, so set a font selector if needed.
982         if (Settings* settings = document.settings()) {
983             StyleResolver* styleResolver = document.styleResolverIfExists();
984             if (settings->fontFallbackPrefersPictographs() && styleResolver)
985                 documentStyle.get().font().update(styleResolver->fontSelector());
986         }
987
988         Style::Change documentChange = determineChange(documentStyle.get(), document.renderView()->style());
989         if (documentChange != NoChange)
990             document.renderView()->setStyle(WTF::move(documentStyle));
991         else
992             documentStyle.dropRef();
993     }
994
995     Element* documentElement = document.documentElement();
996     if (!documentElement)
997         return;
998     if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
999         return;
1000     RenderTreePosition renderTreePosition(*document.renderView());
1001     resolveTree(*documentElement, *document.renderStyle(), renderTreePosition, change);
1002 }
1003
1004 void detachRenderTree(Element& element)
1005 {
1006     detachRenderTree(element, NormalDetach);
1007 }
1008
1009 static Vector<std::function<void ()>>& postResolutionCallbackQueue()
1010 {
1011     static NeverDestroyed<Vector<std::function<void ()>>> vector;
1012     return vector;
1013 }
1014
1015 void queuePostResolutionCallback(std::function<void ()> callback)
1016 {
1017     postResolutionCallbackQueue().append(callback);
1018 }
1019
1020 static void suspendMemoryCacheClientCalls(Document& document)
1021 {
1022     Page* page = document.page();
1023     if (!page || !page->areMemoryCacheClientCallsEnabled())
1024         return;
1025
1026     page->setMemoryCacheClientCallsEnabled(false);
1027
1028     RefPtr<MainFrame> protectedMainFrame = &page->mainFrame();
1029     postResolutionCallbackQueue().append([protectedMainFrame]{
1030         if (Page* page = protectedMainFrame->page())
1031             page->setMemoryCacheClientCallsEnabled(true);
1032     });
1033 }
1034
1035 static unsigned resolutionNestingDepth;
1036
1037 PostResolutionCallbackDisabler::PostResolutionCallbackDisabler(Document& document)
1038 {
1039     ++resolutionNestingDepth;
1040
1041     if (resolutionNestingDepth == 1)
1042         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->suspendPendingRequests();
1043
1044     // FIXME: It's strange to build this into the disabler.
1045     suspendMemoryCacheClientCalls(document);
1046 }
1047
1048 PostResolutionCallbackDisabler::~PostResolutionCallbackDisabler()
1049 {
1050     if (resolutionNestingDepth == 1) {
1051         // Get size each time through the loop because a callback can add more callbacks to the end of the queue.
1052         auto& queue = postResolutionCallbackQueue();
1053         for (size_t i = 0; i < queue.size(); ++i)
1054             queue[i]();
1055         queue.clear();
1056
1057         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->resumePendingRequests();
1058     }
1059
1060     --resolutionNestingDepth;
1061 }
1062
1063 bool postResolutionCallbacksAreSuspended()
1064 {
1065     return resolutionNestingDepth;
1066 }
1067
1068 }
1069 }