Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / ElementRuleCollector.cpp
index d59f50d..d7c7a0e 100644 (file)
 #include "config.h"
 #include "core/css/ElementRuleCollector.h"
 
+#include "core/css/CSSImportRule.h"
+#include "core/css/CSSKeyframesRule.h"
+#include "core/css/CSSMediaRule.h"
 #include "core/css/CSSRuleList.h"
 #include "core/css/CSSSelector.h"
 #include "core/css/CSSStyleRule.h"
-#include "core/css/SelectorCheckerFastPath.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/CSSSupportsRule.h"
 #include "core/css/SiblingTraversalStrategies.h"
 #include "core/css/StylePropertySet.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/shadow/ShadowRoot.h"
-#include "core/rendering/RenderRegion.h"
+#include "core/rendering/style/StyleInheritedData.h"
 
-namespace WebCore {
+namespace blink {
 
 ElementRuleCollector::ElementRuleCollector(const ElementResolveContext& context,
-    const SelectorFilter& filter, RenderStyle* style, ShouldIncludeStyleSheetInCSSOMWrapper includeStyleSheet)
+    const SelectorFilter& filter, RenderStyle* style)
     : m_context(context)
     , m_selectorFilter(filter)
     , m_style(style)
-    , m_regionForStyling(0)
     , m_pseudoStyleRequest(NOPSEUDO)
     , m_mode(SelectorChecker::ResolvingStyle)
     , m_canUseFastReject(m_selectorFilter.parentStackIsConsistent(context.parentNode()))
     , m_sameOriginOnly(false)
     , m_matchingUARules(false)
-    , m_includeStyleSheet(includeStyleSheet)
+    , m_scopeContainsLastMatchedElement(false)
 { }
 
 ElementRuleCollector::~ElementRuleCollector()
@@ -64,23 +67,23 @@ MatchResult& ElementRuleCollector::matchedResult()
     return m_result;
 }
 
-PassRefPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList()
+PassRefPtrWillBeRawPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList()
 {
     ASSERT(m_mode == SelectorChecker::CollectingStyleRules);
     return m_styleRuleList.release();
 }
 
-PassRefPtr<CSSRuleList> ElementRuleCollector::matchedCSSRuleList()
+PassRefPtrWillBeRawPtr<CSSRuleList> ElementRuleCollector::matchedCSSRuleList()
 {
     ASSERT(m_mode == SelectorChecker::CollectingCSSRules);
     return m_cssRuleList.release();
 }
 
-inline void ElementRuleCollector::addMatchedRule(const RuleData* rule, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
+inline void ElementRuleCollector::addMatchedRule(const RuleData* rule, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet)
 {
     if (!m_matchedRules)
-        m_matchedRules = adoptPtr(new Vector<MatchedRule, 32>);
-    m_matchedRules->append(MatchedRule(rule, cascadeScope, cascadeOrder));
+        m_matchedRules = adoptPtrWillBeNoop(new WillBeHeapVector<MatchedRule, 32>);
+    m_matchedRules->append(MatchedRule(rule, specificity, cascadeScope, cascadeOrder, styleSheetIndex, parentStyleSheet));
 }
 
 void ElementRuleCollector::clearMatchedRules()
@@ -116,27 +119,22 @@ void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* pro
         m_result.isCacheable = false;
 }
 
-static bool rulesApplicableInCurrentTreeScope(const Element* element, const ContainerNode* scopingNode, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, bool elementApplyAuthorStyles)
+static bool rulesApplicableInCurrentTreeScope(const Element* element, const ContainerNode* scopingNode, bool matchingTreeBoundaryRules)
 {
-    TreeScope& treeScope = element->treeScope();
-
     // [skipped, because already checked] a) it's a UA rule
-    // b) element is allowed to apply author rules
-    if (elementApplyAuthorStyles)
+    // b) We're mathcing tree boundary rules.
+    if (matchingTreeBoundaryRules)
         return true;
     // c) the rules comes from a scoped style sheet within the same tree scope
-    if (!scopingNode || treeScope == scopingNode->treeScope())
+    if (!scopingNode || element->treeScope() == scopingNode->treeScope())
         return true;
     // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element
-    if (element->isInShadowTree() && (behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost) && scopingNode == element->containingShadowRoot()->host())
-        return true;
-    // e) the rules can cross boundaries
-    if ((behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) == SelectorChecker::CrossesBoundary)
+    if (SelectorChecker::isHostInItsShadowTree(*element, scopingNode))
         return true;
     return false;
 }
 
-void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, RuleRange& ruleRange, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
+void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, RuleRange& ruleRange, CascadeScope cascadeScope, CascadeOrder cascadeOrder, bool matchingTreeBoundaryRules)
 {
     ASSERT(matchRequest.ruleSet);
     ASSERT(m_context.element());
@@ -145,83 +143,85 @@ void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest
     const AtomicString& pseudoId = element.shadowPseudoId();
     if (!pseudoId.isEmpty()) {
         ASSERT(element.isStyledElement());
-        collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), behaviorAtBoundary, ignoreCascadeScope, cascadeOrder, matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId), ignoreCascadeScope, cascadeOrder, matchRequest, ruleRange);
     }
 
-    if (element.isWebVTTElement())
-        collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
+    if (element.isVTTElement())
+        collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), cascadeScope, cascadeOrder, matchRequest, ruleRange);
     // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
     // a) it's a UA rule
-    // b) the tree scope allows author rules
-    // c) the rules comes from a scoped style sheet within the same tree scope
-    // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element
-    // e) the rules can cross boundaries
+    // b) the rules comes from a scoped style sheet within the same tree scope
+    // c) the rules comes from a scoped style sheet within an active shadow root whose host is the given element
+    // d) the rules can cross boundaries
     // b)-e) is checked in rulesApplicableInCurrentTreeScope.
-    if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, matchRequest.scope, behaviorAtBoundary, matchRequest.elementApplyAuthorStyles))
+    if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, matchRequest.scope, matchingTreeBoundaryRules))
         return;
 
     // We need to collect the rules for id, class, tag, and everything else into a buffer and
     // then sort the buffer.
     if (element.hasID())
-        collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForStyleResolution().impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForStyleResolution()), cascadeScope, cascadeOrder, matchRequest, ruleRange);
     if (element.isStyledElement() && element.hasClass()) {
         for (size_t i = 0; i < element.classNames().size(); ++i)
-            collectMatchingRulesForList(matchRequest.ruleSet->classRules(element.classNames()[i].impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
+            collectMatchingRulesForList(matchRequest.ruleSet->classRules(element.classNames()[i]), cascadeScope, cascadeOrder, matchRequest, ruleRange);
     }
 
     if (element.isLink())
-        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), cascadeScope, cascadeOrder, matchRequest, ruleRange);
     if (SelectorChecker::matchesFocusPseudoClass(element))
-        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName().impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
+        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), cascadeScope, cascadeOrder, matchRequest, ruleRange);
+    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName()), cascadeScope, cascadeOrder, matchRequest, ruleRange);
+    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), cascadeScope, cascadeOrder, matchRequest, ruleRange);
 }
 
-void ElementRuleCollector::collectMatchingRulesForRegion(const MatchRequest& matchRequest, RuleRange& ruleRange, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
+CSSRuleList* ElementRuleCollector::nestedRuleList(CSSRule* rule)
 {
-    if (!m_regionForStyling)
-        return;
-
-    unsigned size = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.size();
-    for (unsigned i = 0; i < size; ++i) {
-        const CSSSelector* regionSelector = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).selector;
-        if (checkRegionSelector(regionSelector, toElement(m_regionForStyling->node()))) {
-            RuleSet* regionRules = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
-            ASSERT(regionRules);
-            collectMatchingRules(MatchRequest(regionRules, matchRequest.includeEmptyRules, matchRequest.scope), ruleRange, behaviorAtBoundary, cascadeScope, cascadeOrder);
-        }
+    switch (rule->type()) {
+    case CSSRule::MEDIA_RULE:
+        return toCSSMediaRule(rule)->cssRules();
+    case CSSRule::KEYFRAMES_RULE:
+        return toCSSKeyframesRule(rule)->cssRules();
+    case CSSRule::SUPPORTS_RULE:
+        return toCSSSupportsRule(rule)->cssRules();
+    default:
+        return 0;
     }
 }
 
-
-static CSSStyleSheet* findStyleSheet(StyleEngine* styleEngine, StyleRule* rule)
+template<class CSSRuleCollection>
+CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleRule* styleRule)
 {
-    // FIXME: StyleEngine has a bunch of different accessors for StyleSheet lists, is this the only one we need to care about?
-    const Vector<RefPtr<CSSStyleSheet> >& stylesheets = styleEngine->activeAuthorStyleSheets();
-    for (size_t i = 0; i < stylesheets.size(); ++i) {
-        CSSStyleSheet* sheet = stylesheets[i].get();
-        for (unsigned j = 0; j < sheet->length(); ++j) {
-            CSSRule* cssRule = sheet->item(j);
-            if (cssRule->type() != CSSRule::STYLE_RULE)
-                continue;
+    if (!cssRules)
+        return 0;
+    CSSRule* result = 0;
+    for (unsigned i = 0; i < cssRules->length() && !result; ++i) {
+        CSSRule* cssRule = cssRules->item(i);
+        CSSRule::Type cssRuleType = cssRule->type();
+        if (cssRuleType == CSSRule::STYLE_RULE) {
             CSSStyleRule* cssStyleRule = toCSSStyleRule(cssRule);
-            if (cssStyleRule->styleRule() == rule)
-                return sheet;
+            if (cssStyleRule->styleRule() == styleRule)
+                result = cssRule;
+        } else if (cssRuleType == CSSRule::IMPORT_RULE) {
+            CSSImportRule* cssImportRule = toCSSImportRule(cssRule);
+            result = findStyleRule(cssImportRule->styleSheet(), styleRule);
+        } else {
+            result = findStyleRule(nestedRuleList(cssRule), styleRule);
         }
     }
-    return 0;
+    return result;
 }
 
-void ElementRuleCollector::appendCSSOMWrapperForRule(StyleRule* rule)
+void ElementRuleCollector::appendCSSOMWrapperForRule(CSSStyleSheet* parentStyleSheet, StyleRule* rule)
 {
-    // FIXME: There should be no codepath that creates a CSSOMWrapper without a parent stylesheet or rule because
-    // then that codepath can lead to the CSSStyleSheet contents not getting correctly copied when the rule is modified
-    // through the wrapper (e.g. rule.selectorText="div"). Right now, the inspector uses the pointers for identity though,
-    // so calling CSSStyleSheet->willMutateRules breaks the inspector.
-    CSSStyleSheet* sheet = m_includeStyleSheet == IncludeStyleSheetInCSSOMWrapper ? findStyleSheet(m_context.element()->document().styleEngine(), rule) : 0;
-    RefPtr<CSSRule> cssRule = rule->createCSSOMWrapper(sheet);
-    if (sheet)
-        sheet->registerExtraChildRuleCSSOMWrapper(cssRule);
+    // |parentStyleSheet| is 0 if and only if the |rule| is coming from User Agent. In this case,
+    // it is safe to create CSSOM wrappers without parentStyleSheets as they will be used only
+    // by inspector which will not try to edit them.
+    RefPtrWillBeRawPtr<CSSRule> cssRule = nullptr;
+    if (parentStyleSheet)
+        cssRule = findStyleRule(parentStyleSheet, rule);
+    else
+        cssRule = rule->createCSSOMWrapper();
+    ASSERT(!parentStyleSheet || cssRule);
     ensureRuleList()->rules().append(cssRule);
 }
 
@@ -232,7 +232,7 @@ void ElementRuleCollector::sortAndTransferMatchedRules()
 
     sortMatchedRules();
 
-    Vector<MatchedRule, 32>& matchedRules = *m_matchedRules;
+    WillBeHeapVector<MatchedRule, 32>& matchedRules = *m_matchedRules;
     if (m_mode == SelectorChecker::CollectingStyleRules) {
         for (unsigned i = 0; i < matchedRules.size(); ++i)
             ensureStyleRuleList()->m_list.append(matchedRules[i].ruleData()->rule());
@@ -241,7 +241,7 @@ void ElementRuleCollector::sortAndTransferMatchedRules()
 
     if (m_mode == SelectorChecker::CollectingCSSRules) {
         for (unsigned i = 0; i < matchedRules.size(); ++i)
-            appendCSSOMWrapperForRule(matchedRules[i].ruleData()->rule());
+            appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(matchedRules[i].parentStyleSheet()), matchedRules[i].ruleData()->rule());
         return;
     }
 
@@ -251,36 +251,12 @@ void ElementRuleCollector::sortAndTransferMatchedRules()
         const RuleData* ruleData = matchedRules[i].ruleData();
         if (m_style && ruleData->containsUncommonAttributeSelector())
             m_style->setUnique();
-        m_result.addMatchedProperties(ruleData->rule()->properties(), ruleData->rule(), ruleData->linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules));
+        m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData->linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules));
     }
 }
 
-inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, PseudoId& dynamicPseudo, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary)
+inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, SelectorChecker::MatchResult* result)
 {
-    // They can't match because the fast path uses a pool of tag/class/ids, collected from
-    // elements in that tree and those will never match the host, since it's in a different pool.
-    // So when adding scoped rules to RuleSet, RuleCanUseFastCheckSelector is not used.
-    if (ruleData.hasFastCheckableSelector()) {
-        // We know this selector does not include any pseudo elements.
-        if (m_pseudoStyleRequest.pseudoId != NOPSEUDO)
-            return false;
-        // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
-        // This is limited to HTML only so we don't need to check the namespace.
-        ASSERT(m_context.element());
-        if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_context.element()->isHTMLElement()) {
-            if (!ruleData.hasMultipartSelector())
-                return true;
-        }
-        if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(*m_context.element(), ruleData.selector()->tagQName()))
-            return false;
-        SelectorCheckerFastPath selectorCheckerFastPath(ruleData.selector(), *m_context.element());
-        if (!selectorCheckerFastPath.matchesRightmostAttributeSelector())
-            return false;
-
-        return selectorCheckerFastPath.matches();
-    }
-
-    // Slow path.
     SelectorChecker selectorChecker(m_context.element()->document(), m_mode);
     SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_context.element(), SelectorChecker::VisitedMatchEnabled);
     context.elementStyle = m_style.get();
@@ -288,38 +264,44 @@ inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, const Co
     context.pseudoId = m_pseudoStyleRequest.pseudoId;
     context.scrollbar = m_pseudoStyleRequest.scrollbar;
     context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
-    context.behaviorAtBoundary = behaviorAtBoundary;
-    SelectorChecker::Match match = selectorChecker.match(context, dynamicPseudo, DOMSiblingTraversalStrategy());
+    context.isUARule = m_matchingUARules;
+    context.scopeContainsLastMatchedElement = m_scopeContainsLastMatchedElement;
+    SelectorChecker::Match match = selectorChecker.match(context, DOMSiblingTraversalStrategy(), result);
     if (match != SelectorChecker::SelectorMatches)
         return false;
-    if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.pseudoId != dynamicPseudo)
+    if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.pseudoId != result->dynamicPseudo)
         return false;
     return true;
 }
 
-void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange)
+void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange)
 {
     if (m_canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
         return;
 
     StyleRule* rule = ruleData.rule();
-    PseudoId dynamicPseudo = NOPSEUDO;
-    if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo, behaviorAtBoundary)) {
+    SelectorChecker::MatchResult result;
+    if (ruleMatches(ruleData, matchRequest.scope, &result)) {
         // If the rule has no properties to apply, then ignore it in the non-debug mode.
-        const StylePropertySet* properties = rule->properties();
-        if (!properties || (properties->isEmpty() && !matchRequest.includeEmptyRules))
+        const StylePropertySet& properties = rule->properties();
+        if (properties.isEmpty() && !matchRequest.includeEmptyRules)
             return;
         // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
         if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin())
             return;
+
+        PseudoId dynamicPseudo = result.dynamicPseudo;
         // If we're matching normal rules, set a pseudo bit if
         // we really just matched a pseudo-element.
         if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO) {
             if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorChecker::CollectingStyleRules)
                 return;
             // FIXME: Matching should not modify the style directly.
-            if (m_style && dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
-                m_style->setHasPseudoStyle(dynamicPseudo);
+            if (!m_style || dynamicPseudo >= FIRST_INTERNAL_PSEUDOID)
+                return;
+            if ((dynamicPseudo == BEFORE || dynamicPseudo == AFTER) && !ruleData.rule()->properties().hasProperty(CSSPropertyContent))
+                return;
+            m_style->setHasPseudoStyle(dynamicPseudo);
         } else {
             // Update our first/last rule indices in the matched rules array.
             ++ruleRange.lastRuleIndex;
@@ -327,37 +309,23 @@ void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, Select
                 ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
 
             // Add this rule to our list of matched rules.
-            addMatchedRule(&ruleData, cascadeScope, cascadeOrder);
+            addMatchedRule(&ruleData, result.specificity, cascadeScope, cascadeOrder, matchRequest.styleSheetIndex, matchRequest.styleSheet);
             return;
         }
     }
 }
 
-void ElementRuleCollector::collectMatchingRulesForList(const RuleData* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange)
+static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRule& matchedRule2)
 {
-    if (!rules)
-        return;
-    while (!rules->isLastInArray())
-        collectRuleIfMatches(*rules++, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
-    collectRuleIfMatches(*rules, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
-}
+    if (matchedRule1.cascadeScope() != matchedRule2.cascadeScope())
+        return matchedRule1.cascadeScope() > matchedRule2.cascadeScope();
 
-void ElementRuleCollector::collectMatchingRulesForList(const Vector<RuleData>* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange)
-{
-    if (!rules)
-        return;
-    unsigned size = rules->size();
-    for (unsigned i = 0; i < size; ++i)
-        collectRuleIfMatches(rules->at(i), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange);
-}
+    unsigned specificity1 = matchedRule1.specificity();
+    unsigned specificity2 = matchedRule2.specificity();
+    if (specificity1 != specificity2)
+        return specificity1 < specificity2;
 
-static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRule& matchedRule2)
-{
-    unsigned specificity1 = matchedRule1.ruleData()->specificity();
-    unsigned specificity2 = matchedRule2.ruleData()->specificity();
-    return matchedRule1.cascadeScope() == matchedRule2.cascadeScope() ?
-        ((specificity1 == specificity2) ? matchedRule1.position() < matchedRule2.position() : specificity1 < specificity2) :
-        matchedRule1.cascadeScope() > matchedRule2.cascadeScope();
+    return matchedRule1.position() < matchedRule2.position();
 }
 
 void ElementRuleCollector::sortMatchedRules()
@@ -377,9 +345,9 @@ bool ElementRuleCollector::hasAnyMatchingRules(RuleSet* ruleSet)
     int firstRuleIndex = -1, lastRuleIndex = -1;
     RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
     // FIXME: Verify whether it's ok to ignore CascadeScope here.
-    collectMatchingRules(MatchRequest(ruleSet), ruleRange, SelectorChecker::StaysWithinTreeScope);
+    collectMatchingRules(MatchRequest(ruleSet), ruleRange);
 
     return m_matchedRules && !m_matchedRules->isEmpty();
 }
 
-} // namespace WebCore
+} // namespace blink