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