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