[Refactoring] Implement RuleCollector
authortasak@google.com <tasak@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Mar 2013 11:19:30 +0000 (11:19 +0000)
committertasak@google.com <tasak@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Mar 2013 11:19:30 +0000 (11:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=109916

Reviewed by Antti Koivisto.

Implemented rule collector for an element and collector for a page.
Not all members in class State are required entire while resolving
a style.

No new tests, because just refactoring.

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSAllInOne.cpp:
Added ElementRuleCollector and PageRuleCollector.
* css/DocumentRuleSets.cpp:
(WebCore::ShadowDistributedRules::collectMatchRequests):
Since behaviorAtBoundary is a state owned by ElementRuleCollector,
removed from here.
* css/DocumentRuleSets.h:
(WebCore::ShadowDistributedRules::isEmpty):
Added to quickly check whether there exist any ShadowDistributedRules
or not.
* css/ElementRuleCollector.cpp: Copied from Source/WebCore/css/StyleResolver.cpp.
(WebCore):
(WebCore::ElementRuleCollector::matchedResult):
(WebCore::ElementRuleCollector::matchedRuleList):
(WebCore::ElementRuleCollector::addMatchedRule):
(WebCore::ElementRuleCollector::clearMatchedRules):
(WebCore::ElementRuleCollector::ensureRuleList):
(WebCore::ElementRuleCollector::addElementStyleProperties):
(WebCore::ElementRuleCollector::collectMatchingRules):
(WebCore::ElementRuleCollector::collectMatchingRulesForRegion):
(WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
(WebCore::ElementRuleCollector::matchScopedAuthorRules):
(WebCore::ElementRuleCollector::matchHostRules):
(WebCore::ElementRuleCollector::matchShadowDistributedRules):
(WebCore::ElementRuleCollector::matchAuthorRules):
(WebCore::ElementRuleCollector::matchUserRules):
(WebCore::ElementRuleCollector::matchUARules):
(WebCore::ElementRuleCollector::ruleMatches):
(WebCore::ElementRuleCollector::collectMatchingRulesForList):
(WebCore::ElementRuleCollector::sortMatchedRules):
(WebCore::ElementRuleCollector::matchAllRules):
Moved these methods from StyleResolver to this class.
(WebCore::ElementRuleCollector::hasAnyMatchingRules):
This method is used for checking whether a given element can share
a cache.
* css/ElementRuleCollector.h: Copied from Source/WebCore/css/StyleResolver.h.
(WebCore):
(WebCore::ElementRuleCollector::ElementRuleCollector):
Use styleResolver instance to initialize its member variables, i.e.
SelectorFilter, RuleSets, InspectorCSSOMWrappers, and
StyleScopedResolver.
(ElementRuleCollector):
(WebCore::ElementRuleCollector::setMode):
(WebCore::ElementRuleCollector::setPseudoStyleRequest):
(WebCore::ElementRuleCollector::setSameOriginOnly):
(WebCore::ElementRuleCollector::setRegionForStyling):
Mode, SameOriginOnly, RegionForStyling are only used while collecting
matched rules.
(WebCore::ElementRuleCollector::setMedium):
Need to know which default stylesheet should be looked up.
(WebCore::ElementRuleCollector::document):
* css/PageRuleCollector.cpp: Copied from Source/WebCore/css/StyleResolver.cpp.
(WebCore::comparePageRules):
(WebCore::PageRuleCollector::isLeftPage):
(WebCore::PageRuleCollector::isFirstPage):
(WebCore::PageRuleCollector::pageName):
(WebCore::PageRuleCollector::matchAllPageRules):
(WebCore::PageRuleCollector::matchPageRules):
(WebCore::checkPageSelectorComponents):
(WebCore::PageRuleCollector::matchPageRulesForList):
Moved from StyleResolver.
* css/PageRuleCollector.h: Copied from Source/WebCore/css/StyleResolver.h.
(WebCore):
(WebCore::PageRuleCollector::PageRuleCollector):
(PageRuleCollector):
(WebCore::PageRuleCollector::matchedResult):
* css/StyleResolver.cpp:
(WebCore):
(WebCore::StyleResolver::State::clear):
(WebCore::StyleResolver::MatchResult::addMatchedProperties):
(WebCore::StyleResolver::State::initForStyleResolve):
(WebCore::StyleResolver::styleSharingCandidateMatchesRuleSet):
(WebCore::StyleResolver::styleForElement):
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::pseudoStyleForElement):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::pseudoStyleRulesForElement):
(WebCore::StyleResolver::applyMatchedProperties):
* css/StyleResolver.h:
(WebCore::MatchRequest::MatchRequest):
Removed behaviorAtBoundary. Instead, ElementRuleCollector have the
state.
(MatchRequest):
(WebCore::StyleResolver::selectorFilter):
Added to obtain SelectorFilter in ElementRuleCollector's constructor.
(StyleResolver):
(MatchResult):
(WebCore::StyleResolver::State::State):
To pass ASSERT in StyleResolver::applyProperties, need to keep
m_regionForStyling.
(State):
(WebCore::StyleResolver::State::regionForStyling):
(WebCore::StyleResolver::State::useSVGZoomRules):
(WebCore::StyleResolver::hasSelectorForId):
(WebCore):
(WebCore::checkRegionSelector):
* inspector/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::willMatchRule):
Removed StyleResolver from its parameter list. Instead, added
InspectorCSSOMWrappers and DocumentStyleSheetCollection.
* inspector/InspectorCSSAgent.h:
(WebCore):
(InspectorCSSAgent):
* inspector/InspectorInstrumentation.cpp:
(WebCore):
(WebCore::InspectorInstrumentation::willMatchRuleImpl):
* inspector/InspectorInstrumentation.h:
(WebCore):
(InspectorInstrumentation):
(WebCore::InspectorInstrumentation::willMatchRule):

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

19 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSAllInOne.cpp
Source/WebCore/css/DocumentRuleSets.cpp
Source/WebCore/css/DocumentRuleSets.h
Source/WebCore/css/ElementRuleCollector.cpp [new file with mode: 0644]
Source/WebCore/css/ElementRuleCollector.h [new file with mode: 0644]
Source/WebCore/css/PageRuleCollector.cpp [new file with mode: 0644]
Source/WebCore/css/PageRuleCollector.h [new file with mode: 0644]
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/inspector/InspectorCSSAgent.cpp
Source/WebCore/inspector/InspectorCSSAgent.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h

index de58a2a..0f2fdca 100644 (file)
@@ -1070,6 +1070,7 @@ set(WebCore_SOURCES
     css/CSSValuePool.cpp
     css/DOMWindowCSS.cpp
     css/DocumentRuleSets.cpp
+    css/ElementRuleCollector.cpp
     css/FontFeatureValue.cpp
     css/FontValue.cpp
     css/InspectorCSSOMWrappers.cpp
@@ -1082,6 +1083,7 @@ set(WebCore_SOURCES
     css/MediaQueryList.cpp
     css/MediaQueryListListener.cpp
     css/MediaQueryMatcher.cpp
+    css/PageRuleCollector.cpp
     css/PropertySetCSSStyleDeclaration.cpp
     css/RGBColor.cpp
     css/RuleFeature.h
index bbebb17..3d9b43b 100644 (file)
@@ -1,3 +1,132 @@
+2013-03-07  Takashi Sakamoto  <tasak@google.com>
+
+        [Refactoring] Implement RuleCollector
+        https://bugs.webkit.org/show_bug.cgi?id=109916
+
+        Reviewed by Antti Koivisto.
+
+        Implemented rule collector for an element and collector for a page.
+        Not all members in class State are required entire while resolving
+        a style.
+
+        No new tests, because just refactoring.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSAllInOne.cpp:
+        Added ElementRuleCollector and PageRuleCollector.
+        * css/DocumentRuleSets.cpp:
+        (WebCore::ShadowDistributedRules::collectMatchRequests):
+        Since behaviorAtBoundary is a state owned by ElementRuleCollector,
+        removed from here.
+        * css/DocumentRuleSets.h:
+        (WebCore::ShadowDistributedRules::isEmpty):
+        Added to quickly check whether there exist any ShadowDistributedRules
+        or not.
+        * css/ElementRuleCollector.cpp: Copied from Source/WebCore/css/StyleResolver.cpp.
+        (WebCore):
+        (WebCore::ElementRuleCollector::matchedResult):
+        (WebCore::ElementRuleCollector::matchedRuleList):
+        (WebCore::ElementRuleCollector::addMatchedRule):
+        (WebCore::ElementRuleCollector::clearMatchedRules):
+        (WebCore::ElementRuleCollector::ensureRuleList):
+        (WebCore::ElementRuleCollector::addElementStyleProperties):
+        (WebCore::ElementRuleCollector::collectMatchingRules):
+        (WebCore::ElementRuleCollector::collectMatchingRulesForRegion):
+        (WebCore::ElementRuleCollector::sortAndTransferMatchedRules):
+        (WebCore::ElementRuleCollector::matchScopedAuthorRules):
+        (WebCore::ElementRuleCollector::matchHostRules):
+        (WebCore::ElementRuleCollector::matchShadowDistributedRules):
+        (WebCore::ElementRuleCollector::matchAuthorRules):
+        (WebCore::ElementRuleCollector::matchUserRules):
+        (WebCore::ElementRuleCollector::matchUARules):
+        (WebCore::ElementRuleCollector::ruleMatches):
+        (WebCore::ElementRuleCollector::collectMatchingRulesForList):
+        (WebCore::ElementRuleCollector::sortMatchedRules):
+        (WebCore::ElementRuleCollector::matchAllRules):
+        Moved these methods from StyleResolver to this class.
+        (WebCore::ElementRuleCollector::hasAnyMatchingRules):
+        This method is used for checking whether a given element can share
+        a cache.
+        * css/ElementRuleCollector.h: Copied from Source/WebCore/css/StyleResolver.h.
+        (WebCore):
+        (WebCore::ElementRuleCollector::ElementRuleCollector):
+        Use styleResolver instance to initialize its member variables, i.e.
+        SelectorFilter, RuleSets, InspectorCSSOMWrappers, and
+        StyleScopedResolver.
+        (ElementRuleCollector):
+        (WebCore::ElementRuleCollector::setMode):
+        (WebCore::ElementRuleCollector::setPseudoStyleRequest):
+        (WebCore::ElementRuleCollector::setSameOriginOnly):
+        (WebCore::ElementRuleCollector::setRegionForStyling):
+        Mode, SameOriginOnly, RegionForStyling are only used while collecting
+        matched rules.
+        (WebCore::ElementRuleCollector::setMedium):
+        Need to know which default stylesheet should be looked up.
+        (WebCore::ElementRuleCollector::document):
+        * css/PageRuleCollector.cpp: Copied from Source/WebCore/css/StyleResolver.cpp.
+        (WebCore::comparePageRules):
+        (WebCore::PageRuleCollector::isLeftPage):
+        (WebCore::PageRuleCollector::isFirstPage):
+        (WebCore::PageRuleCollector::pageName):
+        (WebCore::PageRuleCollector::matchAllPageRules):
+        (WebCore::PageRuleCollector::matchPageRules):
+        (WebCore::checkPageSelectorComponents):
+        (WebCore::PageRuleCollector::matchPageRulesForList):
+        Moved from StyleResolver.
+        * css/PageRuleCollector.h: Copied from Source/WebCore/css/StyleResolver.h.
+        (WebCore):
+        (WebCore::PageRuleCollector::PageRuleCollector):
+        (PageRuleCollector):
+        (WebCore::PageRuleCollector::matchedResult):
+        * css/StyleResolver.cpp:
+        (WebCore):
+        (WebCore::StyleResolver::State::clear):
+        (WebCore::StyleResolver::MatchResult::addMatchedProperties):
+        (WebCore::StyleResolver::State::initForStyleResolve):
+        (WebCore::StyleResolver::styleSharingCandidateMatchesRuleSet):
+        (WebCore::StyleResolver::styleForElement):
+        (WebCore::StyleResolver::styleForKeyframe):
+        (WebCore::StyleResolver::pseudoStyleForElement):
+        (WebCore::StyleResolver::styleForPage):
+        (WebCore::StyleResolver::pseudoStyleRulesForElement):
+        (WebCore::StyleResolver::applyMatchedProperties):
+        * css/StyleResolver.h:
+        (WebCore::MatchRequest::MatchRequest):
+        Removed behaviorAtBoundary. Instead, ElementRuleCollector have the
+        state.
+        (MatchRequest):
+        (WebCore::StyleResolver::selectorFilter):
+        Added to obtain SelectorFilter in ElementRuleCollector's constructor.
+        (StyleResolver):
+        (MatchResult):
+        (WebCore::StyleResolver::State::State):
+        To pass ASSERT in StyleResolver::applyProperties, need to keep
+        m_regionForStyling.
+        (State):
+        (WebCore::StyleResolver::State::regionForStyling):
+        (WebCore::StyleResolver::State::useSVGZoomRules):
+        (WebCore::StyleResolver::hasSelectorForId):
+        (WebCore):
+        (WebCore::checkRegionSelector):
+        * inspector/InspectorCSSAgent.cpp:
+        (WebCore::InspectorCSSAgent::willMatchRule):
+        Removed StyleResolver from its parameter list. Instead, added
+        InspectorCSSOMWrappers and DocumentStyleSheetCollection.
+        * inspector/InspectorCSSAgent.h:
+        (WebCore):
+        (InspectorCSSAgent):
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore):
+        (WebCore::InspectorInstrumentation::willMatchRuleImpl):
+        * inspector/InspectorInstrumentation.h:
+        (WebCore):
+        (InspectorInstrumentation):
+        (WebCore::InspectorInstrumentation::willMatchRule):
+
 2013-03-07  Andrey Lushnikov  <lushnikov@chromium.org>
 
         Web Inspector: [ACE] add experimental breakpoint support
index 9f456fd..572e8c5 100644 (file)
@@ -2660,6 +2660,8 @@ webcore_sources += \
        Source/WebCore/css/DashboardRegion.h \
        Source/WebCore/css/DocumentRuleSets.cpp \
        Source/WebCore/css/DocumentRuleSets.h \
+       Source/WebCore/css/ElementRuleCollector.cpp \
+       Source/WebCore/css/ElementRuleCollector.h \
        Source/WebCore/css/FontFeatureValue.cpp \
        Source/WebCore/css/FontFeatureValue.h \
        Source/WebCore/css/FontValue.cpp \
@@ -2684,6 +2686,8 @@ webcore_sources += \
        Source/WebCore/css/MediaQueryListListener.h \
        Source/WebCore/css/MediaQueryMatcher.cpp \
        Source/WebCore/css/MediaQueryMatcher.h \
+       Source/WebCore/css/PageRuleCollector.cpp \
+       Source/WebCore/css/PageRuleCollector.h \
        Source/WebCore/css/Pair.h \
        Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp \
        Source/WebCore/css/PropertySetCSSStyleDeclaration.h \
index 1b655fb..6312c0e 100644 (file)
@@ -305,6 +305,7 @@ SOURCES += \
     css/CSSValuePool.cpp \
     css/DOMWindowCSS.cpp \
     css/DocumentRuleSets.cpp \
+    css/ElementRuleCollector.cpp \
     css/FontFeatureValue.cpp \
     css/FontValue.cpp \
     css/InspectorCSSOMWrappers.cpp \
@@ -317,6 +318,7 @@ SOURCES += \
     css/MediaQueryList.cpp \
     css/MediaQueryListListener.cpp \
     css/MediaQueryMatcher.cpp \
+    css/PageRuleCollector.cpp \
     css/PropertySetCSSStyleDeclaration.cpp \
     css/RGBColor.cpp \
     css/RuleFeature.cpp \
index fcc1dbe..1efd49f 100644 (file)
             'css/DashboardRegion.h',
             'css/DocumentRuleSets.cpp',
             'css/DocumentRuleSets.h',
+            'css/ElementRuleCollector.cpp',
+            'css/ElementRuleCollector.h',
             'css/FontFeatureValue.cpp',
             'css/FontFeatureValue.h',
             'css/FontValue.cpp',
             'css/MediaQueryListListener.h',
             'css/MediaQueryMatcher.cpp',
             'css/MediaQueryMatcher.h',
+            'css/PageRuleCollector.cpp',
+            'css/PageRuleCollector.h',
             'css/PropertySetCSSStyleDeclaration.cpp',
             'css/PropertySetCSSStyleDeclaration.h',
             'css/RGBColor.cpp',
index 7c993c2..4b96ca7 100644 (file)
                FBD6AF8B15EF25E5008B7110 /* CSSBasicShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBD6AF8615EF21D4008B7110 /* CSSBasicShapes.cpp */; };
                FBD6AF8C15EF2604008B7110 /* BasicShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = FBD6AF8315EF21A3008B7110 /* BasicShapes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FBD6AF8D15EF260A008B7110 /* BasicShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBD6AF8215EF21A3008B7110 /* BasicShapes.cpp */; };
+               FBDB619B16D6032A00BB3394 /* ElementRuleCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */; };
+               FBDB619D16D6034600BB3394 /* PageRuleCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBDB619C16D6034600BB3394 /* PageRuleCollector.cpp */; };
+               FBDB619F16D6036500BB3394 /* ElementRuleCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */; };
+               FBDB61A116D6037E00BB3394 /* PageRuleCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = FBDB61A016D6037E00BB3394 /* PageRuleCollector.h */; };
                FBF89045169E9F1F0052D86E /* CSSGroupingRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FBF89044169E9F1F0052D86E /* CSSGroupingRule.cpp */; };
                FC54D05716A7673100575E4D /* CSSSupportsRule.h in Headers */ = {isa = PBXBuildFile; fileRef = FC63BDB1167AABAC00F9380F /* CSSSupportsRule.h */; };
                FC54D05816A7676E00575E4D /* JSCSSSupportsRule.h in Headers */ = {isa = PBXBuildFile; fileRef = FC84802E167AB444008CD100 /* JSCSSSupportsRule.h */; };
                FBD6AF8515EF21D4008B7110 /* BasicShapeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicShapeFunctions.h; sourceTree = "<group>"; };
                FBD6AF8615EF21D4008B7110 /* CSSBasicShapes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSBasicShapes.cpp; sourceTree = "<group>"; };
                FBD6AF8715EF21D4008B7110 /* CSSBasicShapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSBasicShapes.h; sourceTree = "<group>"; };
+               FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ElementRuleCollector.cpp; sourceTree = "<group>"; };
+               FBDB619C16D6034600BB3394 /* PageRuleCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageRuleCollector.cpp; sourceTree = "<group>"; };
+               FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementRuleCollector.h; sourceTree = "<group>"; };
+               FBDB61A016D6037E00BB3394 /* PageRuleCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageRuleCollector.h; sourceTree = "<group>"; };
                FBF89044169E9F1F0052D86E /* CSSGroupingRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSGroupingRule.cpp; sourceTree = "<group>"; };
                FC63BDB0167AABAC00F9380F /* CSSSupportsRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSSupportsRule.cpp; sourceTree = "<group>"; };
                FC63BDB1167AABAC00F9380F /* CSSSupportsRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSupportsRule.h; sourceTree = "<group>"; };
                                FC9A0F71164094CF003D6B8D /* DOMWindowCSS.cpp */,
                                FC9A0F72164094CF003D6B8D /* DOMWindowCSS.h */,
                                FC9A0F73164094CF003D6B8D /* DOMWindowCSS.idl */,
+                               FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */,
+                               FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */,
                                4A6E9FC213C17D1D0046A7F8 /* FontFeatureValue.h */,
                                A80E6CC70A1989CA007FB8C5 /* FontValue.cpp */,
                                A80E6CC30A1989CA007FB8C5 /* FontValue.h */,
                                D3A94A35122DABAC00A37BBC /* MediaQueryListListener.idl */,
                                D3AA10F1123A98AA0092152B /* MediaQueryMatcher.cpp */,
                                D3AA10F2123A98AA0092152B /* MediaQueryMatcher.h */,
+                               FBDB61A016D6037E00BB3394 /* PageRuleCollector.h */,
+                               FBDB619C16D6034600BB3394 /* PageRuleCollector.cpp */,
                                A80E6CD10A1989CA007FB8C5 /* Pair.h */,
                                3189E6DB16B2103500386EA3 /* plugIns.css */,
                                E4BBED0C14F4025D003F0B98 /* PropertySetCSSStyleDeclaration.cpp */,
                                7E66E23416D6EB6C00F7E7FF /* WebGLCompressedTextureATC.h in Headers */,
                                7EA30F6A16DFFE7500257D0B /* JSWebGLCompressedTextureATC.h in Headers */,
                                2D8287F716E4A0380086BD00 /* HitTestLocation.h in Headers */,
+                               FBDB619F16D6036500BB3394 /* ElementRuleCollector.h in Headers */,
+                               FBDB61A116D6037E00BB3394 /* PageRuleCollector.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                7E66E23316D6EB6C00F7E7FF /* WebGLCompressedTextureATC.cpp in Sources */,
                                7EA30F6916DFFE7500257D0B /* JSWebGLCompressedTextureATC.cpp in Sources */,
                                2D8287F616E4A0380086BD00 /* HitTestLocation.cpp in Sources */,
+                               FBDB619B16D6032A00BB3394 /* ElementRuleCollector.cpp in Sources */,
+                               FBDB619D16D6034600BB3394 /* PageRuleCollector.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 913efdc..78e7520 100644 (file)
@@ -71,7 +71,9 @@
 #include "CSSValuePool.cpp"
 #include "DOMWindowCSS.cpp"
 #include "DocumentRuleSets.cpp"
+#include "ElementRuleCollector.cpp"
 #include "InspectorCSSOMWrappers.cpp"
+#include "PageRuleCollector.cpp"
 #include "RuleFeature.cpp"
 #include "RuleSet.cpp"
 #include "SelectorCheckerFastPath.cpp"
index a85c1a7..0ff81b1 100644 (file)
@@ -53,7 +53,7 @@ void ShadowDistributedRules::addRule(StyleRule* rule, size_t selectorIndex, Cont
 void ShadowDistributedRules::collectMatchRequests(bool includeEmptyRules, Vector<MatchRequest>& matchRequests)
 {
     for (ShadowDistributedRuleSetMap::iterator it = m_shadowDistributedRuleSetMap.begin(); it != m_shadowDistributedRuleSetMap.end(); ++it)
-        matchRequests.append(MatchRequest(it->value.get(), includeEmptyRules, it->key, SelectorChecker::CrossesBoundary));
+        matchRequests.append(MatchRequest(it->value.get(), includeEmptyRules, it->key));
 }
 #endif
 
index 13c4ee5..8c4bdb8 100644 (file)
@@ -47,6 +47,7 @@ public:
     void addRule(StyleRule*, size_t selectorIndex, ContainerNode* scope, AddRuleFlags);
     void collectMatchRequests(bool includeEmptyRules, Vector<MatchRequest>&);
     void clear() { m_shadowDistributedRuleSetMap.clear(); }
+    bool isEmpty() const { return m_shadowDistributedRuleSetMap.isEmpty(); }
 private:
     typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ShadowDistributedRuleSetMap;
     ShadowDistributedRuleSetMap m_shadowDistributedRuleSetMap;
diff --git a/Source/WebCore/css/ElementRuleCollector.cpp b/Source/WebCore/css/ElementRuleCollector.cpp
new file mode 100644 (file)
index 0000000..977600f
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "ElementRuleCollector.h"
+
+#include "CSSDefaultStyleSheets.h"
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+#include "CSSValueKeywords.h"
+#include "HTMLElement.h"
+#include "RenderRegion.h"
+#include "SVGElement.h"
+#include "SelectorCheckerFastPath.h"
+#include "SiblingTraversalStrategies.h"
+#include "StylePropertySet.h"
+#include "StyledElement.h"
+
+#include <wtf/TemporaryChange.h>
+
+namespace WebCore {
+
+static StylePropertySet* leftToRightDeclaration()
+{
+    DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
+    if (leftToRightDecl->isEmpty())
+        leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
+    return leftToRightDecl.get();
+}
+
+static StylePropertySet* rightToLeftDeclaration()
+{
+    DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
+    if (rightToLeftDecl->isEmpty())
+        rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
+    return rightToLeftDecl.get();
+}
+
+StyleResolver::MatchResult& ElementRuleCollector::matchedResult()
+{
+    ASSERT(m_mode == SelectorChecker::ResolvingStyle);
+    return m_result;
+}
+
+PassRefPtr<CSSRuleList> ElementRuleCollector::matchedRuleList()
+{
+    ASSERT(m_mode == SelectorChecker::CollectingRules);
+    return m_ruleList.release();
+}
+
+inline void ElementRuleCollector::addMatchedRule(const RuleData* rule)
+{
+    if (!m_matchedRules)
+        m_matchedRules = adoptPtr(new Vector<const RuleData*, 32>);
+    m_matchedRules->append(rule);
+}
+
+inline void ElementRuleCollector::clearMatchedRules()
+{
+    if (!m_matchedRules)
+        return;
+    m_matchedRules->clear();
+}
+
+inline StaticCSSRuleList* ElementRuleCollector::ensureRuleList()
+{
+    if (!m_ruleList)
+        m_ruleList = StaticCSSRuleList::create();
+    return m_ruleList.get();
+}
+
+inline void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* propertySet, bool isCacheable)
+{
+    if (!propertySet)
+        return;
+    m_result.ranges.lastAuthorRule = m_result.matchedProperties.size();
+    if (m_result.ranges.firstAuthorRule == -1)
+        m_result.ranges.firstAuthorRule = m_result.ranges.lastAuthorRule;
+    m_result.addMatchedProperties(propertySet);
+    if (!isCacheable)
+        m_result.isCacheable = false;
+}
+
+void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+{
+    ASSERT(matchRequest.ruleSet);
+    ASSERT(m_state.element());
+
+    const StyleResolver::State& state = m_state;
+    Element* element = state.element();
+    const StyledElement* styledElement = state.styledElement();
+    const AtomicString& pseudoId = element->shadowPseudoId();
+    if (!pseudoId.isEmpty()) {
+        ASSERT(styledElement);
+        collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), matchRequest, ruleRange);
+    }
+
+#if ENABLE(VIDEO_TRACK)
+    if (element->isWebVTTElement())
+        collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange);
+#endif
+    // 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
+    TreeScope* treeScope = element->treeScope();
+    if (!m_matchingUARules
+        && !treeScope->applyAuthorStyles()
+        && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope)
+        && m_behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary)
+        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()), matchRequest, ruleRange);
+    if (styledElement && styledElement->hasClass()) {
+        for (size_t i = 0; i < styledElement->classNames().size(); ++i)
+            collectMatchingRulesForList(matchRequest.ruleSet->classRules(styledElement->classNames()[i].impl()), matchRequest, ruleRange);
+    }
+
+    if (element->isLink())
+        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest, ruleRange);
+    if (SelectorChecker::matchesFocusPseudoClass(element))
+        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest, ruleRange);
+    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element->localName().impl()), matchRequest, ruleRange);
+    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest, ruleRange);
+}
+
+void ElementRuleCollector::collectMatchingRulesForRegion(const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+{
+    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, static_cast<Element*>(m_regionForStyling->node()))) {
+            RuleSet* regionRules = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
+            ASSERT(regionRules);
+            collectMatchingRules(MatchRequest(regionRules, matchRequest.includeEmptyRules, matchRequest.scope), ruleRange);
+        }
+    }
+}
+
+void ElementRuleCollector::sortAndTransferMatchedRules()
+{
+    const StyleResolver::State& state = m_state;
+
+    if (!m_matchedRules || m_matchedRules->isEmpty())
+        return;
+
+    sortMatchedRules();
+
+    Vector<const RuleData*, 32>& matchedRules = *m_matchedRules;
+    if (m_mode == SelectorChecker::CollectingRules) {
+        for (unsigned i = 0; i < matchedRules.size(); ++i)
+            ensureRuleList()->rules().append(matchedRules[i]->rule()->createCSSOMWrapper());
+        return;
+    }
+
+    // Now transfer the set of matched rules over to our list of declarations.
+    for (unsigned i = 0; i < matchedRules.size(); i++) {
+        if (state.style() && matchedRules[i]->containsUncommonAttributeSelector())
+            state.style()->setUnique();
+        m_result.addMatchedProperties(matchedRules[i]->rule()->properties(), matchedRules[i]->rule(), matchedRules[i]->linkMatchType(), matchedRules[i]->propertyWhitelistType());
+    }
+}
+
+void ElementRuleCollector::matchScopedAuthorRules(bool includeEmptyRules)
+{
+#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
+    if (!m_scopeResolver)
+        return;
+
+    // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
+    if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsistency(m_state.element())) {
+        bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyles();
+        bool documentScope = true;
+        unsigned scopeSize = m_scopeResolver->stackSize();
+        for (unsigned i = 0; i < scopeSize; ++i) {
+            clearMatchedRules();
+            m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1;
+
+            const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
+            documentScope = documentScope && !frame.m_scope->isInShadowTree();
+            if (documentScope) {
+                if (!applyAuthorStyles)
+                    continue;
+            } else {
+                if (!m_scopeResolver->matchesStyleBounds(frame))
+                    continue;
+            }
+
+            MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.m_scope);
+            StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
+            collectMatchingRules(matchRequest, ruleRange);
+            collectMatchingRulesForRegion(matchRequest, ruleRange);
+            sortAndTransferMatchedRules();
+        }
+    }
+
+    matchHostRules(includeEmptyRules);
+#else
+    UNUSED_PARAM(includeEmptyRules);
+#endif
+}
+
+void ElementRuleCollector::matchHostRules(bool includeEmptyRules)
+{
+#if ENABLE(SHADOW_DOM)
+    ASSERT(m_scopeResolver);
+
+    clearMatchedRules();
+    m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1;
+
+    Vector<RuleSet*> matchedRules;
+    m_scopeResolver->matchHostRules(m_state.element(), matchedRules);
+    if (matchedRules.isEmpty())
+        return;
+
+    for (unsigned i = matchedRules.size(); i > 0; --i) {
+        StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
+        collectMatchingRules(MatchRequest(matchedRules.at(i-1), includeEmptyRules, m_state.element()), ruleRange);
+    }
+    sortAndTransferMatchedRules();
+#else
+    UNUSED_PARAM(includeEmptyRules);
+#endif
+}
+
+#if ENABLE(SHADOW_DOM)
+inline void ElementRuleCollector::matchShadowDistributedRules(bool includeEmptyRules, StyleResolver::RuleRange& ruleRange)
+{
+    if (m_ruleSets.shadowDistributedRules().isEmpty())
+        return;
+
+    TemporaryChange<bool> canUseFastReject(m_canUseFastReject, false);
+    TemporaryChange<SelectorChecker::BehaviorAtBoundary> behaviorAtBoundary(m_behaviorAtBoundary, SelectorChecker::CrossesBoundary);
+
+    Vector<MatchRequest> matchRequests;
+    m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules, matchRequests);
+    for (size_t i = 0; i < matchRequests.size(); ++i)
+        collectMatchingRules(matchRequests[i], ruleRange);
+}
+#endif
+
+void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules)
+{
+    clearMatchedRules();
+    m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1;
+
+    if (!m_state.element())
+        return;
+
+    // Match global author rules.
+    MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules);
+    StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();
+    collectMatchingRules(matchRequest, ruleRange);
+    collectMatchingRulesForRegion(matchRequest, ruleRange);
+#if ENABLE(SHADOW_DOM)
+    matchShadowDistributedRules(includeEmptyRules, ruleRange);
+#endif
+    sortAndTransferMatchedRules();
+
+    matchScopedAuthorRules(includeEmptyRules);
+}
+
+void ElementRuleCollector::matchUserRules(bool includeEmptyRules)
+{
+    if (!m_ruleSets.userStyle())
+        return;
+    
+    clearMatchedRules();
+
+    m_result.ranges.lastUserRule = m_result.matchedProperties.size() - 1;
+    MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules);
+    StyleResolver::RuleRange ruleRange = m_result.ranges.userRuleRange();
+    collectMatchingRules(matchRequest, ruleRange);
+    collectMatchingRulesForRegion(matchRequest, ruleRange);
+
+    sortAndTransferMatchedRules();
+}
+
+void ElementRuleCollector::matchUARules()
+{
+    TemporaryChange<bool> scope(m_matchingUARules, true);
+
+    // First we match rules from the user agent sheet.
+    if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
+        m_result.isCacheable = false;
+    RuleSet* userAgentStyleSheet = m_isPrintStyle
+        ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
+    matchUARules(userAgentStyleSheet);
+
+    // In quirks mode, we match rules from the quirks user agent sheet.
+    if (document()->inQuirksMode())
+        matchUARules(CSSDefaultStyleSheets::defaultQuirksStyle);
+
+    // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
+    if (document()->isViewSource())
+        matchUARules(CSSDefaultStyleSheets::viewSourceStyle());
+}
+
+void ElementRuleCollector::matchUARules(RuleSet* rules)
+{
+    clearMatchedRules();
+    
+    m_result.ranges.lastUARule = m_result.matchedProperties.size() - 1;
+    StyleResolver::RuleRange ruleRange = m_result.ranges.UARuleRange();
+    collectMatchingRules(MatchRequest(rules), ruleRange);
+
+    sortAndTransferMatchedRules();
+}
+
+inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, PseudoId& dynamicPseudo)
+{
+    const StyleResolver::State& state = m_state;
+
+    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.
+        if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && state.element()->isHTMLElement()) {
+            if (!ruleData.hasMultipartSelector())
+                return true;
+        }
+        if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(state.element(), ruleData.selector()->tagQName()))
+            return false;
+        SelectorCheckerFastPath selectorCheckerFastPath(ruleData.selector(), state.element());
+        if (!selectorCheckerFastPath.matchesRightmostAttributeSelector())
+            return false;
+
+        return selectorCheckerFastPath.matches();
+    }
+
+    // Slow path.
+    SelectorChecker selectorChecker(document(), m_mode);
+    SelectorChecker::SelectorCheckingContext context(ruleData.selector(), state.element(), SelectorChecker::VisitedMatchEnabled);
+    context.elementStyle = state.style();
+    context.scope = scope;
+    context.pseudoId = m_pseudoStyleRequest.pseudoId;
+    context.scrollbar = m_pseudoStyleRequest.scrollbar;
+    context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
+    context.behaviorAtBoundary = m_behaviorAtBoundary;
+    SelectorChecker::Match match = selectorChecker.match(context, dynamicPseudo, DOMSiblingTraversalStrategy());
+    if (match != SelectorChecker::SelectorMatches)
+        return false;
+    if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.pseudoId != dynamicPseudo)
+        return false;
+    return true;
+}
+
+void ElementRuleCollector::collectMatchingRulesForList(const Vector<RuleData>* rules, const MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange)
+{
+    if (!rules)
+        return;
+
+    const StyleResolver::State& state = m_state;
+
+    unsigned size = rules->size();
+    for (unsigned i = 0; i < size; ++i) {
+        const RuleData& ruleData = rules->at(i);
+        if (m_canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
+            continue;
+
+        StyleRule* rule = ruleData.rule();
+        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule, m_inspectorCSSOMWrappers, document()->styleSheetCollection());
+        PseudoId dynamicPseudo = NOPSEUDO;
+        if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo)) {
+            // 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)) {
+                InspectorInstrumentation::didMatchRule(cookie, false);
+                continue;
+            }
+            // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
+            if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) {
+                InspectorInstrumentation::didMatchRule(cookie, false);
+                continue;
+            }
+            // 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::CollectingRules) {
+                    InspectorInstrumentation::didMatchRule(cookie, false);
+                    continue;
+                }
+                if (dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
+                    state.style()->setHasPseudoStyle(dynamicPseudo);
+            } else {
+                // Update our first/last rule indices in the matched rules array.
+                ++ruleRange.lastRuleIndex;
+                if (ruleRange.firstRuleIndex == -1)
+                    ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
+
+                // Add this rule to our list of matched rules.
+                addMatchedRule(&ruleData);
+                InspectorInstrumentation::didMatchRule(cookie, true);
+                continue;
+            }
+        }
+        InspectorInstrumentation::didMatchRule(cookie, false);
+    }
+}
+
+static inline bool compareRules(const RuleData* r1, const RuleData* r2)
+{
+    unsigned specificity1 = r1->specificity();
+    unsigned specificity2 = r2->specificity();
+    return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
+}
+
+void ElementRuleCollector::sortMatchedRules()
+{
+    ASSERT(m_matchedRules);
+    std::sort(m_matchedRules->begin(), m_matchedRules->end(), compareRules);
+}
+
+void ElementRuleCollector::matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties)
+{
+    matchUARules();
+
+    // Now we check user sheet rules.
+    if (matchAuthorAndUserStyles)
+        matchUserRules(false);
+
+    // Now check author rules, beginning first with presentational attributes mapped from HTML.
+    if (m_state.styledElement()) {
+        addElementStyleProperties(m_state.styledElement()->presentationAttributeStyle());
+
+        // Now we check additional mapped declarations.
+        // Tables and table cells share an additional mapped rule that must be applied
+        // after all attributes, since their mapped style depends on the values of multiple attributes.
+        addElementStyleProperties(m_state.styledElement()->additionalPresentationAttributeStyle());
+
+        if (m_state.styledElement()->isHTMLElement()) {
+            bool isAuto;
+            TextDirection textDirection = toHTMLElement(m_state.styledElement())->directionalityIfhasDirAutoAttribute(isAuto);
+            if (isAuto)
+                m_result.addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
+        }
+    }
+    
+    // Check the rules in author sheets next.
+    if (matchAuthorAndUserStyles)
+        matchAuthorRules(false);
+
+    // Now check our inline style attribute.
+    if (matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->inlineStyle()) {
+        // Inline style is immutable as long as there is no CSSOM wrapper.
+        // FIXME: Media control shadow trees seem to have problems with caching.
+        bool isInlineStyleCacheable = !m_state.styledElement()->inlineStyle()->isMutable() && !m_state.styledElement()->isInShadowTree();
+        // FIXME: Constify.
+        addElementStyleProperties(m_state.styledElement()->inlineStyle(), isInlineStyleCacheable);
+    }
+
+#if ENABLE(SVG)
+    // Now check SMIL animation override style.
+    if (includeSMILProperties && matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->isSVGElement())
+        addElementStyleProperties(static_cast<SVGElement*>(m_state.styledElement())->animatedSMILStyleProperties(), false /* isCacheable */);
+#else
+    UNUSED_PARAM(includeSMILProperties);
+#endif
+}
+
+bool ElementRuleCollector::hasAnyMatchingRules(RuleSet* ruleSet)
+{
+    clearMatchedRules();
+
+    m_mode = SelectorChecker::SharingRules;
+    int firstRuleIndex = -1, lastRuleIndex = -1;
+    StyleResolver::RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
+    collectMatchingRules(MatchRequest(ruleSet), ruleRange);
+
+    return m_matchedRules && !m_matchedRules->isEmpty();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/ElementRuleCollector.h b/Source/WebCore/css/ElementRuleCollector.h
new file mode 100644 (file)
index 0000000..987584f
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ElementRuleCollector_h
+#define ElementRuleCollector_h
+
+#include "MediaQueryEvaluator.h"
+#include "SelectorChecker.h"
+#include "StyleResolver.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSRuleList;
+class DocumentRuleSets;
+class RenderRegion;
+class RuleData;
+class RuleSet;
+class SelectorFilter;
+class StyleScopeResolver;
+class StaticCSSRuleList;
+
+class ElementRuleCollector {
+public:
+    ElementRuleCollector(StyleResolver* styleResolver, const StyleResolver::State& state)
+        : m_state(state)
+        , m_ruleSets(styleResolver->ruleSets())
+        , m_selectorFilter(styleResolver->selectorFilter())
+        , m_inspectorCSSOMWrappers(styleResolver->inspectorCSSOMWrappers())
+        , m_scopeResolver(styleResolver->scopeResolver())
+        , m_isPrintStyle(false)
+        , m_regionForStyling(0)
+        , m_pseudoStyleRequest(NOPSEUDO)
+        , m_sameOriginOnly(false)
+        , m_mode(SelectorChecker::ResolvingStyle)
+        , m_canUseFastReject(m_selectorFilter.parentStackIsConsistent(state.parentNode()))
+        , m_behaviorAtBoundary(SelectorChecker::DoesNotCrossBoundary)
+        , m_matchingUARules(false) { }
+
+    void matchAllRules(bool matchAuthorAndUserStyles, bool includeSMILProperties);
+    void matchUARules();
+    void matchAuthorRules(bool includeEmptyRules);
+    void matchUserRules(bool includeEmptyRules);
+
+    void setMode(SelectorChecker::Mode mode) { m_mode = mode; }
+    void setPseudoStyleRequest(const PseudoStyleRequest& request) { m_pseudoStyleRequest = request; }
+    void setSameOriginOnly(bool f) { m_sameOriginOnly = f; } 
+    void setRegionForStyling(RenderRegion* regionForStyling) { m_regionForStyling = regionForStyling; }
+    void setMedium(const MediaQueryEvaluator* medium) { m_isPrintStyle = medium->mediaTypeMatchSpecific("print"); }
+
+    bool hasAnyMatchingRules(RuleSet*);
+
+    StyleResolver::MatchResult& matchedResult();
+    PassRefPtr<CSSRuleList> matchedRuleList();
+
+private:
+    Document* document() { return m_state.document(); }
+    void addElementStyleProperties(const StylePropertySet*, bool isCacheable = true);
+
+#if ENABLE(SHADOW_DOM)
+    void matchUARules(RuleSet*);
+    void matchShadowDistributedRules(bool includeEmptyRules, StyleResolver::RuleRange&);
+    void matchScopedAuthorRules(bool includeEmptyRules);
+    void matchHostRules(bool includeEmptyRules);
+#endif
+
+    void collectMatchingRules(const MatchRequest&, StyleResolver::RuleRange&);
+    void collectMatchingRulesForRegion(const MatchRequest&, StyleResolver::RuleRange&);
+    void collectMatchingRulesForList(const Vector<RuleData>*, const MatchRequest&, StyleResolver::RuleRange&);
+    bool ruleMatches(const RuleData&, const ContainerNode* scope, PseudoId&);
+
+    void sortMatchedRules();
+    void sortAndTransferMatchedRules();
+
+    void addMatchedRule(const RuleData*);
+    void clearMatchedRules();
+
+    StaticCSSRuleList* ensureRuleList();
+        
+private:
+    const StyleResolver::State& m_state;
+    DocumentRuleSets& m_ruleSets;
+    SelectorFilter& m_selectorFilter;
+    InspectorCSSOMWrappers& m_inspectorCSSOMWrappers;
+    StyleScopeResolver* m_scopeResolver;
+
+    bool m_isPrintStyle;
+    RenderRegion* m_regionForStyling;
+    PseudoStyleRequest m_pseudoStyleRequest;
+    bool m_sameOriginOnly;
+    SelectorChecker::Mode m_mode;
+    bool m_canUseFastReject;
+    SelectorChecker::BehaviorAtBoundary m_behaviorAtBoundary;
+    bool m_matchingUARules;
+
+    OwnPtr<Vector<const RuleData*, 32> > m_matchedRules;
+
+    // Output.
+    RefPtr<StaticCSSRuleList> m_ruleList;
+    StyleResolver::MatchResult m_result;
+};
+
+} // namespace WebCore
+
+#endif // ElementRuleCollector_h
diff --git a/Source/WebCore/css/PageRuleCollector.cpp b/Source/WebCore/css/PageRuleCollector.cpp
new file mode 100644 (file)
index 0000000..e766e76
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "PageRuleCollector.h"
+
+#include "CSSDefaultStyleSheets.h"
+#include "StylePropertySet.h"
+#include "StyleRule.h"
+
+namespace WebCore {
+
+static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
+{
+    return r1->selector()->specificity() < r2->selector()->specificity();
+}
+
+bool PageRuleCollector::isLeftPage(int pageIndex) const
+{
+    bool isFirstPageLeft = false;
+    if (!m_state.rootElementStyle()->isLeftToRightDirection())
+        isFirstPageLeft = true;
+
+    return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
+}
+
+bool PageRuleCollector::isFirstPage(int pageIndex) const
+{
+    // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
+    return (!pageIndex);
+}
+
+String PageRuleCollector::pageName(int /* pageIndex */) const
+{
+    // FIXME: Implement page index to page name mapping.
+    return "";
+}
+
+void PageRuleCollector::matchAllPageRules(int pageIndex)
+{
+    const bool isLeft = isLeftPage(pageIndex);
+    const bool isFirst = isFirstPage(pageIndex);
+    const String page = pageName(pageIndex);
+    
+    matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page);
+    matchPageRules(m_ruleSets.userStyle(), isLeft, isFirst, page);
+    // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
+    matchPageRules(m_ruleSets.authorStyle(), isLeft, isFirst, page);
+}
+
+void PageRuleCollector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+    if (!rules)
+        return;
+
+    Vector<StyleRulePage*> matchedPageRules;
+    matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
+    if (matchedPageRules.isEmpty())
+        return;
+
+    std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
+
+    for (unsigned i = 0; i < matchedPageRules.size(); i++)
+        m_result.addMatchedProperties(matchedPageRules[i]->properties());
+}
+
+static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+    for (const CSSSelector* component = selector; component; component = component->tagHistory()) {
+        if (component->m_match == CSSSelector::Tag) {
+            const AtomicString& localName = component->tagQName().localName();
+            if (localName != starAtom && localName != pageName)
+                return false;
+        }
+
+        CSSSelector::PseudoType pseudoType = component->pseudoType();
+        if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
+            || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
+            || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+    for (unsigned i = 0; i < rules.size(); ++i) {
+        StyleRulePage* rule = rules[i];
+
+        if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName))
+            continue;
+
+        // If the rule has no properties to apply, then ignore it.
+        const StylePropertySet* properties = rule->properties();
+        if (!properties || properties->isEmpty())
+            continue;
+
+        // Add this rule to our list of matched rules.
+        matchedRules.append(rule);
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/PageRuleCollector.h b/Source/WebCore/css/PageRuleCollector.h
new file mode 100644 (file)
index 0000000..8f5c29a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PageRuleCollector_h
+#define PageRuleCollector_h
+
+#include "DocumentRuleSets.h"
+#include "StyleResolver.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class StyleRulePage;
+
+class PageRuleCollector {
+public:
+    PageRuleCollector(StyleResolver::State& state, DocumentRuleSets& ruleSets)
+        : m_state(state)
+        , m_ruleSets(ruleSets) { }
+
+    void matchAllPageRules(int pageIndex);
+    StyleResolver::MatchResult& matchedResult() { return m_result; }
+
+private:
+    bool isLeftPage(int pageIndex) const;
+    bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
+    bool isFirstPage(int pageIndex) const;
+    String pageName(int pageIndex) const;
+
+    void matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName);
+    void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName);
+
+    const StyleResolver::State& m_state;
+    DocumentRuleSets& m_ruleSets;
+
+    StyleResolver::MatchResult m_result;
+};
+
+} // namespace WebCore
+
+#endif // PageRuleCollector_h
index 38ba839..f841c84 100644 (file)
@@ -59,6 +59,7 @@
 #include "CounterContent.h"
 #include "CursorList.h"
 #include "DocumentStyleSheetCollection.h"
+#include "ElementRuleCollector.h"
 #include "ElementShadow.h"
 #include "FontFeatureValue.h"
 #include "FontValue.h"
@@ -86,6 +87,7 @@
 #include "NodeRenderStyle.h"
 #include "NodeRenderingContext.h"
 #include "Page.h"
+#include "PageRuleCollector.h"
 #include "Pair.h"
 #include "PerspectiveTransformOperation.h"
 #include "QuotesData.h"
 #include "ShadowData.h"
 #include "ShadowRoot.h"
 #include "ShadowValue.h"
-#include "SiblingTraversalStrategies.h"
 #include "SkewTransformOperation.h"
 #include "StyleBuilder.h"
 #include "StyleCachedImage.h"
@@ -210,30 +211,6 @@ if (isInitial) { \
 
 RenderStyle* StyleResolver::s_styleNotYetAvailable;
 
-static StylePropertySet* leftToRightDeclaration()
-{
-    DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
-    if (leftToRightDecl->isEmpty())
-        leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
-    return leftToRightDecl.get();
-}
-
-static StylePropertySet* rightToLeftDeclaration()
-{
-    DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
-    if (rightToLeftDecl->isEmpty())
-        rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
-    return rightToLeftDecl.get();
-}
-
-
-inline StaticCSSRuleList* StyleResolver::State::ensureRuleList()
-{
-    if (!m_ruleList)
-        m_ruleList = StaticCSSRuleList::create();
-    return m_ruleList.get();
-}
-
 inline void StyleResolver::State::cacheBorderAndBackground()
 {
     m_hasUAAppearance = m_style->hasAppearance();
@@ -251,8 +228,6 @@ inline void StyleResolver::State::clear()
     m_parentStyle = 0;
     m_parentNode = 0;
     m_regionForStyling = 0;
-    m_ruleList = 0;
-    m_matchedRules.clear();
     m_pendingImageProperties.clear();
 #if ENABLE(CSS_SHADERS)
     m_hasPendingShaders = false;
@@ -262,6 +237,16 @@ inline void StyleResolver::State::clear()
 #endif
 }
 
+void StyleResolver::MatchResult::addMatchedProperties(const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
+{
+    matchedProperties.grow(matchedProperties.size() + 1);
+    StyleResolver::MatchedProperties& newProperties = matchedProperties.last();
+    newProperties.properties = const_cast<StylePropertySet*>(properties);
+    newProperties.linkMatchType = linkMatchType;
+    newProperties.whitelistType = propertyWhitelistType;
+    matchedRules.append(rule);
+}
+
 StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
     : m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
     , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
@@ -405,182 +390,6 @@ void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
 }
 
-void StyleResolver::addMatchedProperties(MatchResult& matchResult, const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
-{
-    matchResult.matchedProperties.grow(matchResult.matchedProperties.size() + 1);
-    MatchedProperties& newProperties = matchResult.matchedProperties.last();
-    newProperties.properties = const_cast<StylePropertySet*>(properties);
-    newProperties.linkMatchType = linkMatchType;
-    newProperties.whitelistType = propertyWhitelistType;
-    matchResult.matchedRules.append(rule);
-}
-
-inline void StyleResolver::addElementStyleProperties(MatchResult& result, const StylePropertySet* propertySet, bool isCacheable)
-{
-    if (!propertySet)
-        return;
-    result.ranges.lastAuthorRule = result.matchedProperties.size();
-    if (result.ranges.firstAuthorRule == -1)
-        result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
-    addMatchedProperties(result, propertySet);
-    if (!isCacheable)
-        result.isCacheable = false;
-}
-
-class MatchingUARulesScope {
-public:
-    MatchingUARulesScope();
-    ~MatchingUARulesScope();
-
-    static bool isMatchingUARules();
-
-private:
-    static bool m_matchingUARules;
-};
-
-MatchingUARulesScope::MatchingUARulesScope()
-{
-    ASSERT(!m_matchingUARules);
-    m_matchingUARules = true;
-}
-
-MatchingUARulesScope::~MatchingUARulesScope()
-{
-    m_matchingUARules = false;
-}
-
-inline bool MatchingUARulesScope::isMatchingUARules()
-{
-    return m_matchingUARules;
-}
-
-bool MatchingUARulesScope::m_matchingUARules = false;
-
-void StyleResolver::collectMatchingRules(const MatchRequest& matchRequest, RuleRange& ruleRange)
-{
-    ASSERT(matchRequest.ruleSet);
-    ASSERT(m_state.element());
-
-    State& state = m_state;
-    Element* element = state.element();
-    const StyledElement* styledElement = state.styledElement();
-    const AtomicString& pseudoId = element->shadowPseudoId();
-    if (!pseudoId.isEmpty()) {
-        ASSERT(styledElement);
-        collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), matchRequest, ruleRange);
-    }
-
-#if ENABLE(VIDEO_TRACK)
-    if (element->isWebVTTElement())
-        collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange);
-#endif
-    // 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
-    TreeScope* treeScope = element->treeScope();
-    if (!MatchingUARulesScope::isMatchingUARules()
-        && !treeScope->applyAuthorStyles()
-        && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope)
-        && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary)
-        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()), matchRequest, ruleRange);
-    if (styledElement && styledElement->hasClass()) {
-        for (size_t i = 0; i < styledElement->classNames().size(); ++i)
-            collectMatchingRulesForList(matchRequest.ruleSet->classRules(styledElement->classNames()[i].impl()), matchRequest, ruleRange);
-    }
-
-    if (element->isLink())
-        collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest, ruleRange);
-    if (SelectorChecker::matchesFocusPseudoClass(element))
-        collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element->localName().impl()), matchRequest, ruleRange);
-    collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest, ruleRange);
-}
-
-void StyleResolver::collectMatchingRulesForRegion(const MatchRequest& matchRequest, RuleRange& ruleRange)
-{
-    if (!m_state.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, static_cast<Element*>(m_state.regionForStyling()->node()))) {
-            RuleSet* regionRules = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
-            ASSERT(regionRules);
-            collectMatchingRules(MatchRequest(regionRules, matchRequest.includeEmptyRules, matchRequest.scope), ruleRange);
-        }
-    }
-}
-
-void StyleResolver::sortAndTransferMatchedRules(MatchResult& result)
-{
-    State& state = m_state;
-    Vector<const RuleData*, 32>& matchedRules = state.matchedRules();
-    if (matchedRules.isEmpty())
-        return;
-
-    sortMatchedRules();
-
-    if (state.mode() == SelectorChecker::CollectingRules) {
-        for (unsigned i = 0; i < matchedRules.size(); ++i)
-            state.ensureRuleList()->rules().append(matchedRules[i]->rule()->createCSSOMWrapper());
-        return;
-    }
-
-    // Now transfer the set of matched rules over to our list of declarations.
-    for (unsigned i = 0; i < matchedRules.size(); i++) {
-        if (state.style() && matchedRules[i]->containsUncommonAttributeSelector())
-            state.style()->setUnique();
-        addMatchedProperties(result, matchedRules[i]->rule()->properties(), matchedRules[i]->rule(), matchedRules[i]->linkMatchType(), matchedRules[i]->propertyWhitelistType());
-    }
-}
-
-void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
-{
-#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
-    if (!m_scopeResolver)
-        return;
-
-    // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
-    if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsistency(m_state.element())) {
-        bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyles();
-        bool documentScope = true;
-        unsigned scopeSize = m_scopeResolver->stackSize();
-        for (unsigned i = 0; i < scopeSize; ++i) {
-            m_state.matchedRules().clear();
-            result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
-
-            const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
-            documentScope = documentScope && !frame.m_scope->isInShadowTree();
-            if (documentScope) {
-                if (!applyAuthorStyles)
-                    continue;
-            } else {
-                if (!m_scopeResolver->matchesStyleBounds(frame))
-                    continue;
-            }
-
-            MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.m_scope);
-            RuleRange ruleRange = result.ranges.authorRuleRange();
-            collectMatchingRules(matchRequest, ruleRange);
-            collectMatchingRulesForRegion(matchRequest, ruleRange);
-            sortAndTransferMatchedRules(result);
-        }
-    }
-
-    matchHostRules(result, includeEmptyRules);
-#else
-    UNUSED_PARAM(result);
-    UNUSED_PARAM(includeEmptyRules);
-#endif
-}
-
 inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
 {
 #if ENABLE(SHADOW_DOM)
@@ -590,197 +399,6 @@ inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
 #endif
 }
 
-void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules)
-{
-#if ENABLE(SHADOW_DOM)
-    ASSERT(m_scopeResolver);
-
-    m_state.matchedRules().clear();
-    result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
-
-    Vector<RuleSet*> matchedRules;
-    m_scopeResolver->matchHostRules(m_state.element(), matchedRules);
-    if (matchedRules.isEmpty())
-        return;
-
-    for (unsigned i = matchedRules.size(); i > 0; --i) {
-        RuleRange ruleRange = result.ranges.authorRuleRange();
-        collectMatchingRules(MatchRequest(matchedRules.at(i-1), includeEmptyRules, m_state.element()), ruleRange);
-    }
-    sortAndTransferMatchedRules(result);
-#else
-    UNUSED_PARAM(result);
-    UNUSED_PARAM(includeEmptyRules);
-#endif
-}
-
-void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules)
-{
-    m_state.matchedRules().clear();
-    result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
-
-    if (!m_state.element())
-        return;
-
-    // Match global author rules.
-    MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules);
-    RuleRange ruleRange = result.ranges.authorRuleRange();
-    collectMatchingRules(matchRequest, ruleRange);
-    collectMatchingRulesForRegion(matchRequest, ruleRange);
-#if ENABLE(SHADOW_DOM)
-    Vector<MatchRequest> matchRequests;
-    m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules, matchRequests);
-    for (size_t i = 0; i < matchRequests.size(); ++i)
-        collectMatchingRules(matchRequests[i], ruleRange);
-#endif
-
-    sortAndTransferMatchedRules(result);
-
-    matchScopedAuthorRules(result, includeEmptyRules);
-}
-
-void StyleResolver::matchUserRules(MatchResult& result, bool includeEmptyRules)
-{
-    if (!m_ruleSets.userStyle())
-        return;
-    
-    m_state.matchedRules().clear();
-
-    result.ranges.lastUserRule = result.matchedProperties.size() - 1;
-    MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules);
-    RuleRange ruleRange = result.ranges.userRuleRange();
-    collectMatchingRules(matchRequest, ruleRange);
-    collectMatchingRulesForRegion(matchRequest, ruleRange);
-
-    sortAndTransferMatchedRules(result);
-}
-
-void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules)
-{
-    m_state.matchedRules().clear();
-    
-    result.ranges.lastUARule = result.matchedProperties.size() - 1;
-    RuleRange ruleRange = result.ranges.UARuleRange();
-    collectMatchingRules(MatchRequest(rules), ruleRange);
-
-    sortAndTransferMatchedRules(result);
-}
-
-void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, const MatchRequest& matchRequest, RuleRange& ruleRange)
-{
-    if (!rules)
-        return;
-
-    State& state = m_state;
-    // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
-    // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
-    bool canUseFastReject = m_selectorFilter.parentStackIsConsistent(state.parentNode()) && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary;
-
-    unsigned size = rules->size();
-    for (unsigned i = 0; i < size; ++i) {
-        const RuleData& ruleData = rules->at(i);
-        if (canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
-            continue;
-
-        StyleRule* rule = ruleData.rule();
-        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule, this);
-        PseudoId dynamicPseudo = NOPSEUDO;
-        if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo, matchRequest.behaviorAtBoundary)) {
-            // 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)) {
-                InspectorInstrumentation::didMatchRule(cookie, false);
-                continue;
-            }
-            // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
-            if (state.isSameOriginOnly() && !ruleData.hasDocumentSecurityOrigin()) {
-                InspectorInstrumentation::didMatchRule(cookie, false);
-                continue;
-            }
-            // If we're matching normal rules, set a pseudo bit if
-            // we really just matched a pseudo-element.
-            if (dynamicPseudo != NOPSEUDO && state.pseudoStyleRequest().pseudoId == NOPSEUDO) {
-                if (state.mode() == SelectorChecker::CollectingRules) {
-                    InspectorInstrumentation::didMatchRule(cookie, false);
-                    continue;
-                }
-                if (dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
-                    state.style()->setHasPseudoStyle(dynamicPseudo);
-            } else {
-                // Update our first/last rule indices in the matched rules array.
-                ++ruleRange.lastRuleIndex;
-                if (ruleRange.firstRuleIndex == -1)
-                    ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
-
-                // Add this rule to our list of matched rules.
-                m_state.addMatchedRule(&ruleData);
-                InspectorInstrumentation::didMatchRule(cookie, true);
-                continue;
-            }
-        }
-        InspectorInstrumentation::didMatchRule(cookie, false);
-    }
-}
-
-static inline bool compareRules(const RuleData* r1, const RuleData* r2)
-{
-    unsigned specificity1 = r1->specificity();
-    unsigned specificity2 = r2->specificity();
-    return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
-}
-
-void StyleResolver::sortMatchedRules()
-{
-    std::sort(m_state.matchedRules().begin(), m_state.matchedRules().end(), compareRules);
-}
-
-void StyleResolver::matchAllRules(MatchResult& result, bool includeSMILProperties)
-{
-    matchUARules(result);
-
-    // Now we check user sheet rules.
-    if (m_matchAuthorAndUserStyles)
-        matchUserRules(result, false);
-
-    // Now check author rules, beginning first with presentational attributes mapped from HTML.
-    if (m_state.styledElement()) {
-        addElementStyleProperties(result, m_state.styledElement()->presentationAttributeStyle());
-
-        // Now we check additional mapped declarations.
-        // Tables and table cells share an additional mapped rule that must be applied
-        // after all attributes, since their mapped style depends on the values of multiple attributes.
-        addElementStyleProperties(result, m_state.styledElement()->additionalPresentationAttributeStyle());
-
-        if (m_state.styledElement()->isHTMLElement()) {
-            bool isAuto;
-            TextDirection textDirection = toHTMLElement(m_state.styledElement())->directionalityIfhasDirAutoAttribute(isAuto);
-            if (isAuto)
-                addMatchedProperties(result, textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
-        }
-    }
-    
-    // Check the rules in author sheets next.
-    if (m_matchAuthorAndUserStyles)
-        matchAuthorRules(result, false);
-
-    // Now check our inline style attribute.
-    if (m_matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->inlineStyle()) {
-        // Inline style is immutable as long as there is no CSSOM wrapper.
-        // FIXME: Media control shadow trees seem to have problems with caching.
-        bool isInlineStyleCacheable = !m_state.styledElement()->inlineStyle()->isMutable() && !m_state.styledElement()->isInShadowTree();
-        // FIXME: Constify.
-        addElementStyleProperties(result, m_state.styledElement()->inlineStyle(), isInlineStyleCacheable);
-    }
-
-#if ENABLE(SVG)
-    // Now check SMIL animation override style.
-    if (includeSMILProperties && m_matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->isSVGElement())
-        addElementStyleProperties(result, static_cast<SVGElement*>(m_state.styledElement())->animatedSMILStyleProperties(), false /* isCacheable */);
-#else
-    UNUSED_PARAM(includeSMILProperties);
-#endif
-}
-
 bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
 {
     for (unsigned i = 0; i < classNames.size(); ++i) {
@@ -808,9 +426,8 @@ inline void StyleResolver::initElement(Element* e)
     }
 }
 
-inline void StyleResolver::State::initForStyleResolve(Document* document, Element* e, RenderStyle* parentStyle, const PseudoStyleRequest& pseudoStyleRequest, RenderRegion* regionForStyling)
+inline void StyleResolver::State::initForStyleResolve(Document* document, Element* e, RenderStyle* parentStyle, RenderRegion* regionForStyling)
 {
-    m_pseudoStyleRequest = pseudoStyleRequest;
     m_regionForStyling = regionForStyling;
 
     if (e) {
@@ -832,7 +449,6 @@ inline void StyleResolver::State::initForStyleResolve(Document* document, Elemen
 
     m_style = 0;
     m_pendingImageProperties.clear();
-    m_ruleList = 0;
     m_fontDirty = false;
 }
 
@@ -900,17 +516,9 @@ bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
 {
     if (!ruleSet)
         return false;
-    m_state.matchedRules().clear();
-
-    m_state.setMode(SelectorChecker::SharingRules);
-    int firstRuleIndex = -1, lastRuleIndex = -1;
-    RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
-    collectMatchingRules(MatchRequest(ruleSet), ruleRange);
-    m_state.setMode(SelectorChecker::ResolvingStyle);
-    if (m_state.matchedRules().isEmpty())
-        return false;
-    m_state.matchedRules().clear();
-    return true;
+
+    ElementRuleCollector collector(this, m_state);
+    return collector.hasAnyMatchingRules(ruleSet);
 }
 
 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
@@ -1178,26 +786,6 @@ RenderStyle* StyleResolver::locateSharedStyle()
     return shareElement->renderStyle();
 }
 
-void StyleResolver::matchUARules(MatchResult& result)
-{
-    MatchingUARulesScope scope;
-
-    // First we match rules from the user agent sheet.
-    if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
-        result.isCacheable = false;
-    RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
-        ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
-    matchUARules(result, userAgentStyleSheet);
-
-    // In quirks mode, we match rules from the quirks user agent sheet.
-    if (document()->inQuirksMode())
-        matchUARules(result, CSSDefaultStyleSheets::defaultQuirksStyle);
-
-    // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
-    if (document()->isViewSource())
-        matchUARules(result, CSSDefaultStyleSheets::viewSourceStyle());
-}
-
 static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderStyle* style)
 {
     if (paginationMode == Pagination::Unpaginated)
@@ -1395,7 +983,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS
 
     State& state = m_state;
     initElement(element);
-    state.initForStyleResolve(document(), element, defaultParent, NOPSEUDO, regionForStyling);
+    state.initForStyleResolve(document(), element, defaultParent, regionForStyling);
     if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoint()) {
         RenderStyle* sharedStyle = locateSharedStyle();
         if (sharedStyle)
@@ -1437,13 +1025,16 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS
     if (needsCollection)
         m_ruleSets.collectFeatures(document()->isViewSource(), m_scopeResolver.get());
 
-    MatchResult matchResult;
+    ElementRuleCollector collector(this, state);
+    collector.setRegionForStyling(regionForStyling);
+    collector.setMedium(m_medium.get());
+
     if (matchingBehavior == MatchOnlyUserAgentRules)
-        matchUARules(matchResult);
+        collector.matchUARules();
     else
-        matchAllRules(matchResult, matchingBehavior != MatchAllRulesExcludingSMIL);
+        collector.matchAllRules(m_matchAuthorAndUserStyles, matchingBehavior != MatchAllRulesExcludingSMIL);
 
-    applyMatchedProperties(matchResult, element);
+    applyMatchedProperties(collector.matchedResult(), element);
 
     // Clean up our style object's display and text decorations (among other fixups).
     adjustRenderStyle(state.style(), state.parentStyle(), element);
@@ -1460,7 +1051,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* eleme
 {
     MatchResult result;
     if (keyframe->properties())
-        addMatchedProperties(result, keyframe->properties());
+        result.addMatchedProperties(keyframe->properties());
 
     ASSERT(!m_state.style());
 
@@ -1584,7 +1175,7 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P
 
     initElement(e);
 
-    state.initForStyleResolve(document(), e, parentStyle, pseudoStyleRequest);
+    state.initForStyleResolve(document(), e, parentStyle);
     state.setStyle(RenderStyle::create());
     state.style()->inheritFrom(m_state.parentStyle());
 
@@ -1592,20 +1183,22 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P
     // those rules.
 
     // Check UA, user and author rules.
-    MatchResult matchResult;
-    matchUARules(matchResult);
+    ElementRuleCollector collector(this, state);
+    collector.setPseudoStyleRequest(pseudoStyleRequest);
+    collector.setMedium(m_medium.get());
+    collector.matchUARules();
 
     if (m_matchAuthorAndUserStyles) {
-        matchUserRules(matchResult, false);
-        matchAuthorRules(matchResult, false);
+        collector.matchUserRules(false);
+        collector.matchAuthorRules(false);
     }
 
-    if (matchResult.matchedProperties.isEmpty())
+    if (collector.matchedResult().matchedProperties.isEmpty())
         return 0;
 
     state.style()->setStyleType(pseudoStyleRequest.pseudoId);
 
-    applyMatchedProperties(matchResult, e);
+    applyMatchedProperties(collector.matchedResult(), e);
 
     // Clean up our style object's display and text decorations (among other fixups).
     adjustRenderStyle(state.style(), m_state.parentStyle(), 0);
@@ -1626,17 +1219,12 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
     m_state.setStyle(RenderStyle::create());
     m_state.style()->inheritFrom(m_state.rootElementStyle());
 
-    const bool isLeft = isLeftPage(pageIndex);
-    const bool isFirst = isFirstPage(pageIndex);
-    const String page = pageName(pageIndex);
-    
-    MatchResult result;
-    matchPageRules(result, CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page);
-    matchPageRules(result, m_ruleSets.userStyle(), isLeft, isFirst, page);
-    // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
-    matchPageRules(result, m_ruleSets.authorStyle(), isLeft, isFirst, page);
+    PageRuleCollector collector(m_state, m_ruleSets);
+    collector.matchAllPageRules(pageIndex);
     m_state.setLineHeightValue(0);
     bool inheritedOnly = false;
+
+    MatchResult& result = collector.matchedResult();
 #if ENABLE(CSS_VARIABLES)
     applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
 #endif
@@ -2063,89 +1651,31 @@ PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps
     if (!e || !e->document()->haveStylesheetsLoaded())
         return 0;
 
-    m_state.setMode(SelectorChecker::CollectingRules);
-
     initElement(e);
-    m_state.initForStyleResolve(document(), e, 0, pseudoId);
+    m_state.initForStyleResolve(document(), e, 0);
+
+    ElementRuleCollector collector(this, m_state);
+    collector.setMode(SelectorChecker::CollectingRules);
+    collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
+    collector.setMedium(m_medium.get());
 
-    MatchResult dummy;
     if (rulesToInclude & UAAndUserCSSRules) {
         // First we match rules from the user agent sheet.
-        matchUARules(dummy);
+        collector.matchUARules();
 
         // Now we check user sheet rules.
         if (m_matchAuthorAndUserStyles)
-            matchUserRules(dummy, rulesToInclude & EmptyCSSRules);
+            collector.matchUserRules(rulesToInclude & EmptyCSSRules);
     }
 
     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
-        m_state.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
+        collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
 
         // Check the rules in author sheets.
-        matchAuthorRules(dummy, rulesToInclude & EmptyCSSRules);
-
-        m_state.setSameOriginOnly(false);
-    }
-
-    m_state.setMode(SelectorChecker::ResolvingStyle);
-
-    return m_state.takeRuleList();
-}
-
-inline bool StyleResolver::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, PseudoId& dynamicPseudo, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary)
-{
-    State& state = m_state;
-
-    if (ruleData.hasFastCheckableSelector()) {
-        // We know this selector does not include any pseudo elements.
-        if (state.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.
-        if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && state.element()->isHTMLElement()) {
-            if (!ruleData.hasMultipartSelector())
-                return true;
-        }
-        if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(state.element(), ruleData.selector()->tagQName()))
-            return false;
-        SelectorCheckerFastPath selectorCheckerFastPath(ruleData.selector(), state.element());
-        if (!selectorCheckerFastPath.matchesRightmostAttributeSelector())
-            return false;
-
-        return selectorCheckerFastPath.matches();
+        collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
     }
 
-    // Slow path.
-    SelectorChecker selectorChecker(document(), state.mode());
-    SelectorChecker::SelectorCheckingContext context(ruleData.selector(), state.element(), SelectorChecker::VisitedMatchEnabled);
-    context.elementStyle = state.style();
-    context.scope = scope;
-    context.pseudoId = state.pseudoStyleRequest().pseudoId;
-    context.scrollbar = state.pseudoStyleRequest().scrollbar;
-    context.scrollbarPart = state.pseudoStyleRequest().scrollbarPart;
-    context.behaviorAtBoundary = behaviorAtBoundary;
-    SelectorChecker::Match match = selectorChecker.match(context, dynamicPseudo, DOMSiblingTraversalStrategy());
-    if (match != SelectorChecker::SelectorMatches)
-        return false;
-    if (state.pseudoStyleRequest().pseudoId != NOPSEUDO && state.pseudoStyleRequest().pseudoId != dynamicPseudo)
-        return false;
-    return true;
-}
-
-bool StyleResolver::checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement)
-{
-    if (!regionSelector || !regionElement)
-        return false;
-
-    SelectorChecker selectorChecker(document(), m_state.mode());
-    for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
-        SelectorChecker::SelectorCheckingContext selectorCheckingContext(s, regionElement, SelectorChecker::VisitedMatchDisabled);
-        PseudoId ignoreDynamicPseudo = NOPSEUDO;
-        if (selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo, DOMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches)
-            return true;
-    }
-
-    return false;
+    return collector.matchedRuleList();
 }
 
 // -------------------------------------------------------------------------------------
@@ -2424,86 +1954,6 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
     addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
 }
 
-static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
-{
-    return r1->selector()->specificity() < r2->selector()->specificity();
-}
-
-void StyleResolver::matchPageRules(MatchResult& result, RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
-    if (!rules)
-        return;
-
-    Vector<StyleRulePage*> matchedPageRules;
-    matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
-    if (matchedPageRules.isEmpty())
-        return;
-
-    std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
-
-    for (unsigned i = 0; i < matchedPageRules.size(); i++)
-        addMatchedProperties(result, matchedPageRules[i]->properties());
-}
-
-static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
-    for (const CSSSelector* component = selector; component; component = component->tagHistory()) {
-        if (component->m_match == CSSSelector::Tag) {
-            const AtomicString& localName = component->tagQName().localName();
-            if (localName != starAtom && localName != pageName)
-                return false;
-        }
-
-        CSSSelector::PseudoType pseudoType = component->pseudoType();
-        if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
-            || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
-            || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-void StyleResolver::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
-{
-    for (unsigned i = 0; i < rules.size(); ++i) {
-        StyleRulePage* rule = rules[i];
-
-        if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName))
-            continue;
-
-        // If the rule has no properties to apply, then ignore it.
-        const StylePropertySet* properties = rule->properties();
-        if (!properties || properties->isEmpty())
-            continue;
-
-        // Add this rule to our list of matched rules.
-        matchedRules.append(rule);
-    }
-}
-
-bool StyleResolver::isLeftPage(int pageIndex) const
-{
-    bool isFirstPageLeft = false;
-    if (!m_state.rootElementStyle()->isLeftToRightDirection())
-        isFirstPageLeft = true;
-
-    return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
-}
-
-bool StyleResolver::isFirstPage(int pageIndex) const
-{
-    // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
-    return (!pageIndex);
-}
-
-String StyleResolver::pageName(int /* pageIndex */) const
-{
-    // FIXME: Implement page index to page name mapping.
-    return "";
-}
-
 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
 {
     initElement(0);
index 42c95c9..4720119 100644 (file)
@@ -36,6 +36,7 @@
 #include "ScrollTypes.h"
 #include "SelectorChecker.h"
 #include "SelectorFilter.h"
+#include "SiblingTraversalStrategies.h"
 #include "StyleInheritedData.h"
 #include "StyleScopeResolver.h"
 #include "ViewportStyleResolver.h"
@@ -156,12 +157,10 @@ public:
     MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary)
         : ruleSet(ruleSet)
         , includeEmptyRules(includeEmptyRules)
-        , scope(scope)
-        , behaviorAtBoundary(behaviorAtBoundary) { }
+        , scope(scope) { }
     const RuleSet* ruleSet;
     const bool includeEmptyRules;
     const ContainerNode* scope;
-    const SelectorChecker::BehaviorAtBoundary behaviorAtBoundary;
 };
 
 // This class selects a RenderStyle for a given element based on a collection of stylesheets.
@@ -207,6 +206,7 @@ public:
 
     DocumentRuleSets& ruleSets() { return m_ruleSets; }
     const DocumentRuleSets& ruleSets() const { return m_ruleSets; }
+    SelectorFilter& selectorFilter() { return m_selectorFilter; }
 
 #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
     StyleScopeResolver* ensureScopeResolver()
@@ -325,14 +325,6 @@ public:
 
     void loadPendingResources();
 
-private:
-    // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
-    void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
-    void checkForZoomChange(RenderStyle*, RenderStyle* parentStyle);
-    void checkForTextSizeAdjust();
-
-    void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
-
     struct RuleRange {
         RuleRange(int& firstRuleIndex, int& lastRuleIndex): firstRuleIndex(firstRuleIndex), lastRuleIndex(lastRuleIndex) { }
         int& firstRuleIndex;
@@ -374,30 +366,22 @@ private:
         Vector<StyleRule*, 64> matchedRules;
         MatchRanges ranges;
         bool isCacheable;
-    };
 
-    static void addMatchedProperties(MatchResult&, const StylePropertySet* properties, StyleRule* = 0, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone);
-    void addElementStyleProperties(MatchResult&, const StylePropertySet*, bool isCacheable = true);
+        void addMatchedProperties(const StylePropertySet* properties, StyleRule* = 0, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone);
+    };
 
-    void matchAllRules(MatchResult&, bool includeSMILProperties);
-    void matchUARules(MatchResult&);
-    void matchUARules(MatchResult&, RuleSet*);
-    void matchAuthorRules(MatchResult&, bool includeEmptyRules);
-    void matchUserRules(MatchResult&, bool includeEmptyRules);
-    void matchScopedAuthorRules(MatchResult&, bool includeEmptyRules);
-    void matchHostRules(MatchResult&, bool includeEmptyRules);
+private:
+    // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
+    void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
+    void checkForZoomChange(RenderStyle*, RenderStyle* parentStyle);
+    void checkForTextSizeAdjust();
 
-    void collectMatchingRules(const MatchRequest&, RuleRange&);
-    void collectMatchingRulesForRegion(const MatchRequest&, RuleRange&);
-    void collectMatchingRulesForList(const Vector<RuleData>*, const MatchRequest&, RuleRange&);
+    void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
 
     bool fastRejectSelector(const RuleData&) const;
-    void sortMatchedRules();
-    void sortAndTransferMatchedRules(MatchResult&);
 
-    bool ruleMatches(const RuleData&, const ContainerNode* scope, PseudoId&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary);
-    bool checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement);
     void applyMatchedProperties(const MatchResult&, const Element*);
+
     enum StyleApplicationPass {
 #if ENABLE(CSS_VARIABLES)
         VariableDefinitions,
@@ -446,12 +430,9 @@ public:
         , m_parentStyle(0)
         , m_rootElementStyle(0)
         , m_regionForStyling(0)
-        , m_sameOriginOnly(false)
-        , m_pseudoStyleRequest(NOPSEUDO)
         , m_elementLinkState(NotInsideLink)
         , m_distributedToInsertionPoint(false)
         , m_elementAffectedByClassRules(false)
-        , m_mode(SelectorChecker::ResolvingStyle)
         , m_applyPropertyToRegularStyle(true)
         , m_applyPropertyToVisitedLinkStyle(false)
 #if ENABLE(CSS_SHADERS)
@@ -464,7 +445,7 @@ public:
 
     public:
         void initElement(Element*);
-        void initForStyleResolve(Document*, Element*, RenderStyle* parentStyle = 0, const PseudoStyleRequest& = PseudoStyleRequest(NOPSEUDO), RenderRegion* regionForStyling = 0);
+        void initForStyleResolve(Document*, Element*, RenderStyle* parentStyle = 0, RenderRegion* regionForStyling = 0);
         void clear();
 
         Document* document() const { return m_element->document(); }
@@ -474,25 +455,17 @@ public:
         RenderStyle* style() const { return m_style.get(); }
         PassRefPtr<RenderStyle> takeStyle() { return m_style.release(); }
 
-        StaticCSSRuleList* ensureRuleList();
-        PassRefPtr<CSSRuleList> takeRuleList() { return m_ruleList.release(); }
-
         const ContainerNode* parentNode() const { return m_parentNode; }
         void setParentStyle(RenderStyle* parentStyle) { m_parentStyle = parentStyle; }
         RenderStyle* parentStyle() const { return m_parentStyle; }
         RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
 
         const RenderRegion* regionForStyling() const { return m_regionForStyling; }
-        void setSameOriginOnly(bool isSameOriginOnly) { m_sameOriginOnly = isSameOriginOnly; }
-        bool isSameOriginOnly() const { return m_sameOriginOnly; }
-        const PseudoStyleRequest& pseudoStyleRequest() const { return m_pseudoStyleRequest; }
         EInsideLink elementLinkState() const { return m_elementLinkState; }
         bool distributedToInsertionPoint() const { return m_distributedToInsertionPoint; }
         void setElementAffectedByClassRules(bool isAffected) { m_elementAffectedByClassRules = isAffected; }
         bool elementAffectedByClassRules() const { return m_elementAffectedByClassRules; }
-        void setMode(SelectorChecker::Mode mode) { m_mode = mode; }
-        SelectorChecker::Mode mode() const { return m_mode; }
-        
+
         void setApplyPropertyToRegularStyle(bool isApply) { m_applyPropertyToRegularStyle = isApply; }
         void setApplyPropertyToVisitedLinkStyle(bool isApply) { m_applyPropertyToVisitedLinkStyle = isApply; }
         bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
@@ -526,9 +499,8 @@ public:
         void setWritingMode(WritingMode writingMode) { m_fontDirty |= m_style->setWritingMode(writingMode); }
         void setTextOrientation(TextOrientation textOrientation) { m_fontDirty |= m_style->setTextOrientation(textOrientation); }
 
-        Vector<const RuleData*, 32>& matchedRules() { return m_matchedRules; }
-        void addMatchedRule(const RuleData* rule) { m_matchedRules.append(rule); }
-        
+        bool useSVGZoomRules() const { return m_element && m_element->isSVGElement(); }
+
     private:
         // FIXME(bug 108563): to make it easier to review, these member
         // variables are public. However we should add methods to access
@@ -539,24 +511,16 @@ public:
         ContainerNode* m_parentNode;
         RenderStyle* m_parentStyle;
         RenderStyle* m_rootElementStyle;
-        
-        RenderRegion* m_regionForStyling;
-        bool m_sameOriginOnly;
-        PseudoStyleRequest m_pseudoStyleRequest;
 
+        // Required to ASSERT in applyProperties.
+        RenderRegion* m_regionForStyling;
+        
         EInsideLink m_elementLinkState;
 
         bool m_distributedToInsertionPoint;
 
         bool m_elementAffectedByClassRules;
 
-        SelectorChecker::Mode m_mode;
-
-        // A buffer used to hold the set of matched rules for an element,
-        // and a temporary buffer used for merge sorting.
-        Vector<const RuleData*, 32> m_matchedRules;
-        RefPtr<StaticCSSRuleList> m_ruleList;
-
         bool m_applyPropertyToRegularStyle;
         bool m_applyPropertyToVisitedLinkStyle;
 
@@ -695,6 +659,21 @@ inline bool StyleResolver::hasSelectorForId(const AtomicString& idValue) const
     return m_ruleSets.features().idsInRules.contains(idValue.impl());
 }
 
+inline bool checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement)
+{
+    if (!regionSelector || !regionElement)
+        return false;
+
+    SelectorChecker selectorChecker(regionElement->document(), SelectorChecker::QueryingRules);
+    for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) {
+        SelectorChecker::SelectorCheckingContext selectorCheckingContext(s, regionElement, SelectorChecker::VisitedMatchDisabled);
+        PseudoId ignoreDynamicPseudo = NOPSEUDO;
+        if (selectorChecker.match(selectorCheckingContext, ignoreDynamicPseudo, DOMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches)
+            return true;
+    }
+    return false;
+}
+
 } // namespace WebCore
 
 #endif // StyleResolver_h
index 934d09d..3d96b70 100644 (file)
@@ -958,11 +958,11 @@ PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorPro
     return result.release();
 }
 
-void InspectorCSSAgent::willMatchRule(StyleRule* rule, StyleResolver* styleResolver)
+void InspectorCSSAgent::willMatchRule(StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* styleSheetCollection)
 {
 //    printf("InspectorCSSAgent::willMatchRule %s\n", rule->selectorList().selectorsText().utf8().data());
     if (m_currentSelectorProfile)
-        m_currentSelectorProfile->startSelector(styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule, styleResolver->document()->styleSheetCollection()));
+        m_currentSelectorProfile->startSelector(inspectorCSSOMWrappers.getWrapperForRuleInSheets(rule, styleSheetCollection));
 }
 
 void InspectorCSSAgent::didMatchRule(bool matched)
index 143e454..40f8820 100644 (file)
@@ -47,7 +47,9 @@ class CSSStyleDeclaration;
 class CSSStyleRule;
 class CSSStyleSheet;
 class Document;
+class DocumentStyleSheetCollection;
 class Element;
+class InspectorCSSOMWrappers;
 class InspectorFrontend;
 class InstrumentingAgents;
 class NameNodeMap;
@@ -125,7 +127,7 @@ public:
     virtual void stopSelectorProfiler(ErrorString*, RefPtr<TypeBuilder::CSS::SelectorProfile>&);
 
     PassRefPtr<TypeBuilder::CSS::SelectorProfile> stopSelectorProfilerImpl(ErrorString*, bool needProfile);
-    void willMatchRule(StyleRule*, StyleResolver*);
+    void willMatchRule(StyleRule*, InspectorCSSOMWrappers&, DocumentStyleSheetCollection*);
     void didMatchRule(bool);
     void willProcessRule(StyleRule*, StyleResolver*);
     void didProcessRule();
index d45bff9..11b74d8 100644 (file)
@@ -590,11 +590,11 @@ void InspectorInstrumentation::didScheduleStyleRecalculationImpl(InstrumentingAg
         resourceAgent->didScheduleStyleRecalculation(document);
 }
 
-InspectorInstrumentationCookie InspectorInstrumentation::willMatchRuleImpl(InstrumentingAgents* instrumentingAgents, StyleRule* rule, StyleResolver* styleResolver)
+InspectorInstrumentationCookie InspectorInstrumentation::willMatchRuleImpl(InstrumentingAgents* instrumentingAgents, StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* sheetCollection)
 {
     InspectorCSSAgent* cssAgent = instrumentingAgents->inspectorCSSAgent();
     if (cssAgent) {
-        cssAgent->willMatchRule(rule, styleResolver);
+        cssAgent->willMatchRule(rule, inspectorCSSOMWrappers, sheetCollection);
         return InspectorInstrumentationCookie(instrumentingAgents, 1);
     }
 
index 9578b60..0083079 100644 (file)
@@ -61,10 +61,12 @@ class Document;
 class Element;
 class EventContext;
 class DocumentLoader;
+class DocumentStyleSheetCollection;
 class DeviceOrientationData;
 class GeolocationPosition;
 class GraphicsContext;
 class InspectorCSSAgent;
+class InspectorCSSOMWrappers;
 class InspectorInstrumentation;
 class InspectorTimelineAgent;
 class InstrumentingAgents;
@@ -174,7 +176,7 @@ public:
     static InspectorInstrumentationCookie willRecalculateStyle(Document*);
     static void didRecalculateStyle(const InspectorInstrumentationCookie&);
     static void didScheduleStyleRecalculation(Document*);
-    static InspectorInstrumentationCookie willMatchRule(Document*, StyleRule*, StyleResolver*);
+    static InspectorInstrumentationCookie willMatchRule(Document*, StyleRule*, InspectorCSSOMWrappers&, DocumentStyleSheetCollection*);
     static void didMatchRule(const InspectorInstrumentationCookie&, bool matched);
     static InspectorInstrumentationCookie willProcessRule(Document*, StyleRule*, StyleResolver*);
     static void didProcessRule(const InspectorInstrumentationCookie&);
@@ -375,7 +377,7 @@ private:
     static InspectorInstrumentationCookie willRecalculateStyleImpl(InstrumentingAgents*, Frame*);
     static void didRecalculateStyleImpl(const InspectorInstrumentationCookie&);
     static void didScheduleStyleRecalculationImpl(InstrumentingAgents*, Document*);
-    static InspectorInstrumentationCookie willMatchRuleImpl(InstrumentingAgents*, StyleRule*, StyleResolver*);
+    static InspectorInstrumentationCookie willMatchRuleImpl(InstrumentingAgents*, StyleRule*, InspectorCSSOMWrappers&, DocumentStyleSheetCollection*);
     static void didMatchRuleImpl(const InspectorInstrumentationCookie&, bool matched);
     static InspectorInstrumentationCookie willProcessRuleImpl(InstrumentingAgents*, StyleRule*, StyleResolver*);
     static void didProcessRuleImpl(const InspectorInstrumentationCookie&);
@@ -1178,16 +1180,17 @@ inline void InspectorInstrumentation::didScheduleStyleRecalculation(Document* do
 #endif
 }
 
-inline InspectorInstrumentationCookie InspectorInstrumentation::willMatchRule(Document* document, StyleRule* rule, StyleResolver* styleResolver)
+inline InspectorInstrumentationCookie InspectorInstrumentation::willMatchRule(Document* document, StyleRule* rule, InspectorCSSOMWrappers& inspectorCSSOMWrappers, DocumentStyleSheetCollection* styleSheetCollection)
 {
 #if ENABLE(INSPECTOR)
     FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
-        return willMatchRuleImpl(instrumentingAgents, rule, styleResolver);
+        return willMatchRuleImpl(instrumentingAgents, rule, inspectorCSSOMWrappers, styleSheetCollection);
 #else
     UNUSED_PARAM(document);
     UNUSED_PARAM(rule);
-    UNUSED_PARAM(styleResolver);
+    UNUSED_PARAM(inspectorCSSOMWrappers);
+    UNUSED_PARAM(styleSheetCollection);
 #endif
     return InspectorInstrumentationCookie();
 }