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