Move MatchResult and related types out of StyleResolver
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Oct 2019 08:18:36 +0000 (08:18 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Oct 2019 08:18:36 +0000 (08:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203252

Reviewed by Zalan Bujtas.

Reverse the dependency between StyleResolver and ElementRuleCollector so that the former depends on the latter.
This makes the code easier to understand and enables further cleanups.

The patch also gets rid of the confusing RuleRange objects in fovor of splitting declarations from different cascade levels to separate vectors.
The desired cascade level is indicated with an enum instead of a range.

There is also some general modernization.

* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::matchResult const):
(WebCore::ElementRuleCollector::addElementStyleProperties):
(WebCore::ElementRuleCollector::transferMatchedRules):
(WebCore::ElementRuleCollector::matchAllRules):
(WebCore::ElementRuleCollector::addMatchedProperties):
(WebCore::ElementRuleCollector::matchedResult): Deleted.
* css/ElementRuleCollector.h:
(WebCore::PseudoStyleRequest::PseudoStyleRequest):
(WebCore::MatchResult::isEmpty const):
(WebCore::operator==):
(WebCore::operator!=):
* css/PageRuleCollector.cpp:
(WebCore::PageRuleCollector::matchPageRules):
* css/PageRuleCollector.h:
(WebCore::PageRuleCollector::matchResult const):
(WebCore::PageRuleCollector::matchedResult): Deleted.
* css/StyleResolver.cpp:
(WebCore::StyleResolver::sweepMatchedPropertiesCache):
(WebCore::StyleResolver::styleForElement):
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::pseudoStyleForElement):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::computeMatchedPropertiesHash):
(WebCore::StyleResolver::findFromMatchedPropertiesCache):
(WebCore::extractDirectionAndWritingMode):
(WebCore::StyleResolver::applyMatchedProperties):
(WebCore::StyleResolver::cascadedPropertiesForRollback):
(WebCore::StyleResolver::CascadedProperties::addMatch):
(WebCore::declarationsForCascadeLevel):
(WebCore::StyleResolver::CascadedProperties::addNormalMatches):
(WebCore::StyleResolver::CascadedProperties::addImportantMatches):
(WebCore::StyleResolver::MatchResult::addMatchedProperties): Deleted.
(WebCore::operator==): Deleted.
(WebCore::operator!=): Deleted.
(WebCore::cascadeLevelForIndex): Deleted.
* css/StyleResolver.h:
(WebCore::StyleResolver::MatchedPropertiesCacheItem::MatchedPropertiesCacheItem):
(WebCore::PseudoStyleRequest::PseudoStyleRequest): Deleted.
(WebCore::StyleResolver::RuleRange::RuleRange): Deleted.
(WebCore::StyleResolver::MatchRanges::MatchRanges): Deleted.
(WebCore::StyleResolver::MatchRanges::UARuleRange): Deleted.
(WebCore::StyleResolver::MatchRanges::authorRuleRange): Deleted.
(WebCore::StyleResolver::MatchRanges::userRuleRange): Deleted.
(WebCore::StyleResolver::MatchResult::MatchResult): Deleted.
(WebCore::StyleResolver::MatchResult::matchedProperties const): Deleted.
(WebCore::StyleResolver::isRightPage const): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251532 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/css/ElementRuleCollector.cpp
Source/WebCore/css/ElementRuleCollector.h
Source/WebCore/css/PageRuleCollector.cpp
Source/WebCore/css/PageRuleCollector.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h

index f6eb088..d35e0c1 100644 (file)
@@ -1,3 +1,66 @@
+2019-10-24  Antti Koivisto  <antti@apple.com>
+
+        Move MatchResult and related types out of StyleResolver
+        https://bugs.webkit.org/show_bug.cgi?id=203252
+
+        Reviewed by Zalan Bujtas.
+
+        Reverse the dependency between StyleResolver and ElementRuleCollector so that the former depends on the latter.
+        This makes the code easier to understand and enables further cleanups.
+
+        The patch also gets rid of the confusing RuleRange objects in fovor of splitting declarations from different cascade levels to separate vectors.
+        The desired cascade level is indicated with an enum instead of a range.
+
+        There is also some general modernization.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::matchResult const):
+        (WebCore::ElementRuleCollector::addElementStyleProperties):
+        (WebCore::ElementRuleCollector::transferMatchedRules):
+        (WebCore::ElementRuleCollector::matchAllRules):
+        (WebCore::ElementRuleCollector::addMatchedProperties):
+        (WebCore::ElementRuleCollector::matchedResult): Deleted.
+        * css/ElementRuleCollector.h:
+        (WebCore::PseudoStyleRequest::PseudoStyleRequest):
+        (WebCore::MatchResult::isEmpty const):
+        (WebCore::operator==):
+        (WebCore::operator!=):
+        * css/PageRuleCollector.cpp:
+        (WebCore::PageRuleCollector::matchPageRules):
+        * css/PageRuleCollector.h:
+        (WebCore::PageRuleCollector::matchResult const):
+        (WebCore::PageRuleCollector::matchedResult): Deleted.
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::sweepMatchedPropertiesCache):
+        (WebCore::StyleResolver::styleForElement):
+        (WebCore::StyleResolver::styleForKeyframe):
+        (WebCore::StyleResolver::pseudoStyleForElement):
+        (WebCore::StyleResolver::styleForPage):
+        (WebCore::StyleResolver::computeMatchedPropertiesHash):
+        (WebCore::StyleResolver::findFromMatchedPropertiesCache):
+        (WebCore::extractDirectionAndWritingMode):
+        (WebCore::StyleResolver::applyMatchedProperties):
+        (WebCore::StyleResolver::cascadedPropertiesForRollback):
+        (WebCore::StyleResolver::CascadedProperties::addMatch):
+        (WebCore::declarationsForCascadeLevel):
+        (WebCore::StyleResolver::CascadedProperties::addNormalMatches):
+        (WebCore::StyleResolver::CascadedProperties::addImportantMatches):
+        (WebCore::StyleResolver::MatchResult::addMatchedProperties): Deleted.
+        (WebCore::operator==): Deleted.
+        (WebCore::operator!=): Deleted.
+        (WebCore::cascadeLevelForIndex): Deleted.
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::MatchedPropertiesCacheItem::MatchedPropertiesCacheItem):
+        (WebCore::PseudoStyleRequest::PseudoStyleRequest): Deleted.
+        (WebCore::StyleResolver::RuleRange::RuleRange): Deleted.
+        (WebCore::StyleResolver::MatchRanges::MatchRanges): Deleted.
+        (WebCore::StyleResolver::MatchRanges::UARuleRange): Deleted.
+        (WebCore::StyleResolver::MatchRanges::authorRuleRange): Deleted.
+        (WebCore::StyleResolver::MatchRanges::userRuleRange): Deleted.
+        (WebCore::StyleResolver::MatchResult::MatchResult): Deleted.
+        (WebCore::StyleResolver::MatchResult::matchedProperties const): Deleted.
+        (WebCore::StyleResolver::isRightPage const): Deleted.
+
 2019-10-23  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: provide a way to inject "bootstrap" JavaScript into the page as the first script executed
index a2a59d2..cfb5f7c 100644 (file)
@@ -95,7 +95,7 @@ ElementRuleCollector::ElementRuleCollector(const Element& element, const RuleSet
     ASSERT(!m_selectorFilter || m_selectorFilter->parentStackIsConsistent(element.parentNode()));
 }
 
-StyleResolver::MatchResult& ElementRuleCollector::matchedResult()
+const MatchResult& ElementRuleCollector::matchResult() const
 {
     ASSERT(m_mode == SelectorChecker::Mode::ResolvingStyle);
     return m_result;
@@ -124,14 +124,8 @@ inline void ElementRuleCollector::addElementStyleProperties(const StylePropertie
     if (!propertySet)
         return;
 
-    if (m_result.ranges.lastAuthorRule != -1)
-        ++m_result.ranges.lastAuthorRule;
-    else {
-        m_result.ranges.lastAuthorRule = m_result.matchedProperties().size();
-        m_result.ranges.firstAuthorRule = m_result.ranges.lastAuthorRule;
-    }
+    addMatchedProperties({ propertySet }, DeclarationOrigin::Author);
 
-    m_result.addMatchedProperties(*propertySet);
     if (!isCacheable)
         m_result.isCacheable = false;
 }
@@ -178,22 +172,6 @@ void ElementRuleCollector::transferMatchedRules(DeclarationOrigin declarationOri
     if (m_matchedRules.size() <= m_matchedRuleTransferIndex)
         return;
 
-    auto rangeForDeclarationOrigin = [&]() {
-        switch (declarationOrigin) {
-        case DeclarationOrigin::UserAgent: return m_result.ranges.UARuleRange();
-        case DeclarationOrigin::Author: return m_result.ranges.authorRuleRange();
-        case DeclarationOrigin::User: return m_result.ranges.userRuleRange();
-        }
-        ASSERT_NOT_REACHED();
-        return m_result.ranges.authorRuleRange();
-    }();
-
-    // FIXME: Range updating should be done by MatchResults type
-    // FIXME: MatchResults shouldn't be in StyleResolver namespace.
-    bool updateRanges = m_mode != SelectorChecker::Mode::CollectingRules;
-    if (updateRanges && rangeForDeclarationOrigin.firstRuleIndex == -1)
-        rangeForDeclarationOrigin.firstRuleIndex = m_result.matchedRules.size();
-
     for (; m_matchedRuleTransferIndex < m_matchedRules.size(); ++m_matchedRuleTransferIndex) {
         auto& matchedRule = m_matchedRules[m_matchedRuleTransferIndex];
         if (fromScope && matchedRule.styleScopeOrdinal < *fromScope)
@@ -204,11 +182,13 @@ void ElementRuleCollector::transferMatchedRules(DeclarationOrigin declarationOri
             continue;
         }
 
-        m_result.addMatchedProperties(matchedRule.ruleData->rule()->properties(), matchedRule.ruleData->rule(), matchedRule.ruleData->linkMatchType(), matchedRule.ruleData->propertyWhitelistType(), matchedRule.styleScopeOrdinal);
+        addMatchedProperties({
+            &matchedRule.ruleData->rule()->properties(),
+            static_cast<uint16_t>(matchedRule.ruleData->linkMatchType()),
+            static_cast<uint16_t>(matchedRule.ruleData->propertyWhitelistType()),
+            matchedRule.styleScopeOrdinal
+        }, declarationOrigin);
     }
-
-    if (updateRanges)
-        rangeForDeclarationOrigin.lastRuleIndex = m_result.matchedRules.size() - 1;
 }
 
 void ElementRuleCollector::matchAuthorRules()
@@ -586,9 +566,10 @@ void ElementRuleCollector::matchAllRules(bool matchAuthorAndUserStyles, bool inc
 
         if (is<HTMLElement>(styledElement)) {
             bool isAuto;
-            TextDirection textDirection = downcast<HTMLElement>(styledElement).directionalityIfhasDirAutoAttribute(isAuto);
+            auto textDirection = downcast<HTMLElement>(styledElement).directionalityIfhasDirAutoAttribute(isAuto);
+            auto& properties = textDirection == TextDirection::LTR ? leftToRightDeclaration() : rightToLeftDeclaration();
             if (isAuto)
-                m_result.addMatchedProperties(textDirection == TextDirection::LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
+                addMatchedProperties({ &properties }, DeclarationOrigin::Author);
         }
     }
     
@@ -633,4 +614,59 @@ bool ElementRuleCollector::hasAnyMatchingRules(const RuleSet* ruleSet)
     return !m_matchedRules.isEmpty();
 }
 
+void ElementRuleCollector::addMatchedProperties(MatchedProperties&& matchedProperties, DeclarationOrigin declarationOrigin)
+{
+    // FIXME: This should be moved to the matched properties cache code.
+    auto computeIsCacheable = [&] {
+        if (!m_result.isCacheable)
+            return false;
+
+        if (matchedProperties.styleScopeOrdinal != Style::ScopeOrdinal::Element)
+            return false;
+
+        auto& properties = *matchedProperties.properties;
+        for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
+            // Currently the property cache only copy the non-inherited values and resolve
+            // the inherited ones.
+            // Here we define some exception were we have to resolve some properties that are not inherited
+            // by default. If those exceptions become too common on the web, it should be possible
+            // to build a list of exception to resolve instead of completely disabling the cache.
+            StyleProperties::PropertyReference current = properties.propertyAt(i);
+            if (current.isInherited())
+                continue;
+
+            // If the property value is explicitly inherited, we need to apply further non-inherited properties
+            // as they might override the value inherited here. For this reason we don't allow declarations with
+            // explicitly inherited properties to be cached.
+            const CSSValue& value = *current.value();
+            if (value.isInheritedValue())
+                return false;
+
+            // The value currentColor has implicitely the same side effect. It depends on the value of color,
+            // which is an inherited value, making the non-inherited property implicitly inherited.
+            if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).valueID() == CSSValueCurrentcolor)
+                return false;
+
+            if (value.hasVariableReferences())
+                return false;
+        }
+
+        return true;
+    };
+
+    m_result.isCacheable = computeIsCacheable();
+
+    switch (declarationOrigin) {
+    case DeclarationOrigin::UserAgent:
+        m_result.userAgentDeclarations.append(WTFMove(matchedProperties));
+        break;
+    case DeclarationOrigin::User:
+        m_result.userDeclarations.append(WTFMove(matchedProperties));
+        break;
+    case DeclarationOrigin::Author:
+        m_result.authorDeclarations.append(WTFMove(matchedProperties));
+        break;
+    }
+}
+
 } // namespace WebCore
index 1ddbfea..5e53531 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "MediaQueryEvaluator.h"
 #include "SelectorChecker.h"
-#include "StyleResolver.h"
+#include "StyleScope.h"
 #include <memory>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
@@ -36,12 +36,40 @@ class RuleData;
 class RuleSet;
 class SelectorFilter;
 
+class PseudoStyleRequest {
+public:
+    PseudoStyleRequest(PseudoId pseudoId, Optional<StyleScrollbarState> scrollbarState = WTF::nullopt)
+        : pseudoId(pseudoId)
+        , scrollbarState(scrollbarState)
+    {
+    }
+
+    PseudoId pseudoId;
+    Optional<StyleScrollbarState> scrollbarState;
+};
+
 struct MatchedRule {
     const RuleData* ruleData;
-    unsigned specificity;   
+    unsigned specificity;
     Style::ScopeOrdinal styleScopeOrdinal;
 };
 
+struct MatchedProperties {
+    RefPtr<const StyleProperties> properties;
+    uint16_t linkMatchType { SelectorChecker::MatchAll };
+    uint16_t whitelistType { PropertyWhitelistNone };
+    Style::ScopeOrdinal styleScopeOrdinal { Style::ScopeOrdinal::Element };
+};
+
+struct MatchResult {
+    bool isCacheable { true };
+    Vector<MatchedProperties, 32> userAgentDeclarations;
+    Vector<MatchedProperties, 32> userDeclarations;
+    Vector<MatchedProperties, 32> authorDeclarations;
+
+    bool isEmpty() const { return userAgentDeclarations.isEmpty() && userDeclarations.isEmpty() && authorDeclarations.isEmpty(); }
+};
+
 class ElementRuleCollector {
 public:
     ElementRuleCollector(const Element&, const DocumentRuleSets&, const SelectorFilter*);
@@ -62,7 +90,7 @@ public:
 
     bool hasAnyMatchingRules(const RuleSet*);
 
-    StyleResolver::MatchResult& matchedResult();
+    const MatchResult& matchResult() const;
     const Vector<RefPtr<StyleRule>>& matchedRuleList() const;
 
     void clearMatchedRules();
@@ -94,11 +122,12 @@ private:
 
     void sortMatchedRules();
 
-    enum class DeclarationOrigin { UserAgent, Author, User };
+    enum class DeclarationOrigin { UserAgent, User, Author };
     void sortAndTransferMatchedRules(DeclarationOrigin);
     void transferMatchedRules(DeclarationOrigin, Optional<Style::ScopeOrdinal> forScope = { });
 
     void addMatchedRule(const RuleData&, unsigned specificity, Style::ScopeOrdinal);
+    void addMatchedProperties(MatchedProperties&&, DeclarationOrigin);
 
     const Element& element() const { return m_element.get(); }
 
@@ -123,9 +152,19 @@ private:
     // Output.
     Vector<RefPtr<StyleRule>> m_matchedRuleList;
     bool m_didMatchUncommonAttributeSelector { false };
-    StyleResolver::MatchResult m_result;
+    MatchResult m_result;
     Style::Relations m_styleRelations;
     PseudoIdSet m_matchedPseudoElementIds;
 };
 
+inline bool operator==(const MatchedProperties& a, const MatchedProperties& b)
+{
+    return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
+}
+
+inline bool operator!=(const MatchedProperties& a, const MatchedProperties& b)
+{
+    return !(a == b);
+}
+
 } // namespace WebCore
index a28450a..07483df 100644 (file)
@@ -87,7 +87,7 @@ void PageRuleCollector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isF
     std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
 
     for (unsigned i = 0; i < matchedPageRules.size(); i++)
-        m_result.addMatchedProperties(matchedPageRules[i]->properties());
+        m_result.authorDeclarations.append({ &matchedPageRules[i]->properties() });
 }
 
 static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName)
index 7839871..ce46d1c 100644 (file)
@@ -36,7 +36,7 @@ public:
         , m_ruleSets(ruleSets) { }
 
     void matchAllPageRules(int pageIndex);
-    StyleResolver::MatchResult& matchedResult() { return m_result; }
+    const MatchResult& matchResult() const { return m_result; }
 
 private:
     bool isLeftPage(int pageIndex) const;
@@ -50,7 +50,7 @@ private:
     const StyleResolver::State& m_state;
     DocumentRuleSets& m_ruleSets;
 
-    StyleResolver::MatchResult m_result;
+    MatchResult m_result;
 };
 
 } // namespace WebCore
index c5f1bc3..15434a0 100644 (file)
@@ -119,7 +119,7 @@ using namespace HTMLNames;
 
 static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
 
-static void extractDirectionAndWritingMode(const RenderStyle&, const StyleResolver::MatchResult&, TextDirection&, WritingMode&);
+static void extractDirectionAndWritingMode(const RenderStyle&, const MatchResult&, TextDirection&, WritingMode&);
 
 inline void StyleResolver::State::cacheBorderAndBackground()
 {
@@ -139,54 +139,6 @@ inline void StyleResolver::State::clear()
     m_cssToLengthConversionData = CSSToLengthConversionData();
 }
 
-void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType, Style::ScopeOrdinal styleScopeOrdinal)
-{
-    m_matchedProperties.grow(m_matchedProperties.size() + 1);
-    StyleResolver::MatchedProperties& newProperties = m_matchedProperties.last();
-    newProperties.properties = const_cast<StyleProperties*>(&properties);
-    newProperties.linkMatchType = linkMatchType;
-    newProperties.whitelistType = propertyWhitelistType;
-    newProperties.styleScopeOrdinal = styleScopeOrdinal;
-    matchedRules.append(rule);
-
-    if (styleScopeOrdinal != Style::ScopeOrdinal::Element)
-        isCacheable = false;
-
-    if (isCacheable) {
-        for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
-            // Currently the property cache only copy the non-inherited values and resolve
-            // the inherited ones.
-            // Here we define some exception were we have to resolve some properties that are not inherited
-            // by default. If those exceptions become too common on the web, it should be possible
-            // to build a list of exception to resolve instead of completely disabling the cache.
-
-            StyleProperties::PropertyReference current = properties.propertyAt(i);
-            if (!current.isInherited()) {
-                // If the property value is explicitly inherited, we need to apply further non-inherited properties
-                // as they might override the value inherited here. For this reason we don't allow declarations with
-                // explicitly inherited properties to be cached.
-                const CSSValue& value = *current.value();
-                if (value.isInheritedValue()) {
-                    isCacheable = false;
-                    break;
-                }
-
-                // The value currentColor has implicitely the same side effect. It depends on the value of color,
-                // which is an inherited value, making the non-inherited property implicitly inherited.
-                if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).valueID() == CSSValueCurrentcolor) {
-                    isCacheable = false;
-                    break;
-                }
-
-                if (value.hasVariableReferences()) {
-                    isCacheable = false;
-                    break;
-                }
-            }
-        }
-    }
-}
-
 StyleResolver::StyleResolver(Document& document)
     : m_ruleSets(*this)
     , m_matchedPropertiesCacheSweepTimer(*this, &StyleResolver::sweepMatchedPropertiesCache)
@@ -275,20 +227,18 @@ void StyleResolver::sweepMatchedPropertiesCache()
     // Look for cache entries containing a style declaration with a single ref and remove them.
     // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
     // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
-    Vector<unsigned, 16> toRemove;
-    MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
-    MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
-    for (; it != end; ++it) {
-        Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
-        for (size_t i = 0; i < matchedProperties.size(); ++i) {
-            if (matchedProperties[i].properties->hasOneRef()) {
-                toRemove.append(it->key);
-                break;
-            }
+    auto hasOneRef = [](auto& declarations) {
+        for (auto& matchedProperties : declarations) {
+            if (matchedProperties.properties->hasOneRef())
+                return true;
         }
-    }
-    for (size_t i = 0; i < toRemove.size(); ++i)
-        m_matchedPropertiesCache.remove(toRemove[i]);
+        return false;
+    };
+
+    m_matchedPropertiesCache.removeIf([&](auto& keyValue) {
+        auto& entry = keyValue.value;
+        return hasOneRef(entry.userAgentDeclarations) || hasOneRef(entry.userDeclarations) || hasOneRef(entry.authorDeclarations);
+    });
 
     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
 }
@@ -389,7 +339,7 @@ ElementStyle StyleResolver::styleForElement(const Element& element, const Render
 
     auto elementStyleRelations = Style::commitRelationsToRenderStyle(style, element, collector.styleRelations());
 
-    applyMatchedProperties(collector.matchedResult(), element);
+    applyMatchedProperties(collector.matchResult(), element);
 
     // Clean up our style object's display and text decorations (among other fixups).
     adjustRenderStyle(*state.style(), *state.parentStyle(), parentBoxStyle, &element);
@@ -407,7 +357,7 @@ std::unique_ptr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle*
     RELEASE_ASSERT(!m_isDeleted);
 
     MatchResult result;
-    result.addMatchedProperties(keyframe->properties());
+    result.authorDeclarations.append({ &keyframe->properties() });
 
     ASSERT(!m_state.style());
 
@@ -424,7 +374,7 @@ std::unique_ptr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle*
     // We don't need to bother with !important. Since there is only ever one
     // decl, there's nothing to override. So just add the first properties.
     CascadedProperties cascade(direction, writingMode);
-    cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1);
+    cascade.addNormalMatches(result, CascadeLevel::AuthorLevel);
 
     ApplyCascadedPropertyState applyState { this, &cascade, &result };
     applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
@@ -590,12 +540,12 @@ std::unique_ptr<RenderStyle> StyleResolver::pseudoStyleForElement(const Element&
 
     ASSERT(!collector.matchedPseudoElementIds());
 
-    if (collector.matchedResult().matchedProperties().isEmpty())
+    if (collector.matchResult().isEmpty())
         return nullptr;
 
     state.style()->setStyleType(pseudoStyleRequest.pseudoId);
 
-    applyMatchedProperties(collector.matchedResult(), element);
+    applyMatchedProperties(collector.matchResult(), element);
 
     // Clean up our style object's display and text decorations (among other fixups).
     adjustRenderStyle(*state.style(), *m_state.parentStyle(), nullptr, nullptr);
@@ -623,14 +573,14 @@ std::unique_ptr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
     PageRuleCollector collector(m_state, m_ruleSets);
     collector.matchAllPageRules(pageIndex);
 
-    MatchResult& result = collector.matchedResult();
+    auto& result = collector.matchResult();
 
     TextDirection direction;
     WritingMode writingMode;
     extractDirectionAndWritingMode(*m_state.style(), result, direction, writingMode);
 
     CascadedProperties cascade(direction, writingMode);
-    cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1);
+    cascade.addNormalMatches(result, CascadeLevel::AuthorLevel);
 
     ApplyCascadedPropertyState applyState { this, &cascade, &result };
     applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
@@ -1319,34 +1269,11 @@ static bool elementTypeHasAppearanceFromUAStyle(const Element& element)
         || localName == HTMLNames::meterTag;
 }
 
-unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
-{
-    return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
-}
-
-bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
-{
-    return a.firstUARule == b.firstUARule
-        && a.lastUARule == b.lastUARule
-        && a.firstAuthorRule == b.firstAuthorRule
-        && a.lastAuthorRule == b.lastAuthorRule
-        && a.firstUserRule == b.firstUserRule
-        && a.lastUserRule == b.lastUserRule;
-}
-
-bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
-{
-    return !(a == b);
-}
-
-bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
+unsigned StyleResolver::computeMatchedPropertiesHash(const MatchResult& matchResult)
 {
-    return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
-}
-
-bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
-{
-    return !(a == b);
+    return StringHasher::hashMemory(matchResult.userAgentDeclarations.data(), sizeof(MatchedProperties) * matchResult.userAgentDeclarations.size())
+        ^ StringHasher::hashMemory(matchResult.userDeclarations.data(), sizeof(MatchedProperties) * matchResult.userDeclarations.size())
+        ^ StringHasher::hashMemory(matchResult.authorDeclarations.data(), sizeof(MatchedProperties) * matchResult.authorDeclarations.size());
 }
 
 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
@@ -1356,17 +1283,11 @@ const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedP
     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
     if (it == m_matchedPropertiesCache.end())
         return nullptr;
-    MatchedPropertiesCacheItem& cacheItem = it->value;
 
-    size_t size = matchResult.matchedProperties().size();
-    if (size != cacheItem.matchedProperties.size())
-        return nullptr;
-    for (size_t i = 0; i < size; ++i) {
-        if (matchResult.matchedProperties()[i] != cacheItem.matchedProperties[i])
-            return nullptr;
-    }
-    if (cacheItem.ranges != matchResult.ranges)
+    auto& cacheItem = it->value;
+    if (matchResult.userAgentDeclarations != cacheItem.userAgentDeclarations || matchResult.userDeclarations != cacheItem.userDeclarations || matchResult.authorDeclarations != cacheItem.authorDeclarations)
         return nullptr;
+
     return &cacheItem;
 }
 
@@ -1423,7 +1344,7 @@ static bool isCacheableInMatchedPropertiesCache(const Element& element, const Re
     return true;
 }
 
-void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolver::MatchResult& matchResult, TextDirection& direction, WritingMode& writingMode)
+void extractDirectionAndWritingMode(const RenderStyle& style, const MatchResult& matchResult, TextDirection& direction, WritingMode& writingMode)
 {
     direction = style.direction();
     writingMode = style.writingMode();
@@ -1431,26 +1352,28 @@ void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolve
     bool hadImportantWritingMode = false;
     bool hadImportantDirection = false;
 
-    for (const auto& matchedProperties : matchResult.matchedProperties()) {
-        for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) {
-            auto property = matchedProperties.properties->propertyAt(i);
-            if (!property.value()->isPrimitiveValue())
-                continue;
-            switch (property.id()) {
-            case CSSPropertyWritingMode:
-                if (!hadImportantWritingMode || property.isImportant()) {
-                    writingMode = downcast<CSSPrimitiveValue>(*property.value());
-                    hadImportantWritingMode = property.isImportant();
-                }
-                break;
-            case CSSPropertyDirection:
-                if (!hadImportantDirection || property.isImportant()) {
-                    direction = downcast<CSSPrimitiveValue>(*property.value());
-                    hadImportantDirection = property.isImportant();
+    for (auto* matchedDeclarations : { &matchResult.userAgentDeclarations, &matchResult.userDeclarations, &matchResult.authorDeclarations }) {
+        for (const auto& matchedProperties : *matchedDeclarations) {
+            for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) {
+                auto property = matchedProperties.properties->propertyAt(i);
+                if (!property.value()->isPrimitiveValue())
+                    continue;
+                switch (property.id()) {
+                case CSSPropertyWritingMode:
+                    if (!hadImportantWritingMode || property.isImportant()) {
+                        writingMode = downcast<CSSPrimitiveValue>(*property.value());
+                        hadImportantWritingMode = property.isImportant();
+                    }
+                    break;
+                case CSSPropertyDirection:
+                    if (!hadImportantDirection || property.isImportant()) {
+                        direction = downcast<CSSPrimitiveValue>(*property.value());
+                        hadImportantDirection = property.isImportant();
+                    }
+                    break;
+                default:
+                    break;
                 }
-                break;
-            default:
-                break;
             }
         }
     }
@@ -1459,7 +1382,7 @@ void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolve
 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element& element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache)
 {
     State& state = m_state;
-    unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties().data(), matchResult.matchedProperties().size()) : 0;
+    unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult) : 0;
     bool applyInheritedOnly = false;
     const MatchedPropertiesCacheItem* cacheItem = nullptr;
     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))
@@ -1493,8 +1416,8 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
         // If so, we cache the border and background styles so that RenderTheme::adjustStyle()
         // can look at them later to figure out if this is a styled form control or not.
         CascadedProperties cascade(direction, writingMode);
-        cascade.addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
-        cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
+        cascade.addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
+        cascade.addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
 
         ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
 
@@ -1520,10 +1443,12 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
     }
 
     CascadedProperties cascade(direction, writingMode);
-    cascade.addNormalMatches(matchResult, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly);
-    cascade.addImportantMatches(matchResult, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
-    cascade.addImportantMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
-    cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
+    cascade.addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
+    cascade.addNormalMatches(matchResult, CascadeLevel::UserLevel, applyInheritedOnly);
+    cascade.addNormalMatches(matchResult, CascadeLevel::AuthorLevel, applyInheritedOnly);
+    cascade.addImportantMatches(matchResult, CascadeLevel::AuthorLevel, applyInheritedOnly);
+    cascade.addImportantMatches(matchResult, CascadeLevel::UserLevel, applyInheritedOnly);
+    cascade.addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, applyInheritedOnly);
 
     ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
 
@@ -1719,10 +1644,10 @@ StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(
         auto newAuthorRollback(makeUnique<CascadedProperties>(direction, writingMode));
 
         // This special rollback cascade contains UA rules and user rules but no author rules.
-        newAuthorRollback->addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
-        newAuthorRollback->addNormalMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
-        newAuthorRollback->addImportantMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
-        newAuthorRollback->addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+        newAuthorRollback->addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, false);
+        newAuthorRollback->addNormalMatches(matchResult, CascadeLevel::UserLevel, false);
+        newAuthorRollback->addImportantMatches(matchResult, CascadeLevel::UserLevel, false);
+        newAuthorRollback->addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, false);
 
         state().setAuthorRollback(newAuthorRollback);
         return state().authorRollback();
@@ -1736,8 +1661,8 @@ StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(
         auto newUserRollback(makeUnique<CascadedProperties>(direction, writingMode));
 
         // This special rollback cascade contains only UA rules.
-        newUserRollback->addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
-        newUserRollback->addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+        newUserRollback->addNormalMatches(matchResult, CascadeLevel::UserAgentLevel, false);
+        newUserRollback->addImportantMatches(matchResult, CascadeLevel::UserAgentLevel, false);
 
         state().setUserRollback(newUserRollback);
         return state().userRollback();
@@ -2210,10 +2135,6 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
     return true;
 }
 
-inline StyleResolver::MatchedProperties::MatchedProperties() = default;
-
-StyleResolver::MatchedProperties::~MatchedProperties() = default;
-
 StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
     : m_direction(direction)
     , m_writingMode(writingMode)
@@ -2299,22 +2220,11 @@ void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue&
     m_deferredProperties.append(property);
 }
 
-static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult& matchResult, int index)
-{
-    if (index >= matchResult.ranges.firstUARule && index <= matchResult.ranges.lastUARule)
-        return CascadeLevel::UserAgentLevel;
-    if (index >= matchResult.ranges.firstUserRule && index <= matchResult.ranges.lastUserRule)
-        return CascadeLevel::UserLevel;
-    return CascadeLevel::AuthorLevel;
-}
 
-void StyleResolver::CascadedProperties::addMatch(const MatchResult& matchResult, unsigned index, bool isImportant, bool inheritedOnly)
+void StyleResolver::CascadedProperties::addMatch(const MatchedProperties& matchedProperties, CascadeLevel cascadeLevel, bool isImportant, bool inheritedOnly)
 {
-    auto& matchedProperties = matchResult.matchedProperties()[index];
     auto& styleProperties = *matchedProperties.properties;
-
     auto propertyWhitelistType = static_cast<PropertyWhitelistType>(matchedProperties.whitelistType);
-    auto cascadeLevel = cascadeLevelForIndex(matchResult, index);
 
     for (unsigned i = 0, count = styleProperties.propertyCount(); i < count; ++i) {
         auto current = styleProperties.propertyAt(i);
@@ -2342,13 +2252,22 @@ void StyleResolver::CascadedProperties::addMatch(const MatchResult& matchResult,
     }
 }
 
-void StyleResolver::CascadedProperties::addNormalMatches(const MatchResult& matchResult, int startIndex, int endIndex, bool inheritedOnly)
+
+static auto& declarationsForCascadeLevel(const MatchResult& matchResult, CascadeLevel cascadeLevel)
 {
-    if (startIndex == -1)
-        return;
+    switch (cascadeLevel) {
+    case CascadeLevel::UserAgentLevel: return matchResult.userAgentDeclarations;
+    case CascadeLevel::UserLevel: return matchResult.userDeclarations;
+    case CascadeLevel::AuthorLevel: return matchResult.authorDeclarations;
+    }
+    ASSERT_NOT_REACHED();
+    return matchResult.authorDeclarations;
+}
 
-    for (int i = startIndex; i <= endIndex; ++i)
-        addMatch(matchResult, i, false, inheritedOnly);
+void StyleResolver::CascadedProperties::addNormalMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
+{
+    for (auto& matchedDeclarations : declarationsForCascadeLevel(matchResult, cascadeLevel))
+        addMatch(matchedDeclarations, cascadeLevel, false, inheritedOnly);
 }
 
 static bool hasImportantProperties(const StyleProperties& properties)
@@ -2360,20 +2279,19 @@ static bool hasImportantProperties(const StyleProperties& properties)
     return false;
 }
 
-void StyleResolver::CascadedProperties::addImportantMatches(const MatchResult& matchResult, int startIndex, int endIndex, bool inheritedOnly)
+void StyleResolver::CascadedProperties::addImportantMatches(const MatchResult& matchResult, CascadeLevel cascadeLevel, bool inheritedOnly)
 {
-    if (startIndex == -1)
-        return;
-
     struct IndexAndOrdinal {
-        int index;
+        unsigned index;
         Style::ScopeOrdinal ordinal;
     };
     Vector<IndexAndOrdinal> importantMatches;
     bool hasMatchesFromOtherScopes = false;
 
-    for (int i = startIndex; i <= endIndex; ++i) {
-        const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i];
+    auto& matchedDeclarations = declarationsForCascadeLevel(matchResult, cascadeLevel);
+
+    for (unsigned i = 0; i < matchedDeclarations.size(); ++i) {
+        const MatchedProperties& matchedProperties = matchedDeclarations[i];
 
         if (!hasImportantProperties(*matchedProperties.properties))
             continue;
@@ -2396,7 +2314,7 @@ void StyleResolver::CascadedProperties::addImportantMatches(const MatchResult& m
     }
 
     for (auto& match : importantMatches)
-        addMatch(matchResult, match.index, true, inheritedOnly);
+        addMatch(matchedDeclarations[match.index], cascadeLevel, true, inheritedOnly);
 }
 
 void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
index 52941ba..905d2a3 100644 (file)
@@ -25,6 +25,7 @@
 #include "CSSToLengthConversionData.h"
 #include "CSSToStyleMap.h"
 #include "DocumentRuleSets.h"
+#include "ElementRuleCollector.h"
 #include "InspectorCSSOMWrappers.h"
 #include "MediaQueryEvaluator.h"
 #include "RenderStyle.h"
@@ -99,18 +100,6 @@ enum class CascadeLevel: uint8_t {
     UserLevel
 };
 
-class PseudoStyleRequest {
-public:
-    PseudoStyleRequest(PseudoId pseudoId, Optional<StyleScrollbarState> scrollbarState = WTF::nullopt)
-        : pseudoId(pseudoId)
-        , scrollbarState(scrollbarState)
-    {
-    }
-
-    PseudoId pseudoId;
-    Optional<StyleScrollbarState> scrollbarState;
-};
-
 struct ElementStyle {
     ElementStyle(std::unique_ptr<RenderStyle> renderStyle, std::unique_ptr<Style::Relations> relations = { })
         : renderStyle(WTFMove(renderStyle))
@@ -175,8 +164,6 @@ public:
     Vector<RefPtr<StyleRule>> pseudoStyleRulesForElement(const Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
 
 public:
-    struct MatchResult;
-
     void applyPropertyToStyle(CSSPropertyID, CSSValue*, std::unique_ptr<RenderStyle>);
     void applyPropertyToCurrentStyle(CSSPropertyID, CSSValue*);
 
@@ -221,48 +208,6 @@ public:
     void clearCachedPropertiesAffectedByViewportUnits();
 
     bool createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations);
-
-    struct RuleRange {
-        RuleRange(int& firstRuleIndex, int& lastRuleIndex): firstRuleIndex(firstRuleIndex), lastRuleIndex(lastRuleIndex) { }
-        int& firstRuleIndex;
-        int& lastRuleIndex;
-    };
-
-    struct MatchRanges {
-        MatchRanges() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1) { }
-        int firstUARule;
-        int lastUARule;
-        int firstAuthorRule;
-        int lastAuthorRule;
-        int firstUserRule;
-        int lastUserRule;
-        RuleRange UARuleRange() { return RuleRange(firstUARule, lastUARule); }
-        RuleRange authorRuleRange() { return RuleRange(firstAuthorRule, lastAuthorRule); }
-        RuleRange userRuleRange() { return RuleRange(firstUserRule, lastUserRule); }
-    };
-
-    struct MatchedProperties {
-        MatchedProperties();
-        ~MatchedProperties();
-        
-        RefPtr<StyleProperties> properties;
-        uint16_t linkMatchType;
-        uint16_t whitelistType;
-        Style::ScopeOrdinal styleScopeOrdinal;
-    };
-
-    struct MatchResult {
-        MatchResult() : isCacheable(true) { }
-        Vector<StyleRule*, 64> matchedRules;
-        MatchRanges ranges;
-        bool isCacheable;
-
-        const Vector<MatchedProperties, 64>& matchedProperties() const { return m_matchedProperties; }
-
-        void addMatchedProperties(const StyleProperties&, StyleRule* = nullptr, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone, Style::ScopeOrdinal = Style::ScopeOrdinal::Element);
-    private:
-        Vector<MatchedProperties, 64> m_matchedProperties;
-    };
     
     class CascadedProperties {
         WTF_MAKE_FAST_ALLOCATED;
@@ -281,8 +226,8 @@ public:
         bool hasProperty(CSSPropertyID) const;
         Property& property(CSSPropertyID);
 
-        void addNormalMatches(const MatchResult&, int startIndex, int endIndex, bool inheritedOnly = false);
-        void addImportantMatches(const MatchResult&, int startIndex, int endIndex, bool inheritedOnly = false);
+        void addNormalMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
+        void addImportantMatches(const MatchResult&, CascadeLevel, bool inheritedOnly = false);
 
         void applyDeferredProperties(StyleResolver&, ApplyCascadedPropertyState&);
 
@@ -291,7 +236,7 @@ public:
         Property customProperty(const String&) const;
         
     private:
-        void addMatch(const MatchResult&, unsigned index, bool isImportant, bool inheritedOnly);
+        void addMatch(const MatchedProperties&, CascadeLevel, bool isImportant, bool inheritedOnly);
         void set(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
         void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
         static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, Style::ScopeOrdinal);
@@ -335,14 +280,6 @@ private:
 
     void cascadeMatches(CascadedProperties&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
 
-    void matchPageRules(MatchResult&, RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
-    void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>&, bool isLeftPage, bool isFirstPage, const String& pageName);
-
-    bool isLeftPage(int pageIndex) const;
-    bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
-    bool isFirstPage(int pageIndex) const;
-    String pageName(int pageIndex) const;
-
     DocumentRuleSets m_ruleSets;
 
     typedef HashMap<AtomStringImpl*, RefPtr<StyleRuleKeyframes>> KeyframesRuleMap;
@@ -477,20 +414,22 @@ private:
 
     void applySVGProperty(CSSPropertyID, CSSValue*);
 
-    static unsigned computeMatchedPropertiesHash(const MatchedProperties*, unsigned size);
+    static unsigned computeMatchedPropertiesHash(const MatchResult&);
     struct MatchedPropertiesCacheItem {
-        Vector<MatchedProperties> matchedProperties;
-        MatchRanges ranges;
+        Vector<MatchedProperties> userAgentDeclarations;
+        Vector<MatchedProperties> userDeclarations;
+        Vector<MatchedProperties> authorDeclarations;
         std::unique_ptr<RenderStyle> renderStyle;
         std::unique_ptr<RenderStyle> parentRenderStyle;
         
         MatchedPropertiesCacheItem(const MatchResult& matchResult, const RenderStyle* style, const RenderStyle* parentStyle)
-            : ranges(matchResult.ranges)
-            , renderStyle(RenderStyle::clonePtr(*style))
+            : renderStyle(RenderStyle::clonePtr(*style))
             , parentRenderStyle(RenderStyle::clonePtr(*parentStyle))
         {
             // Assign rather than copy-construct so we only allocate as much vector capacity as needed.
-            matchedProperties = matchResult.matchedProperties();
+            userAgentDeclarations = matchResult.userAgentDeclarations;
+            userDeclarations = matchResult.userDeclarations;
+            authorDeclarations = matchResult.authorDeclarations;
         }
         MatchedPropertiesCacheItem() = default;
     };
@@ -531,11 +470,6 @@ private:
     bool m_matchAuthorAndUserStyles { true };
     // See if we still have crashes where StyleResolver gets deleted early.
     bool m_isDeleted { false };
-
-    friend bool operator==(const MatchedProperties&, const MatchedProperties&);
-    friend bool operator!=(const MatchedProperties&, const MatchedProperties&);
-    friend bool operator==(const MatchRanges&, const MatchRanges&);
-    friend bool operator!=(const MatchRanges&, const MatchRanges&);
 };
 
 // State to use when applying properties, to keep track of which custom and high-priority
@@ -543,7 +477,7 @@ private:
 struct ApplyCascadedPropertyState {
     StyleResolver* styleResolver;
     StyleResolver::CascadedProperties* cascade;
-    const StyleResolver::MatchResult* matchResult;
+    const MatchResult* matchResult;
     Bitmap<numCSSProperties> appliedProperties = { };
     HashSet<String> appliedCustomProperties = { };
     Bitmap<numCSSProperties> inProgressProperties = { };