ElementRuleCollector function signature cleanups
https://bugs.webkit.org/show_bug.cgi?id=203153

Reviewed by Zalan Bujtas.

Many functions in ElementRuleCollector take repetitive arguments that can be removed:

- Make includeEmptyRules argument a class member
- Remove RuleRange argument, update the ranges in rule transfer step.

* css/ElementRuleCollector.cpp:
(WebCore::MatchRequest::MatchRequest):
(WebCore::ElementRuleCollector::addMatchedRule):
(WebCore::ElementRuleCollector::collectMatchingRules):
(WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
(WebCore::ElementRuleCollector::transferMatchedRules):
(WebCore::ElementRuleCollector::matchAuthorRules):
(WebCore::ElementRuleCollector::matchesAnyAuthorRules):
(WebCore::ElementRuleCollector::collectMatchingAuthorRules):
(WebCore::ElementRuleCollector::matchAuthorShadowPseudoElementRules):
(WebCore::ElementRuleCollector::matchHostPseudoClassRules):
(WebCore::ElementRuleCollector::matchSlottedPseudoElementRules):
(WebCore::ElementRuleCollector::matchPartPseudoElementRules):
(WebCore::ElementRuleCollector::matchPartPseudoElementRulesForScope):
(WebCore::ElementRuleCollector::collectMatchingShadowPseudoElementRules):
(WebCore::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot):
(WebCore::ElementRuleCollector::matchUserRules):
(WebCore::ElementRuleCollector::matchUARules):
(WebCore::ElementRuleCollector::collectMatchingRulesForList):
(WebCore::ElementRuleCollector::matchAllRules):
(WebCore::ElementRuleCollector::hasAnyMatchingRules):
* css/ElementRuleCollector.h:
(WebCore::ElementRuleCollector::setIncludeEmptyRules):
(WebCore::ElementRuleCollector::transferMatchedRules):

Range update happens now here based on the supplied argument.

* css/StyleResolver.cpp:
(WebCore::StyleResolver::pseudoStyleForElement):
(WebCore::StyleResolver::pseudoStyleRulesForElement):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251289 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 7a091d1..485648d 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,48 @@
 2019-10-18  Antti Koivisto  <antti@apple.com>
 
+        ElementRuleCollector function signature cleanups
+        https://bugs.webkit.org/show_bug.cgi?id=203153
+
+        Reviewed by Zalan Bujtas.
+
+        Many functions in ElementRuleCollector take repetitive arguments that can be removed:
+
+        - Make includeEmptyRules argument a class member
+        - Remove RuleRange argument, update the ranges in rule transfer step.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::MatchRequest::MatchRequest):
+        (WebCore::ElementRuleCollector::addMatchedRule):
+        (WebCore::ElementRuleCollector::collectMatchingRules):
+        (WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
+        (WebCore::ElementRuleCollector::transferMatchedRules):
+        (WebCore::ElementRuleCollector::matchAuthorRules):
+        (WebCore::ElementRuleCollector::matchesAnyAuthorRules):
+        (WebCore::ElementRuleCollector::collectMatchingAuthorRules):
+        (WebCore::ElementRuleCollector::matchAuthorShadowPseudoElementRules):
+        (WebCore::ElementRuleCollector::matchHostPseudoClassRules):
+        (WebCore::ElementRuleCollector::matchSlottedPseudoElementRules):
+        (WebCore::ElementRuleCollector::matchPartPseudoElementRules):
+        (WebCore::ElementRuleCollector::matchPartPseudoElementRulesForScope):
+        (WebCore::ElementRuleCollector::collectMatchingShadowPseudoElementRules):
+        (WebCore::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot):
+        (WebCore::ElementRuleCollector::matchUserRules):
+        (WebCore::ElementRuleCollector::matchUARules):
+        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
+        (WebCore::ElementRuleCollector::matchAllRules):
+        (WebCore::ElementRuleCollector::hasAnyMatchingRules):
+        * css/ElementRuleCollector.h:
+        (WebCore::ElementRuleCollector::setIncludeEmptyRules):
+        (WebCore::ElementRuleCollector::transferMatchedRules):
+
+        Range update happens now here based on the supplied argument.
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::pseudoStyleForElement):
+        (WebCore::StyleResolver::pseudoStyleRulesForElement):
+x
+2019-10-18  Antti Koivisto  <antti@apple.com>
+
         [CSS Shadow Parts] :part rules should be able to override style attribute
         https://bugs.webkit.org/show_bug.cgi?id=202919
 
diff --git a/Source/WebCore/css/ElementRuleCollector.cpp b/Source/WebCore/css/ElementRuleCollector.cpp
index 8a6c871..cd9ebce 100644
--- a/Source/WebCore/css/ElementRuleCollector.cpp
+++ b/Source/WebCore/css/ElementRuleCollector.cpp
@@ -68,14 +68,12 @@
 
 class MatchRequest {
 public:
-    MatchRequest(const RuleSet* ruleSet, bool includeEmptyRules = false, Style::ScopeOrdinal styleScopeOrdinal = Style::ScopeOrdinal::Element)
+    MatchRequest(const RuleSet* ruleSet, Style::ScopeOrdinal styleScopeOrdinal = Style::ScopeOrdinal::Element)
         : ruleSet(ruleSet)
-        , includeEmptyRules(includeEmptyRules)
         , styleScopeOrdinal(styleScopeOrdinal)
     {
     }
     const RuleSet* ruleSet;
-    const bool includeEmptyRules;
     Style::ScopeOrdinal styleScopeOrdinal;
 };
 
@@ -109,16 +107,8 @@
     return m_matchedRuleList;
 }
 
-inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, Style::ScopeOrdinal styleScopeOrdinal, StyleResolver::RuleRange& ruleRange)
+inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, Style::ScopeOrdinal styleScopeOrdinal)
 {
-    // Update our first/last rule indices in the matched rules array.
-    if (ruleRange.lastRuleIndex != -1)
-        ++ruleRange.lastRuleIndex;
-    else {
-        ruleRange.lastRuleIndex = m_result.matchedProperties().size();
-        ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
-    }
-
     m_matchedRules.append({ &ruleData, specificity, styleScopeOrdinal });
 }
 
@@ -146,45 +136,62 @@
         m_result.isCacheable = false;
 }
 
-void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest)
 {
     ASSERT(matchRequest.ruleSet);
     ASSERT_WITH_MESSAGE(!(m_mode == SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements && m_pseudoStyleRequest.pseudoId != PseudoId::None), "When in StyleInvalidation or SharingRules, SelectorChecker does not try to match the pseudo ID. While ElementRuleCollector supports matching a particular pseudoId in this case, this would indicate a error at the call site since matching a particular element should be unnecessary.");
 
     auto* shadowRoot = element().containingShadowRoot();
     if (shadowRoot && shadowRoot->mode() == ShadowRootMode::UserAgent)
-        collectMatchingShadowPseudoElementRules(matchRequest, ruleRange);
+        collectMatchingShadowPseudoElementRules(matchRequest);
 
     // We need to collect the rules for id, class, tag, and everything else into a buffer and
     // then sort the buffer.
     auto& id = element().idForStyleResolution();
     if (!id.isNull())
-        collectMatchingRulesForList(matchRequest.ruleSet->idRules(id), matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->idRules(id), matchRequest);
     if (element().hasClass()) {
         for (size_t i = 0; i < element().classNames().size(); ++i)
-            collectMatchingRulesForList(matchRequest.ruleSet->classRules(element().classNames()[i]), matchRequest, ruleRange);
+            collectMatchingRulesForList(matchRequest.ruleSet->classRules(element().classNames()[i]), matchRequest);
     }
 
     if (element().isLink())
-        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest);
     if (SelectorChecker::matchesFocusPseudoClass(element()))
-        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest);
+    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element().localName(), element().isHTMLElement() && element().document().isHTMLDocument()), matchRequest);
+    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest);
 }
 
-void ElementRuleCollector::sortAndTransferMatchedRules()
+void ElementRuleCollector::sortAndTransferMatchedRules(DeclarationOrigin declarationOrigin)
 {
     if (m_matchedRules.isEmpty())
         return;
 
     sortMatchedRules();
 
-    transferMatchedRules();
+    transferMatchedRules(declarationOrigin);
 }
 
-void ElementRuleCollector::transferMatchedRules(Optional<Style::ScopeOrdinal> fromScope)
+void ElementRuleCollector::transferMatchedRules(DeclarationOrigin declarationOrigin, Optional<Style::ScopeOrdinal> fromScope)
 {
+    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();
+        }
+    }();
+
+    // 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)
@@ -197,15 +204,18 @@
 
         m_result.addMatchedProperties(matchedRule.ruleData->rule()->properties(), matchedRule.ruleData->rule(), matchedRule.ruleData->linkMatchType(), matchedRule.ruleData->propertyWhitelistType(), matchedRule.styleScopeOrdinal);
     }
+
+    if (updateRanges)
+        rangeForDeclarationOrigin.lastRuleIndex = m_result.matchedRules.size() - 1;
 }
 
-void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules)
+void ElementRuleCollector::matchAuthorRules()
 {
     clearMatchedRules();
 
-    collectMatchingAuthorRules(includeEmptyRules);
+    collectMatchingAuthorRules();
 
-    sortAndTransferMatchedRules();
+    sortAndTransferMatchedRules(DeclarationOrigin::Author);
 }
 
 bool ElementRuleCollector::matchesAnyAuthorRules()
@@ -213,34 +223,32 @@
     clearMatchedRules();
 
     // FIXME: This should bail out on first match.
-    collectMatchingAuthorRules(false);
+    collectMatchingAuthorRules();
 
     return !m_matchedRules.isEmpty();
 }
 
-void ElementRuleCollector::collectMatchingAuthorRules(bool includeEmptyRules)
+void ElementRuleCollector::collectMatchingAuthorRules()
 {
-    StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
-
     {
-        MatchRequest matchRequest(&m_authorStyle, includeEmptyRules);
-        collectMatchingRules(matchRequest, ruleRange);
+        MatchRequest matchRequest(&m_authorStyle);
+        collectMatchingRules(matchRequest);
     }
 
     auto* parent = element().parentElement();
     if (parent && parent->shadowRoot())
-        matchSlottedPseudoElementRules(includeEmptyRules, ruleRange);
+        matchSlottedPseudoElementRules();
 
     if (element().shadowRoot())
-        matchHostPseudoClassRules(includeEmptyRules, ruleRange);
+        matchHostPseudoClassRules();
 
     if (element().isInShadowTree()) {
-        matchAuthorShadowPseudoElementRules(includeEmptyRules, ruleRange);
-        matchPartPseudoElementRules(includeEmptyRules, ruleRange);
+        matchAuthorShadowPseudoElementRules();
+        matchPartPseudoElementRules();
     }
 }
 
-void ElementRuleCollector::matchAuthorShadowPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchAuthorShadowPseudoElementRules()
 {
     ASSERT(element().isInShadowTree());
     auto& shadowRoot = *element().containingShadowRoot();
@@ -248,11 +256,11 @@
         return;
     // Look up shadow pseudo elements also from the host scope author style as they are web-exposed.
     auto& hostAuthorRules = Style::Scope::forNode(*shadowRoot.host()).resolver().ruleSets().authorStyle();
-    MatchRequest hostAuthorRequest { &hostAuthorRules, includeEmptyRules, Style::ScopeOrdinal::ContainingHost };
-    collectMatchingShadowPseudoElementRules(hostAuthorRequest, ruleRange);
+    MatchRequest hostAuthorRequest { &hostAuthorRules, Style::ScopeOrdinal::ContainingHost };
+    collectMatchingShadowPseudoElementRules(hostAuthorRequest);
 }
 
-void ElementRuleCollector::matchHostPseudoClassRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchHostPseudoClassRules()
 {
     ASSERT(element().shadowRoot());
 
@@ -263,11 +271,11 @@
 
     SetForScope<bool> change(m_isMatchingHostPseudoClass, true);
 
-    MatchRequest hostMatchRequest { nullptr, includeEmptyRules, Style::ScopeOrdinal::Shadow };
-    collectMatchingRulesForList(&shadowHostRules, hostMatchRequest, ruleRange);
+    MatchRequest hostMatchRequest { nullptr, Style::ScopeOrdinal::Shadow };
+    collectMatchingRulesForList(&shadowHostRules, hostMatchRequest);
 }
 
-void ElementRuleCollector::matchSlottedPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchSlottedPseudoElementRules()
 {
     auto* slot = element().assignedSlot();
     auto styleScopeOrdinal = Style::ScopeOrdinal::FirstSlot;
@@ -279,20 +287,20 @@
         // Find out if there are any ::slotted rules in the shadow tree matching the current slot.
         // FIXME: This is really part of the slot style and could be cached when resolving it.
         ElementRuleCollector collector(*slot, styleScope.resolver().ruleSets().authorStyle(), nullptr);
-        auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot(includeEmptyRules);
+        auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot();
         if (!slottedPseudoElementRules)
             continue;
         // Match in the current scope.
         SetForScope<bool> change(m_isMatchingSlottedPseudoElements, true);
 
-        MatchRequest scopeMatchRequest(nullptr, includeEmptyRules, styleScopeOrdinal);
-        collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest, ruleRange);
+        MatchRequest scopeMatchRequest(nullptr, styleScopeOrdinal);
+        collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest);
 
         m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules));
     }
 }
 
-void ElementRuleCollector::matchPartPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchPartPseudoElementRules()
 {
     ASSERT(element().isInShadowTree());
 
@@ -302,18 +310,18 @@
     if (partMatchingElement.partNames().isEmpty() || !partMatchingElement.isInShadowTree())
         return;
 
-    matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot(), includeEmptyRules, ruleRange);
+    matchPartPseudoElementRulesForScope(*partMatchingElement.containingShadowRoot());
 }
 
-void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot)
 {
     auto& shadowHost = *scopeShadowRoot.host();
     {
         SetForScope<RefPtr<const Element>> partMatchingScope(m_shadowHostInPartRuleScope, &shadowHost);
 
         auto& hostAuthorRules = Style::Scope::forNode(shadowHost).resolver().ruleSets().authorStyle();
-        MatchRequest hostAuthorRequest { &hostAuthorRules, includeEmptyRules, Style::ScopeOrdinal::ContainingHost };
-        collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), hostAuthorRequest, ruleRange);
+        MatchRequest hostAuthorRequest { &hostAuthorRules, Style::ScopeOrdinal::ContainingHost };
+        collectMatchingRulesForList(&hostAuthorRules.partPseudoElementRules(), hostAuthorRequest);
     }
 
     // Element may be exposed to styling from enclosing scopes via exportparts attributes.
@@ -321,10 +329,10 @@
         return;
 
     if (auto* parentScopeShadowRoot = shadowHost.containingShadowRoot())
-        matchPartPseudoElementRulesForScope(*parentScopeShadowRoot, includeEmptyRules, ruleRange);
+        matchPartPseudoElementRulesForScope(*parentScopeShadowRoot);
 }
 
-void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::collectMatchingShadowPseudoElementRules(const MatchRequest& matchRequest)
 {
     ASSERT(matchRequest.ruleSet);
     ASSERT(element().containingShadowRoot()->mode() == ShadowRootMode::UserAgent);
@@ -333,14 +341,14 @@
 #if ENABLE(VIDEO_TRACK)
     // FXIME: WebVTT should not be done by styling UA shadow trees like this.
     if (element().isWebVTTElement())
-        collectMatchingRulesForList(rules.cuePseudoRules(), matchRequest, ruleRange);
+        collectMatchingRulesForList(rules.cuePseudoRules(), matchRequest);
 #endif
     auto& pseudoId = element().shadowPseudoId();
     if (!pseudoId.isEmpty())
-        collectMatchingRulesForList(rules.shadowPseudoElementRules(pseudoId), matchRequest, ruleRange);
+        collectMatchingRulesForList(rules.shadowPseudoElementRules(pseudoId), matchRequest);
 }
 
-std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules)
+std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot()
 {
     ASSERT(is<HTMLSlotElement>(element()));
 
@@ -349,9 +357,8 @@
     m_mode = SelectorChecker::Mode::CollectingRules;
 
     // Match global author rules.
-    MatchRequest matchRequest(&m_authorStyle, includeEmptyRules);
-    StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
-    collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest, ruleRange);
+    MatchRequest matchRequest(&m_authorStyle);
+    collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest);
 
     if (m_matchedRules.isEmpty())
         return { };
@@ -364,18 +371,17 @@
     return ruleDataVector;
 }
 
-void ElementRuleCollector::matchUserRules(bool includeEmptyRules)
+void ElementRuleCollector::matchUserRules()
 {
     if (!m_userStyle)
         return;
     
     clearMatchedRules();
 
-    MatchRequest matchRequest(m_userStyle, includeEmptyRules);
-    StyleResolver::RuleRange ruleRange = m_result.ranges.userRuleRange();
-    collectMatchingRules(matchRequest, ruleRange);
+    MatchRequest matchRequest(m_userStyle);
+    collectMatchingRules(matchRequest);
 
-    sortAndTransferMatchedRules();
+    sortAndTransferMatchedRules(DeclarationOrigin::User);
 }
 
 void ElementRuleCollector::matchUARules()
@@ -399,10 +405,9 @@
 {
     clearMatchedRules();
     
-    StyleResolver::RuleRange ruleRange = m_result.ranges.UARuleRange();
-    collectMatchingRules(MatchRequest(&rules), ruleRange);
+    collectMatchingRules(MatchRequest(&rules));
 
-    sortAndTransferMatchedRules();
+    sortAndTransferMatchedRules(DeclarationOrigin::UserAgent);
 }
 
 static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* selector)
@@ -514,7 +519,7 @@
     return selectorMatches;
 }
 
-void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVector* rules, const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+void ElementRuleCollector::collectMatchingRulesForList(const RuleSet::RuleDataVector* rules, const MatchRequest& matchRequest)
 {
     if (!rules)
         return;
@@ -534,12 +539,12 @@
         // Note that if we get null back here, it means we have a rule with deferred properties,
         // and that means we always have to consider it.
         const StyleProperties* properties = rule->propertiesWithoutDeferredParsing();
-        if (properties && properties->isEmpty() && !matchRequest.includeEmptyRules)
+        if (properties && properties->isEmpty() && !m_shouldIncludeEmptyRules)
             continue;
 
         unsigned specificity;
         if (ruleMatches(ruleData, specificity))
-            addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal, ruleRange);
+            addMatchedRule(ruleData, specificity, matchRequest.styleScopeOrdinal);
     }
 }
 
@@ -566,7 +571,7 @@
 
     // Now we check user sheet rules.
     if (matchAuthorAndUserStyles)
-        matchUserRules(false);
+        matchUserRules();
 
     // Now check author rules, beginning first with presentational attributes mapped from HTML.
     if (is<StyledElement>(element())) {
@@ -589,16 +594,16 @@
     if (matchAuthorAndUserStyles) {
         clearMatchedRules();
 
-        collectMatchingAuthorRules(false);
+        collectMatchingAuthorRules();
         sortMatchedRules();
 
-        transferMatchedRules(Style::ScopeOrdinal::Element);
+        transferMatchedRules(DeclarationOrigin::Author, Style::ScopeOrdinal::Element);
 
         // Inline style behaves as if it has higher specificity than any rule.
         addElementInlineStyleProperties(includeSMILProperties);
 
         // Rules from the host scope override inline style.
-        transferMatchedRules(Style::ScopeOrdinal::ContainingHost);
+        transferMatchedRules(DeclarationOrigin::Author, Style::ScopeOrdinal::ContainingHost);
     }
 }
 
@@ -622,9 +627,7 @@
     clearMatchedRules();
 
     m_mode = SelectorChecker::Mode::CollectingRulesIgnoringVirtualPseudoElements;
-    int firstRuleIndex = -1, lastRuleIndex = -1;
-    StyleResolver::RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
-    collectMatchingRules(MatchRequest(ruleSet), ruleRange);
+    collectMatchingRules(MatchRequest(ruleSet));
 
     return !m_matchedRules.isEmpty();
 }
diff --git a/Source/WebCore/css/ElementRuleCollector.h b/Source/WebCore/css/ElementRuleCollector.h
index 903fb89..1ddbfea 100644
--- a/Source/WebCore/css/ElementRuleCollector.h
+++ b/Source/WebCore/css/ElementRuleCollector.h
@@ -47,10 +47,12 @@
     ElementRuleCollector(const Element&, const DocumentRuleSets&, const SelectorFilter*);
     ElementRuleCollector(const Element&, const RuleSet& authorStyle, const SelectorFilter*);
 
+    void setIncludeEmptyRules(bool value) { m_shouldIncludeEmptyRules = value; }
+
     void matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties);
     void matchUARules();
-    void matchAuthorRules(bool includeEmptyRules);
-    void matchUserRules(bool includeEmptyRules);
+    void matchAuthorRules();
+    void matchUserRules();
 
     bool matchesAnyAuthorRules();
 
@@ -74,27 +76,29 @@
 
     void matchUARules(const RuleSet&);
 
-    void collectMatchingAuthorRules(bool includeEmptyRules);
+    void collectMatchingAuthorRules();
     void addElementInlineStyleProperties(bool includeSMILProperties);
 
-    void matchAuthorShadowPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
-    void matchHostPseudoClassRules(bool includeEmptyRules, StyleResolver::RuleRange&);
-    void matchSlottedPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
-    void matchPartPseudoElementRules(bool includeEmptyRules, StyleResolver::RuleRange&);
-    void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot, bool includeEmptyRules, StyleResolver::RuleRange&);
+    void matchAuthorShadowPseudoElementRules();
+    void matchHostPseudoClassRules();
+    void matchSlottedPseudoElementRules();
+    void matchPartPseudoElementRules();
+    void matchPartPseudoElementRulesForScope(const ShadowRoot& scopeShadowRoot);
 
-    void collectMatchingShadowPseudoElementRules(const MatchRequest&, StyleResolver::RuleRange&);
-    std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules);
+    void collectMatchingShadowPseudoElementRules(const MatchRequest&);
+    std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot();
 
-    void collectMatchingRules(const MatchRequest&, StyleResolver::RuleRange&);
-    void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&, StyleResolver::RuleRange&);
+    void collectMatchingRules(const MatchRequest&);
+    void collectMatchingRulesForList(const RuleSet::RuleDataVector*, const MatchRequest&);
     bool ruleMatches(const RuleData&, unsigned &specificity);
 
     void sortMatchedRules();
-    void sortAndTransferMatchedRules();
-    void transferMatchedRules(Optional<Style::ScopeOrdinal> forScope = { });
 
-    void addMatchedRule(const RuleData&, unsigned specificity, Style::ScopeOrdinal, StyleResolver::RuleRange&);
+    enum class DeclarationOrigin { UserAgent, Author, User };
+    void sortAndTransferMatchedRules(DeclarationOrigin);
+    void transferMatchedRules(DeclarationOrigin, Optional<Style::ScopeOrdinal> forScope = { });
+
+    void addMatchedRule(const RuleData&, unsigned specificity, Style::ScopeOrdinal);
 
     const Element& element() const { return m_element.get(); }
 
@@ -104,6 +108,7 @@
     const RuleSet* m_userAgentMediaQueryStyle { nullptr };
     const SelectorFilter* m_selectorFilter { nullptr };
 
+    bool m_shouldIncludeEmptyRules { false };
     bool m_isPrintStyle { false };
     PseudoStyleRequest m_pseudoStyleRequest { PseudoId::None };
     SelectorChecker::Mode m_mode { SelectorChecker::Mode::ResolvingStyle };
diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp
index 0c13c99..e4f14db 100644
--- a/Source/WebCore/css/StyleResolver.cpp
+++ b/Source/WebCore/css/StyleResolver.cpp
@@ -584,8 +584,8 @@
     collector.matchUARules();
 
     if (m_matchAuthorAndUserStyles) {
-        collector.matchUserRules(false);
-        collector.matchAuthorRules(false);
+        collector.matchUserRules();
+        collector.matchAuthorRules();
     }
 
     ASSERT(!collector.matchedPseudoElementIds());
@@ -1257,6 +1257,7 @@
     collector.setMode(SelectorChecker::Mode::CollectingRules);
     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
     collector.setMedium(&m_mediaQueryEvaluator);
+    collector.setIncludeEmptyRules(rulesToInclude & EmptyCSSRules);
 
     if (rulesToInclude & UAAndUserCSSRules) {
         // First we match rules from the user agent sheet.
@@ -1264,11 +1265,11 @@
 
         // Now we check user sheet rules.
         if (m_matchAuthorAndUserStyles)
-            collector.matchUserRules(rulesToInclude & EmptyCSSRules);
+            collector.matchUserRules();
     }
 
     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules))
-        collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
+        collector.matchAuthorRules();
 
     return collector.matchedRuleList();
 }