Enable selector filtering for ::before and ::after pseudo element resolution
[WebKit-https.git] / Source / WebCore / style / StyleTreeResolver.cpp
index b46ca7f..333e42a 100644 (file)
 #include "config.h"
 #include "StyleTreeResolver.h"
 
-#include "AuthorStyleSheets.h"
+#include "CSSAnimationController.h"
 #include "CSSFontSelector.h"
 #include "ComposedTreeAncestorIterator.h"
 #include "ComposedTreeIterator.h"
+#include "DocumentTimeline.h"
 #include "ElementIterator.h"
 #include "HTMLBodyElement.h"
+#include "HTMLMeterElement.h"
+#include "HTMLNames.h"
+#include "HTMLProgressElement.h"
 #include "HTMLSlotElement.h"
 #include "LoaderStrategy.h"
 #include "MainFrame.h"
 #include "NodeRenderStyle.h"
+#include "Page.h"
 #include "PlatformStrategies.h"
+#include "RenderElement.h"
+#include "RenderView.h"
 #include "Settings.h"
 #include "ShadowRoot.h"
+#include "StyleFontSizeFunctions.h"
 #include "StyleResolver.h"
+#include "StyleScope.h"
 #include "Text.h"
 
-#if PLATFORM(IOS)
-#include "WKContentObservation.h"
-#endif
-
 namespace WebCore {
 
 namespace Style {
 
-static RenderStyle* placeholderStyle;
-
-static void ensurePlaceholderStyle(Document& document)
-{
-    if (placeholderStyle)
-        return;
-    placeholderStyle = RenderStyle::createPtr().release();
-    placeholderStyle->setDisplay(NONE);
-    placeholderStyle->setIsPlaceholderStyle();
-    placeholderStyle->fontCascade().update(&document.fontSelector());
-}
-
 TreeResolver::TreeResolver(Document& document)
     : m_document(document)
 {
-    ensurePlaceholderStyle(document);
 }
 
-TreeResolver::~TreeResolver()
-{
-}
+TreeResolver::~TreeResolver() = default;
 
 TreeResolver::Scope::Scope(Document& document)
-    : styleResolver(document.ensureStyleResolver())
+    : styleResolver(document.styleScope().resolver())
     , sharingResolver(document, styleResolver.ruleSets(), selectorFilter)
 {
 }
 
 TreeResolver::Scope::Scope(ShadowRoot& shadowRoot, Scope& enclosingScope)
-    : styleResolver(shadowRoot.styleResolver())
+    : styleResolver(shadowRoot.styleScope().resolver())
     , sharingResolver(shadowRoot.documentScope(), styleResolver.ruleSets(), selectorFilter)
     , shadowRoot(&shadowRoot)
     , enclosingScope(&enclosingScope)
 {
+    styleResolver.setOverrideDocumentElementStyle(enclosingScope.styleResolver.overrideDocumentElementStyle());
+}
+
+TreeResolver::Scope::~Scope()
+{
+    styleResolver.setOverrideDocumentElementStyle(nullptr);
 }
 
-TreeResolver::Parent::Parent(Document& document, Change change)
+TreeResolver::Parent::Parent(Document& document)
     : element(nullptr)
     , style(*document.renderStyle())
-    , change(change)
 {
 }
 
-TreeResolver::Parent::Parent(Element& element, RenderStyle& style, Change change)
+TreeResolver::Parent::Parent(Element& element, const RenderStyle& style, Change change)
     : element(&element)
     , style(style)
     , change(change)
@@ -103,29 +98,21 @@ TreeResolver::Parent::Parent(Element& element, RenderStyle& style, Change change
 void TreeResolver::pushScope(ShadowRoot& shadowRoot)
 {
     m_scopeStack.append(adoptRef(*new Scope(shadowRoot, scope())));
-    scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get());
 }
 
 void TreeResolver::pushEnclosingScope()
 {
     ASSERT(scope().enclosingScope);
     m_scopeStack.append(*scope().enclosingScope);
-    scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get());
 }
 
 void TreeResolver::popScope()
 {
-    scope().styleResolver.setOverrideDocumentElementStyle(nullptr);
     return m_scopeStack.removeLast();
 }
 
-std::unique_ptr<RenderStyle> TreeResolver::styleForElement(Element& element, RenderStyle& inheritedStyle)
+std::unique_ptr<RenderStyle> TreeResolver::styleForElement(Element& element, const RenderStyle& inheritedStyle)
 {
-    if (!m_document.haveStylesheetsLoaded() && !element.renderer()) {
-        m_document.setHasNodesWithPlaceholderStyle();
-        return RenderStyle::clonePtr(*placeholderStyle);
-    }
-
     if (element.hasCustomStyleResolveCallbacks()) {
         RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr;
         if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) {
@@ -139,7 +126,7 @@ std::unique_ptr<RenderStyle> TreeResolver::styleForElement(Element& element, Ren
     if (auto style = scope().sharingResolver.resolve(element, *m_update))
         return style;
 
-    auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter);
+    auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, parentBoxStyle(), MatchAllRules, &scope().selectorFilter);
 
     if (elementStyle.relations)
         commitRelations(WTFMove(elementStyle.relations), *m_update);
@@ -158,7 +145,8 @@ static void resetStyleForNonRenderedDescendants(Element& current)
 
         if (child.needsStyleRecalc() || affectedByPreviousSibling) {
             child.resetComputedStyle();
-            child.clearNeedsStyleRecalc();
+            child.resetStyleRelations();
+            child.setHasValidStyle();
         }
 
         if (child.childNeedsStyleRecalc()) {
@@ -176,44 +164,48 @@ static bool affectsRenderedSubtree(Element& element, const RenderStyle& newStyle
         return true;
     if (element.rendererIsNeeded(newStyle))
         return true;
-    if (element.shouldMoveToFlowThread(newStyle))
-        return true;
     return false;
 }
 
-ElementUpdate TreeResolver::resolveElement(Element& element)
+static const RenderStyle* renderOrDisplayContentsStyle(const Element& element)
 {
-    auto newStyle = styleForElement(element, parent().style);
-
-    auto* renderer = element.renderer();
+    if (auto* renderStyle = element.renderStyle())
+        return renderStyle;
+    if (element.hasDisplayContents())
+        return element.existingComputedStyle();
+    return nullptr;
+}
 
-    if (!affectsRenderedSubtree(element, *newStyle))
+ElementUpdates TreeResolver::resolveElement(Element& element)
+{
+    if (m_didSeePendingStylesheet && !element.renderer() && !m_document.isIgnoringPendingStylesheets()) {
+        m_document.setHasNodesWithMissingStyle();
         return { };
+    }
 
-    ElementUpdate update;
+    auto newStyle = styleForElement(element, parent().style);
 
-    bool needsNewRenderer = !renderer || element.styleChangeType() == ReconstructRenderTree || parent().change == Detach;
+    if (!affectsRenderedSubtree(element, *newStyle))
+        return { };
 
-    std::unique_ptr<RenderStyle> animatedStyle;
-    if (!needsNewRenderer && m_document.frame()->animation().updateAnimations(*renderer, *newStyle, animatedStyle))
-        update.isSynthetic = true;
+    auto* existingStyle = renderOrDisplayContentsStyle(element);
 
-    update.change = needsNewRenderer ? Detach : determineChange(renderer->style(), *newStyle);
-    update.style = animatedStyle ? WTFMove(animatedStyle) : WTFMove(newStyle);
+    if (m_didSeePendingStylesheet && (!existingStyle || existingStyle->isNotFinal())) {
+        newStyle->setIsNotFinal();
+        m_document.setHasNodesWithNonFinalStyle();
+    }
 
-    if (element.styleChangeType() == SyntheticStyleChange)
-        update.isSynthetic = true;
+    auto update = createAnimatedElementUpdate(WTFMove(newStyle), element, parent().change);
 
     if (&element == m_document.documentElement()) {
         m_documentElementStyle = RenderStyle::clonePtr(*update.style);
         scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get());
 
-        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating
-        // 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).
-        if (m_document.authorStyleSheets().usesRemUnits() && update.change != NoChange && renderer && renderer->style().fontSize() != update.style->fontSize()) {
-            // Cached RenderStyles may depend on the rem units.
+        if (update.change != NoChange && existingStyle && existingStyle->computedFontPixelSize() != update.style->computedFontPixelSize()) {
+            // "rem" units are relative to the document element's font size so we need to recompute everything.
+            // In practice this is rare.
             scope().styleResolver.invalidateMatchedPropertiesCache();
-            update.change = Force;
+            update.change = std::max(update.change, Force);
         }
     }
 
@@ -222,67 +214,91 @@ ElementUpdate TreeResolver::resolveElement(Element& element)
     if (&element == m_document.body())
         m_document.setTextColor(update.style->visitedDependentColor(CSSPropertyColor));
 
-    if (update.change != Detach && (parent().change == Force || element.styleChangeType() >= FullStyleChange))
-        update.change = Force;
+    // FIXME: These elements should not change renderer based on appearance property.
+    if (element.hasTagName(HTMLNames::meterTag) || is<HTMLProgressElement>(element)) {
+        if (existingStyle && update.style->appearance() != existingStyle->appearance())
+            update.change = Detach;
+    }
+
+    auto beforeUpdate = resolvePseudoStyle(element, update, BEFORE);
+    auto afterUpdate = resolvePseudoStyle(element, update, AFTER);
 
-    return update;
+    return { WTFMove(update), WTFMove(beforeUpdate), WTFMove(afterUpdate) };
 }
 
-#if PLATFORM(IOS)
-static EVisibility elementImplicitVisibility(const Element* element)
+ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
 {
-    RenderObject* renderer = element->renderer();
-    if (!renderer)
-        return VISIBLE;
-
-    RenderStyle& style = renderer->style();
+    if (elementUpdate.style->display() == NONE)
+        return { };
+    if (!elementUpdate.style->hasPseudoStyle(pseudoId))
+        return { };
 
-    Length width(style.width());
-    Length height(style.height());
-    if ((width.isFixed() && width.value() <= 0) || (height.isFixed() && height.value() <= 0))
-        return HIDDEN;
+    auto pseudoStyle = scope().styleResolver.pseudoStyleForElement(element, { pseudoId }, *elementUpdate.style, &scope().selectorFilter);
+    if (!pseudoStyle)
+        return { };
 
-    Length top(style.top());
-    Length left(style.left());
-    if (left.isFixed() && width.isFixed() && -left.value() >= width.value())
-        return HIDDEN;
+    PseudoElement* pseudoElement = pseudoId == BEFORE ? element.beforePseudoElement() : element.afterPseudoElement();
+    if (!pseudoElement) {
+        auto newPseudoElement = PseudoElement::create(element, pseudoId);
+        pseudoElement = newPseudoElement.ptr();
+        if (pseudoId == BEFORE)
+            element.setBeforePseudoElement(WTFMove(newPseudoElement));
+        else
+            element.setAfterPseudoElement(WTFMove(newPseudoElement));
+    }
 
-    if (top.isFixed() && height.isFixed() && -top.value() >= height.value())
-        return HIDDEN;
-    return VISIBLE;
+    return createAnimatedElementUpdate(WTFMove(pseudoStyle), *pseudoElement, elementUpdate.change);
 }
 
-class CheckForVisibilityChangeOnRecalcStyle {
-public:
-    CheckForVisibilityChangeOnRecalcStyle(Element* element, RenderStyle* currentStyle)
-        : m_element(element)
-        , m_previousDisplay(currentStyle ? currentStyle->display() : NONE)
-        , m_previousVisibility(currentStyle ? currentStyle->visibility() : HIDDEN)
-        , m_previousImplicitVisibility(WKObservingContentChanges() && WKObservedContentChange() != WKContentVisibilityChange ? elementImplicitVisibility(element) : VISIBLE)
-    {
+const RenderStyle* TreeResolver::parentBoxStyle() const
+{
+    // 'display: contents' doesn't generate boxes.
+    for (unsigned i = m_parentStack.size(); i; --i) {
+        auto& parent = m_parentStack[i - 1];
+        if (parent.style.display() == NONE)
+            return nullptr;
+        if (parent.style.display() != CONTENTS)
+            return &parent.style;
     }
-    ~CheckForVisibilityChangeOnRecalcStyle()
-    {
-        if (!WKObservingContentChanges())
-            return;
-        if (m_element->isInUserAgentShadowTree())
-            return;
-        RenderStyle* style = m_element->renderStyle();
-        if (!style)
-            return;
-        if ((m_previousDisplay == NONE && style->display() != NONE) || (m_previousVisibility == HIDDEN && style->visibility() != HIDDEN)
-            || (m_previousImplicitVisibility == HIDDEN && elementImplicitVisibility(m_element.get()) == VISIBLE))
-            WKSetObservedContentChange(WKContentVisibilityChange);
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderStyle> newStyle, Element& element, Change parentChange)
+{
+    auto* oldStyle = renderOrDisplayContentsStyle(element);
+
+    if (auto timeline = element.document().existingTimeline()) {
+        auto webAnimations = timeline->animationsForElement(element);
+        if (!webAnimations.isEmpty()) {
+            auto animatedStyle = RenderStyle::clonePtr(*newStyle);
+            for (const auto& animation : webAnimations)
+                animation->resolve(*animatedStyle);
+            newStyle = WTFMove(animatedStyle);
+        }
     }
-private:
-    RefPtr<Element> m_element;
-    EDisplay m_previousDisplay;
-    EVisibility m_previousVisibility;
-    EVisibility m_previousImplicitVisibility;
-};
-#endif // PLATFORM(IOS)
 
-void TreeResolver::pushParent(Element& element, RenderStyle& style, Change change)
+    auto& animationController = m_document.frame()->animation();
+
+    auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle);
+
+    if (animationUpdate.style)
+        newStyle = WTFMove(animationUpdate.style);
+
+    auto change = oldStyle ? determineChange(*oldStyle, *newStyle) : Detach;
+
+    auto validity = element.styleValidity();
+    if (validity >= Validity::SubtreeInvalid)
+        change = std::max(change, validity == Validity::SubtreeAndRenderersInvalid ? Detach : Force);
+    if (parentChange >= Force)
+        change = std::max(change, parentChange);
+
+    bool shouldRecompositeLayer = element.styleResolutionShouldRecompositeLayer() || animationUpdate.stateChanged;
+
+    return { WTFMove(newStyle), change, shouldRecompositeLayer };
+}
+
+void TreeResolver::pushParent(Element& element, const RenderStyle& style, Change change)
 {
     scope().selectorFilter.pushParent(&element);
 
@@ -292,12 +308,10 @@ void TreeResolver::pushParent(Element& element, RenderStyle& style, Change chang
         pushScope(*shadowRoot);
         parent.didPushScope = true;
     }
-#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
     else if (is<HTMLSlotElement>(element) && downcast<HTMLSlotElement>(element).assignedNodes()) {
         pushEnclosingScope();
         parent.didPushScope = true;
     }
-#endif
 
     m_parentStack.append(WTFMove(parent));
 }
@@ -306,7 +320,7 @@ void TreeResolver::popParent()
 {
     auto& parentElement = *parent().element;
 
-    parentElement.clearNeedsStyleRecalc();
+    parentElement.setHasValidStyle();
     parentElement.clearChildNeedsStyleRecalc();
 
     if (parent().didPushScope)
@@ -326,13 +340,66 @@ void TreeResolver::popParentsToDepth(unsigned depth)
         popParent();
 }
 
-static bool shouldResolvePseudoElement(PseudoElement* pseudoElement)
+static bool shouldResolvePseudoElement(const PseudoElement* pseudoElement)
 {
     if (!pseudoElement)
         return false;
-    bool needsStyleRecalc = pseudoElement->needsStyleRecalc();
-    pseudoElement->clearNeedsStyleRecalc();
-    return needsStyleRecalc;
+    return pseudoElement->needsStyleRecalc();
+}
+
+static bool shouldResolveElement(const Element& element, Style::Change parentChange)
+{
+    if (parentChange >= Inherit)
+        return true;
+    if (parentChange == NoInherit) {
+        auto* existingStyle = renderOrDisplayContentsStyle(element);
+        if (existingStyle && existingStyle->hasExplicitlyInheritedProperties())
+            return true;
+    }
+    if (element.needsStyleRecalc())
+        return true;
+    if (shouldResolvePseudoElement(element.beforePseudoElement()))
+        return true;
+    if (shouldResolvePseudoElement(element.afterPseudoElement()))
+        return true;
+
+    return false;
+}
+
+static void clearNeedsStyleResolution(Element& element)
+{
+    element.setHasValidStyle();
+    if (auto* before = element.beforePseudoElement())
+        before->setHasValidStyle();
+    if (auto* after = element.afterPseudoElement())
+        after->setHasValidStyle();
+}
+
+static bool hasLoadingStylesheet(const Style::Scope& styleScope, const Element& element, bool checkDescendants)
+{
+    if (!styleScope.hasPendingSheetsInBody())
+        return false;
+    if (styleScope.hasPendingSheetInBody(element))
+        return true;
+    if (!checkDescendants)
+        return false;
+    for (auto& descendant : descendantsOfType<Element>(element)) {
+        if (styleScope.hasPendingSheetInBody(descendant))
+            return true;
+    };
+    return false;
+}
+
+static std::unique_ptr<RenderStyle> createInheritedDisplayContentsStyleIfNeeded(const RenderStyle& parentElementStyle, const RenderStyle* parentBoxStyle)
+{
+    if (parentElementStyle.display() != CONTENTS)
+        return nullptr;
+    if (parentBoxStyle && !parentBoxStyle->inheritedNotEqual(&parentElementStyle))
+        return nullptr;
+    // Compute style for imaginary unstyled <span> around the text node.
+    auto style = RenderStyle::createPtr();
+    style->inheritFrom(parentElementStyle);
+    return style;
 }
 
 void TreeResolver::resolveComposedTree()
@@ -353,63 +420,66 @@ void TreeResolver::resolveComposedTree()
         auto& node = *it;
         auto& parent = this->parent();
 
+        ASSERT(node.isConnected());
         ASSERT(node.containingShadowRoot() == scope().shadowRoot);
         ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot());
 
         if (is<Text>(node)) {
             auto& text = downcast<Text>(node);
-            if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach)
-                m_update->addText(text, parent.element);
+            
+            if ((text.styleValidity() >= Validity::SubtreeAndRenderersInvalid && parent.change != Detach) || parent.style.display() == CONTENTS) {
+                TextUpdate textUpdate;
+                textUpdate.inheritedDisplayContentsStyle = createInheritedDisplayContentsStyleIfNeeded(parent.style, parentBoxStyle());
 
-            text.clearNeedsStyleRecalc();
+                m_update->addText(text, parent.element, WTFMove(textUpdate));
+            }
+
+            text.setHasValidStyle();
             it.traverseNextSkippingChildren();
             continue;
         }
 
         auto& element = downcast<Element>(node);
 
+        if (it.depth() > Settings::defaultMaximumRenderTreeDepth) {
+            resetStyleForNonRenderedDescendants(element);
+            element.clearChildNeedsStyleRecalc();
+            it.traverseNextSkippingChildren();
+            continue;
+        }
+
         // FIXME: We should deal with this during style invalidation.
         bool affectedByPreviousSibling = element.styleIsAffectedByPreviousSibling() && parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle;
         if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle)
             parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle();
 
-        bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement());
+        auto* style = renderOrDisplayContentsStyle(element);
+        auto change = NoChange;
 
-        RenderStyle* style;
-        Change change;
-
-        bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling || element.hasDisplayContents();
+        bool shouldResolve = shouldResolveElement(element, parent.change) || affectedByPreviousSibling;
         if (shouldResolve) {
-#if PLATFORM(IOS)
-            CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle());
-#endif
-            element.resetComputedStyle();
-
-            if (element.hasCustomStyleResolveCallbacks()) {
-                if (!element.willRecalcStyle(parent.change)) {
-                    it.traverseNextSkippingChildren();
-                    continue;
-                }
-            }
+            if (!element.hasDisplayContents())
+                element.resetComputedStyle();
+            element.resetStyleRelations();
+
+            if (element.hasCustomStyleResolveCallbacks())
+                element.willRecalcStyle(parent.change);
 
-            auto elementUpdate = resolveElement(element);
+            auto elementUpdates = resolveElement(element);
 
             if (element.hasCustomStyleResolveCallbacks())
-                element.didRecalcStyle(elementUpdate.change);
+                element.didRecalcStyle(elementUpdates.update.change);
 
-            style = elementUpdate.style.get();
-            change = elementUpdate.change;
+            style = elementUpdates.update.style.get();
+            change = elementUpdates.update.change;
 
             if (affectedByPreviousSibling && change != Detach)
                 change = Force;
 
-            if (elementUpdate.style)
-                m_update->addElement(element, parent.element, WTFMove(elementUpdate));
+            if (elementUpdates.update.style)
+                m_update->addElement(element, parent.element, WTFMove(elementUpdates));
 
-            element.clearNeedsStyleRecalc();
-        } else {
-            style = element.renderStyle();
-            change = NoChange;
+            clearNeedsStyleResolution(element);
         }
 
         if (!style) {
@@ -418,6 +488,10 @@ void TreeResolver::resolveComposedTree()
         }
 
         bool shouldIterateChildren = style && (element.childNeedsStyleRecalc() || change != NoChange);
+
+        if (!m_didSeePendingStylesheet)
+            m_didSeePendingStylesheet = hasLoadingStylesheet(m_document.styleScope(), element, !shouldIterateChildren);
+
         if (!shouldIterateChildren) {
             it.traverseNextSkippingChildren();
             continue;
@@ -431,19 +505,23 @@ void TreeResolver::resolveComposedTree()
     popParentsToDepth(1);
 }
 
-std::unique_ptr<Update> TreeResolver::resolve(Change change)
+std::unique_ptr<Update> TreeResolver::resolve()
 {
     auto& renderView = *m_document.renderView();
 
     Element* documentElement = m_document.documentElement();
-    if (!documentElement)
+    if (!documentElement) {
+        m_document.styleScope().resolver();
         return nullptr;
-    if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
+    }
+    if (!documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
         return nullptr;
 
+    m_didSeePendingStylesheet = m_document.styleScope().hasPendingSheetsBeforeBody();
+
     m_update = std::make_unique<Update>(m_document);
     m_scopeStack.append(adoptRef(*new Scope(m_document)));
-    m_parentStack.append(Parent(m_document, change));
+    m_parentStack.append(Parent(m_document));
 
     // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
     renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules());
@@ -465,15 +543,15 @@ std::unique_ptr<Update> TreeResolver::resolve(Change change)
     return WTFMove(m_update);
 }
 
-static Vector<std::function<void ()>>& postResolutionCallbackQueue()
+static Vector<Function<void ()>>& postResolutionCallbackQueue()
 {
-    static NeverDestroyed<Vector<std::function<void ()>>> vector;
+    static NeverDestroyed<Vector<Function<void ()>>> vector;
     return vector;
 }
 
-void queuePostResolutionCallback(std::function<void ()> callback)
+void queuePostResolutionCallback(Function<void ()>&& callback)
 {
-    postResolutionCallbackQueue().append(callback);
+    postResolutionCallbackQueue().append(WTFMove(callback));
 }
 
 static void suspendMemoryCacheClientCalls(Document& document)
@@ -484,8 +562,7 @@ static void suspendMemoryCacheClientCalls(Document& document)
 
     page->setMemoryCacheClientCallsEnabled(false);
 
-    RefPtr<MainFrame> protectedMainFrame = &page->mainFrame();
-    postResolutionCallbackQueue().append([protectedMainFrame]{
+    postResolutionCallbackQueue().append([protectedMainFrame = Ref<MainFrame>(page->mainFrame())] {
         if (Page* page = protectedMainFrame->page())
             page->setMemoryCacheClientCallsEnabled(true);
     });
@@ -524,10 +601,5 @@ bool postResolutionCallbacksAreSuspended()
     return resolutionNestingDepth;
 }
 
-bool isPlaceholderStyle(const RenderStyle& style)
-{
-    return &style == placeholderStyle;
-}
-
 }
 }