Title: [130732] trunk/Source/WebCore
Revision
130732
Author
morr...@google.com
Date
2012-10-09 01:00:53 -0700 (Tue, 09 Oct 2012)

Log Message

[Refactoring] Scoped Style related code should have its own class.
https://bugs.webkit.org/show_bug.cgi?id=98244

Reviewed by Dimitri Glazkov.

This change extracts StyleScopeResolver from StyleResolver to clarify
the responsibility of the style scope handling. Now we can easily see
where the style scoping needs to be involed.

Coming Shadow DOM related change like @host rules will fit within this class.

No new tests, refactoring.

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSAllInOne.cpp:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::StyleResolver):
(WebCore::StyleResolver::collectFeatures):
(WebCore::StyleResolver::appendAuthorStylesheets):
(WebCore::StyleResolver::pushParentElement):
(WebCore::StyleResolver::popParentElement):
(WebCore::StyleResolver::pushParentShadowRoot):
(WebCore::StyleResolver::popParentShadowRoot):
(WebCore::StyleResolver::matchScopedAuthorRules):
(WebCore::StyleResolver::collectMatchingRulesForList):
(WebCore::StyleResolver::reportMemoryUsage):
* css/StyleResolver.h:
(StyleResolver):
* css/StyleScopeResolver.cpp: Added.
(WebCore):
(WebCore::StyleScopeResolver::StyleScopeResolver):
(WebCore::StyleScopeResolver::~StyleScopeResolver):
(WebCore::StyleScopeResolver::scopeFor):
(WebCore::StyleScopeResolver::ruleSetFor):
(WebCore::StyleScopeResolver::ensureRuleSetFor):
(WebCore::StyleScopeResolver::setupStack):
(WebCore::StyleScopeResolver::push):
(WebCore::StyleScopeResolver::pop):
(WebCore::StyleScopeResolver::collectFeaturesTo):
(WebCore::StyleScopeResolver::reportMemoryUsage):
* css/StyleScopeResolver.h: Added.
(WebCore):
(StyleScopeResolver):
(WebCore::StyleScopeResolver::StackFrame::StackFrame):
(StackFrame):
(WebCore::StyleScopeResolver::hasScopedStyles):
(WebCore::StyleScopeResolver::stackSize):
(WebCore::StyleScopeResolver::stackFrameAt):
(WebCore::StyleScopeResolver::matchesStyleBounds):
(WebCore::StyleScopeResolver::stackIsConsistent):
(WebCore::StyleScopeResolver::ensureStackConsistency):
(WebCore::StyleScopeResolver::scopeFor):
(WebCore::StyleScopeResolver::ensureRuleSetFor):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (130731 => 130732)


--- trunk/Source/WebCore/CMakeLists.txt	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/CMakeLists.txt	2012-10-09 08:00:53 UTC (rev 130732)
@@ -1081,6 +1081,7 @@
     css/StyleResolver.cpp
     css/StyleRule.cpp
     css/StyleRuleImport.cpp
+    css/StyleScopeResolver.cpp
     css/StyleSheet.cpp
     css/StyleSheetContents.cpp
     css/StyleSheetList.cpp

Modified: trunk/Source/WebCore/ChangeLog (130731 => 130732)


--- trunk/Source/WebCore/ChangeLog	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/ChangeLog	2012-10-09 08:00:53 UTC (rev 130732)
@@ -1,3 +1,63 @@
+2012-10-09  Hajime Morrita  <morr...@google.com>
+
+        [Refactoring] Scoped Style related code should have its own class.
+        https://bugs.webkit.org/show_bug.cgi?id=98244
+
+        Reviewed by Dimitri Glazkov.
+
+        This change extracts StyleScopeResolver from StyleResolver to clarify
+        the responsibility of the style scope handling. Now we can easily see
+        where the style scoping needs to be involed.
+
+        Coming Shadow DOM related change like @host rules will fit within this class.
+
+        No new tests, refactoring.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSAllInOne.cpp:
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::StyleResolver):
+        (WebCore::StyleResolver::collectFeatures):
+        (WebCore::StyleResolver::appendAuthorStylesheets):
+        (WebCore::StyleResolver::pushParentElement):
+        (WebCore::StyleResolver::popParentElement):
+        (WebCore::StyleResolver::pushParentShadowRoot):
+        (WebCore::StyleResolver::popParentShadowRoot):
+        (WebCore::StyleResolver::matchScopedAuthorRules):
+        (WebCore::StyleResolver::collectMatchingRulesForList):
+        (WebCore::StyleResolver::reportMemoryUsage):
+        * css/StyleResolver.h:
+        (StyleResolver):
+        * css/StyleScopeResolver.cpp: Added.
+        (WebCore):
+        (WebCore::StyleScopeResolver::StyleScopeResolver):
+        (WebCore::StyleScopeResolver::~StyleScopeResolver):
+        (WebCore::StyleScopeResolver::scopeFor):
+        (WebCore::StyleScopeResolver::ruleSetFor):
+        (WebCore::StyleScopeResolver::ensureRuleSetFor):
+        (WebCore::StyleScopeResolver::setupStack):
+        (WebCore::StyleScopeResolver::push):
+        (WebCore::StyleScopeResolver::pop):
+        (WebCore::StyleScopeResolver::collectFeaturesTo):
+        (WebCore::StyleScopeResolver::reportMemoryUsage):
+        * css/StyleScopeResolver.h: Added.
+        (WebCore):
+        (StyleScopeResolver):
+        (WebCore::StyleScopeResolver::StackFrame::StackFrame):
+        (StackFrame):
+        (WebCore::StyleScopeResolver::hasScopedStyles):
+        (WebCore::StyleScopeResolver::stackSize):
+        (WebCore::StyleScopeResolver::stackFrameAt):
+        (WebCore::StyleScopeResolver::matchesStyleBounds):
+        (WebCore::StyleScopeResolver::stackIsConsistent):
+        (WebCore::StyleScopeResolver::ensureStackConsistency):
+        (WebCore::StyleScopeResolver::scopeFor):
+        (WebCore::StyleScopeResolver::ensureRuleSetFor):
+
 2012-10-08  Simon Hausmann  <simon.hausm...@digia.com>
 
         [Qt] Make RenderThemeQStyle/ScrollbarThemeQStyle compile without QStyle/QtWidgets

Modified: trunk/Source/WebCore/GNUmakefile.list.am (130731 => 130732)


--- trunk/Source/WebCore/GNUmakefile.list.am	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2012-10-09 08:00:53 UTC (rev 130732)
@@ -2634,6 +2634,8 @@
 	Source/WebCore/css/StyleRule.h \
 	Source/WebCore/css/StyleRuleImport.cpp \
 	Source/WebCore/css/StyleRuleImport.h \
+	Source/WebCore/css/StyleScopeResolver.cpp \
+	Source/WebCore/css/StyleScopeResolver.h \
 	Source/WebCore/css/StyleSheet.cpp \
 	Source/WebCore/css/StyleSheet.h \
 	Source/WebCore/css/StyleSheetContents.cpp \

Modified: trunk/Source/WebCore/Target.pri (130731 => 130732)


--- trunk/Source/WebCore/Target.pri	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/Target.pri	2012-10-09 08:00:53 UTC (rev 130732)
@@ -324,6 +324,7 @@
     css/StyleResolver.cpp \
     css/StyleRule.cpp \
     css/StyleRuleImport.cpp \
+    css/StyleScopeResolver.cpp \
     css/StyleSheet.cpp \
     css/StyleSheetContents.cpp \
     css/StyleSheetList.cpp \

Modified: trunk/Source/WebCore/WebCore.gypi (130731 => 130732)


--- trunk/Source/WebCore/WebCore.gypi	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/WebCore.gypi	2012-10-09 08:00:53 UTC (rev 130732)
@@ -2636,6 +2636,8 @@
             'css/StyleRule.h',
             'css/StyleRuleImport.cpp',
             'css/StyleRuleImport.h',
+            'css/StyleScopeResolver.cpp',
+            'css/StyleScopeResolver.h',
             'css/StyleSheet.cpp',
             'css/StyleSheet.h',
             'css/StyleSheetContents.cpp',

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (130731 => 130732)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-10-09 08:00:53 UTC (rev 130732)
@@ -3876,6 +3876,8 @@
 		A7B070D2130A409C00A3763C /* FrameActionScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B070D0130A409C00A3763C /* FrameActionScheduler.cpp */; };
 		A7B070D3130A409C00A3763C /* FrameActionScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B070D1130A409C00A3763C /* FrameActionScheduler.h */; };
 		A7B6E69F0B291A9600D0529F /* DragData.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B6E69D0B291A9600D0529F /* DragData.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		A7B761A0161EE526002083D3 /* StyleScopeResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B7619E161EE526002083D3 /* StyleScopeResolver.cpp */; };
+		A7B761A1161EE526002083D3 /* StyleScopeResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B7619F161EE526002083D3 /* StyleScopeResolver.h */; };
 		A7BBE26611AFB3F20005EA03 /* JSHTMLMeterElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BBE26411AFB3F20005EA03 /* JSHTMLMeterElement.cpp */; };
 		A7BBE26711AFB3F20005EA03 /* JSHTMLMeterElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BBE26511AFB3F20005EA03 /* JSHTMLMeterElement.h */; };
 		A7BF7EDF14C9175A0014489D /* InternalSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BF7EDC14C9175A0014489D /* InternalSettings.cpp */; };
@@ -11118,6 +11120,8 @@
 		A7B4EA7814C9348400C8F5BF /* JSInternalSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInternalSettings.cpp; sourceTree = "<group>"; };
 		A7B4EA7914C9348400C8F5BF /* JSInternalSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalSettings.h; sourceTree = "<group>"; };
 		A7B6E69D0B291A9600D0529F /* DragData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragData.h; sourceTree = "<group>"; };
+		A7B7619E161EE526002083D3 /* StyleScopeResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleScopeResolver.cpp; sourceTree = "<group>"; };
+		A7B7619F161EE526002083D3 /* StyleScopeResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleScopeResolver.h; sourceTree = "<group>"; };
 		A7B7749614CF6353004044BB /* HTMLContentElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLContentElement.idl; sourceTree = "<group>"; };
 		A7BBE26411AFB3F20005EA03 /* JSHTMLMeterElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLMeterElement.cpp; sourceTree = "<group>"; };
 		A7BBE26511AFB3F20005EA03 /* JSHTMLMeterElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLMeterElement.h; sourceTree = "<group>"; };
@@ -21254,6 +21258,8 @@
 				E4BBED4B14FCDBA1003F0B98 /* StyleRule.h */,
 				E4946EAC156E64DD00D3297F /* StyleRuleImport.cpp */,
 				E4946EAD156E64DD00D3297F /* StyleRuleImport.h */,
+				A7B7619E161EE526002083D3 /* StyleScopeResolver.cpp */,
+				A7B7619F161EE526002083D3 /* StyleScopeResolver.h */,
 				A8EA80050A19516E00A8EF5F /* StyleSheet.cpp */,
 				A8EA80040A19516E00A8EF5F /* StyleSheet.h */,
 				850656DC0AAB44D9002D15C0 /* StyleSheet.idl */,
@@ -25014,6 +25020,7 @@
 				E139866415478474001E3F65 /* StyleResolver.h in Headers */,
 				E4BBED4D14FCDBA1003F0B98 /* StyleRule.h in Headers */,
 				E4946EAF156E64DD00D3297F /* StyleRuleImport.h in Headers */,
+				A7B761A1161EE526002083D3 /* StyleScopeResolver.h in Headers */,
 				3138A9E51474434600B0ED12 /* StyleShader.h in Headers */,
 				A8EA800C0A19516E00A8EF5F /* StyleSheet.h in Headers */,
 				E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */,
@@ -28223,6 +28230,7 @@
 				E139866315478474001E3F65 /* StyleResolver.cpp in Sources */,
 				E4BBED4C14FCDBA1003F0B98 /* StyleRule.cpp in Sources */,
 				E4946EAE156E64DD00D3297F /* StyleRuleImport.cpp in Sources */,
+				A7B761A0161EE526002083D3 /* StyleScopeResolver.cpp in Sources */,
 				A8EA800D0A19516E00A8EF5F /* StyleSheet.cpp in Sources */,
 				E4F9EEF2156D9FFA00D23E7E /* StyleSheetContents.cpp in Sources */,
 				A8EA800B0A19516E00A8EF5F /* StyleSheetList.cpp in Sources */,

Modified: trunk/Source/WebCore/css/CSSAllInOne.cpp (130731 => 130732)


--- trunk/Source/WebCore/css/CSSAllInOne.cpp	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/css/CSSAllInOne.cpp	2012-10-09 08:00:53 UTC (rev 130732)
@@ -72,3 +72,4 @@
 #include "StylePropertySet.cpp"
 #include "StylePropertyShorthand.cpp"
 #include "StyleResolver.cpp"
+#include "StyleScopeResolver.cpp"

Modified: trunk/Source/WebCore/css/StyleResolver.cpp (130731 => 130732)


--- trunk/Source/WebCore/css/StyleResolver.cpp	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/css/StyleResolver.cpp	2012-10-09 08:00:53 UTC (rev 130732)
@@ -114,6 +114,7 @@
 #include "StylePendingImage.h"
 #include "StyleRule.h"
 #include "StyleRuleImport.h"
+#include "StyleScopeResolver.h"
 #include "StyleSheetContents.h"
 #include "StyleSheetList.h"
 #include "Text.h"
@@ -287,10 +288,6 @@
 #if ENABLE(CSS_SHADERS)
     , m_hasPendingShaders(false)
 #endif
-#if ENABLE(STYLE_SCOPED)
-    , m_scopeStackParent(0)
-    , m_scopeStackParentBoundsIndex(0)
-#endif
     , m_styleMap(this)
 {
     Element* root = document->documentElement();
@@ -395,10 +392,8 @@
     // sharing candidates.
     m_features.add(defaultStyle->features());
     m_features.add(m_authorStyle->features());
-#if ENABLE(STYLE_SCOPED)
-    for (ScopedRuleSetMap::iterator it = m_scopedAuthorStyles.begin(); it != m_scopedAuthorStyles.end(); ++it)
-        m_features.add(it->value->features());
-#endif
+    if (m_scopeResolver)
+        m_scopeResolver->collectFeaturesTo(m_features);
     if (m_userStyle)
         m_features.add(m_userStyle->features());
 
@@ -406,38 +401,6 @@
     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
 }
 
-#if ENABLE(STYLE_SCOPED)
-const ContainerNode* StyleResolver::determineScope(const CSSStyleSheet* sheet)
-{
-    ASSERT(sheet);
-
-    if (!ContextFeatures::styleScopedEnabled(document()))
-        return 0;
-
-    Node* ownerNode = sheet->ownerNode();
-    if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag))
-        return 0;
-
-    HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
-    if (!styleElement->scoped())
-        return styleElement->isInShadowTree()? styleElement->shadowRoot() : 0;
-
-    ContainerNode* parent = styleElement->parentNode();
-    if (!parent)
-        return 0;
-
-    return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
-}
-
-inline RuleSet* StyleResolver::ruleSetForScope(const ContainerNode* scope) const
-{
-    if (!scope->hasScopedHTMLStyleChild())
-        return 0;
-    ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(scope);
-    return it != m_scopedAuthorStyles.end() ? it->value.get() : 0; 
-}
-#endif
-
 void StyleResolver::resetAuthorStyle()
 {
     m_authorStyle = RuleSet::create();
@@ -458,16 +421,13 @@
         if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), this))
             continue;
         StyleSheetContents* sheet = cssSheet->contents();
-#if ENABLE(STYLE_SCOPED)
-        const ContainerNode* scope = determineScope(cssSheet);
-        if (scope) {
-            ScopedRuleSetMap::AddResult addResult = m_scopedAuthorStyles.add(scope, nullptr);
-            if (addResult.isNewEntry)
-                addResult.iterator->value = RuleSet::create();
-            addResult.iterator->value->addRulesFromSheet(sheet, *m_medium, this, scope);
+        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
+            if (!m_scopeResolver)
+                m_scopeResolver = adoptPtr(new StyleScopeResolver());
+            m_scopeResolver->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope);
             continue;
         }
-#endif
+
         m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
         if (!m_styleRuleToCSSOMWrapperMap.isEmpty())
             collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, cssSheet);
@@ -479,62 +439,6 @@
         document()->renderer()->style()->font().update(fontSelector());
 }
 
-#if ENABLE(STYLE_SCOPED)
-void StyleResolver::setupScopeStack(const ContainerNode* parent)
-{
-    // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
-    ASSERT(!m_scopedAuthorStyles.isEmpty());
-
-    m_scopeStack.shrink(0);
-    int authorStyleBoundsIndex = 0;
-    for (const ContainerNode* scope = parent; scope; scope = scope->parentOrHostNode()) {
-        RuleSet* ruleSet = ruleSetForScope(scope);
-        if (ruleSet)
-            m_scopeStack.append(ScopeStackFrame(scope, authorStyleBoundsIndex, ruleSet));
-        if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
-            --authorStyleBoundsIndex;
-    }
-    m_scopeStack.reverse();
-    m_scopeStackParent = parent;
-    m_scopeStackParentBoundsIndex = 0;
-}
-
-void StyleResolver::pushScope(const ContainerNode* scope, const ContainerNode* scopeParent)
-{
-    // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
-    if (m_scopedAuthorStyles.isEmpty()) {
-        ASSERT(!m_scopeStackParent);
-        ASSERT(m_scopeStack.isEmpty());
-        return;
-    }
-    // In some wacky cases during style resolve we may get invoked for random elements.
-    // Recreate the whole scoping element stack in such cases.
-    if (!scopeStackIsConsistent(scopeParent)) {
-        setupScopeStack(scope);
-        return;
-    }
-    if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
-        ++m_scopeStackParentBoundsIndex;
-    // Otherwise just push the parent onto the stack.
-    RuleSet* ruleSet = ruleSetForScope(scope);
-    if (ruleSet)
-        m_scopeStack.append(ScopeStackFrame(scope, m_scopeStackParentBoundsIndex, ruleSet));
-    m_scopeStackParent = scope;
-}
-
-void StyleResolver::popScope(const ContainerNode* scope)
-{
-    // Only bother to update the scoping element stack if it is consistent.
-    if (scopeStackIsConsistent(scope)) {
-        if (!m_scopeStack.isEmpty() && m_scopeStack.last().m_scope == scope)
-            m_scopeStack.removeLast();
-        if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
-            --m_scopeStackParentBoundsIndex;
-        m_scopeStackParent = scope->parentOrHostNode();
-    }
-}
-#endif
-
 void StyleResolver::pushParentElement(Element* parent)
 {
     const ContainerNode* parentsParent = parent->parentOrHostElement();
@@ -549,7 +453,8 @@
         m_checker.pushParent(parent);
 
     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
-    pushScope(parent, parent->parentOrHostNode());
+    if (m_scopeResolver)
+        m_scopeResolver->push(parent, parent->parentOrHostNode());
 }
 
 void StyleResolver::popParentElement(Element* parent)
@@ -558,19 +463,22 @@
     // Pause maintaining the stack in this case.
     if (m_checker.parentStackIsConsistent(parent))
         m_checker.popParent();
-    popScope(parent);
+    if (m_scopeResolver)
+        m_scopeResolver->pop(parent);
 }
 
 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
 {
     ASSERT(shadowRoot->host());
-    pushScope(shadowRoot, shadowRoot->host());
+    if (m_scopeResolver)
+        m_scopeResolver->push(shadowRoot, shadowRoot->host());
 }
 
 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
 {
     ASSERT(shadowRoot->host());
-    popScope(shadowRoot);
+    if (m_scopeResolver)
+        m_scopeResolver->pop(shadowRoot);
 }
 
 // This is a simplified style setting function for keyframe styles
@@ -810,26 +718,24 @@
 void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
 {
 #if ENABLE(STYLE_SCOPED)
-    if (m_scopedAuthorStyles.isEmpty())
+    if (!m_scopeResolver || !m_scopeResolver->hasScopedStyles())
         return;
 
     // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
-    if (!scopeStackIsConsistent(m_element))
-        setupScopeStack(m_element);
-    if (m_scopeStack.isEmpty())
+    if (!m_scopeResolver->ensureStackConsistency(m_element))
         return;
 
     bool applyAuthorStyles = m_element->treeScope()->applyAuthorStyles();
     bool documentScope = true;
-    unsigned scopeSize = m_scopeStack.size();
+    unsigned scopeSize = m_scopeResolver->stackSize();
     for (unsigned i = 0; i < scopeSize; ++i) {
-        const ScopeStackFrame& frame = m_scopeStack[i];
+        const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
         documentScope = documentScope && !frame.m_scope->isInShadowTree();
         if (documentScope) {
             if (!applyAuthorStyles)
                 continue;
         } else {
-            if (frame.m_authorStyleBoundsIndex != m_scopeStackParentBoundsIndex)
+            if (!m_scopeResolver->matchesStyleBounds(frame))
                 continue;
         }
            
@@ -934,11 +840,7 @@
 
         StyleRule* rule = ruleData.rule();
         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
-#if ENABLE(STYLE_SCOPED)
         if (checkSelector(ruleData, options.scope)) {
-#else
-        if (checkSelector(ruleData)) {
-#endif
             // Check whether the rule is applicable in the current tree scope. Criteria for this:
             // a) it's a UA rule
             // b) the tree scope allows author rules
@@ -946,9 +848,7 @@
             // d) the rule contains shadow-ID pseudo elements
             if (!MatchingUARulesScope::isMatchingUARules()
                 && !treeScope->applyAuthorStyles()
-#if ENABLE(STYLE_SCOPED)
                 && (!options.scope || options.scope->treeScope() != treeScope)
-#endif
                 && !m_hasUnknownPseudoElements) {
 
                 InspectorInstrumentation::didMatchRule(cookie, false);
@@ -5303,10 +5203,7 @@
 #if ENABLE(CSS_FILTERS) && ENABLE(SVG)
     info.addMember(m_pendingSVGDocuments);
 #endif
-#if ENABLE(STYLE_SCOPED)
-    info.addMember(m_scopedAuthorStyles);
-    info.addMember(m_scopeStack);
-#endif
+    info.addMember(m_scopeResolver);
 
     // FIXME: move this to a place where it would be called only once?
     info.addMember(defaultStyle);

Modified: trunk/Source/WebCore/css/StyleResolver.h (130731 => 130732)


--- trunk/Source/WebCore/css/StyleResolver.h	2012-10-09 07:58:40 UTC (rev 130731)
+++ trunk/Source/WebCore/css/StyleResolver.h	2012-10-09 08:00:53 UTC (rev 130732)
@@ -74,6 +74,7 @@
 class Settings;
 class StaticCSSRuleList;
 class StyleBuilder;
+class StyleScopeResolver;
 class StyleImage;
 class StyleKeyframe;
 class StylePendingImage;
@@ -179,14 +180,6 @@
 
     PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const StyleKeyframe*, KeyframeValue&);
 
-#if ENABLE(STYLE_SCOPED)
-    void pushScope(const ContainerNode* scope, const ContainerNode* scopeParent);
-    void popScope(const ContainerNode* scope);
-#else
-    void pushScope(const ContainerNode*, const ContainerNode*) { }
-    void popScope(const ContainerNode*) { }
-#endif
-
 public:
     // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
     enum CSSRuleFilter {
@@ -493,34 +486,7 @@
     HashMap<FilterOperation*, RefPtr<WebKitCSSSVGDocumentValue> > m_pendingSVGDocuments;
 #endif
 
-#if ENABLE(STYLE_SCOPED)
-    const ContainerNode* determineScope(const CSSStyleSheet*);
-
-    typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap;
-
-    RuleSet* ruleSetForScope(const ContainerNode*) const;
-
-    void setupScopeStack(const ContainerNode*);
-    bool scopeStackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_scopeStackParent; }
-
-    ScopedRuleSetMap m_scopedAuthorStyles;
-    
-    struct ScopeStackFrame {
-        ScopeStackFrame() : m_scope(0), m_authorStyleBoundsIndex(0), m_ruleSet(0) { }
-        ScopeStackFrame(const ContainerNode* scope, int authorStyleBoundsIndex, RuleSet* ruleSet) : m_scope(scope), m_authorStyleBoundsIndex(authorStyleBoundsIndex), m_ruleSet(ruleSet) { }
-        const ContainerNode* m_scope;
-        int m_authorStyleBoundsIndex;
-        RuleSet* m_ruleSet;
-    };
-    // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child)
-    // encountered during tree iteration for style resolution.
-    Vector<ScopeStackFrame> m_scopeStack;
-    // Element last seen as parent element when updating m_scopingElementStack.
-    // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack.
-    const ContainerNode* m_scopeStackParent;
-    int m_scopeStackParentBoundsIndex;
-#endif
-
+    OwnPtr<StyleScopeResolver> m_scopeResolver;
     CSSToStyleMap m_styleMap;
 
     friend class StyleBuilder;

Added: trunk/Source/WebCore/css/StyleScopeResolver.cpp (0 => 130732)


--- trunk/Source/WebCore/css/StyleScopeResolver.cpp	                        (rev 0)
+++ trunk/Source/WebCore/css/StyleScopeResolver.cpp	2012-10-09 08:00:53 UTC (rev 130732)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StyleScopeResolver.h"
+
+#if ENABLE(STYLE_SCOPED)
+
+#include "CSSStyleSheet.h"
+#include "ContextFeatures.h"
+#include "HTMLNames.h"
+#include "HTMLStyleElement.h"
+#include "RuleFeature.h"
+#include "RuleSet.h"
+#include "ShadowRoot.h"
+#include "WebCoreMemoryInstrumentation.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+
+namespace WebCore {
+
+StyleScopeResolver::StyleScopeResolver()
+    : m_stackParent(0)
+    , m_stackParentBoundsIndex(0)
+{
+}
+
+StyleScopeResolver::~StyleScopeResolver()
+{
+}
+
+const ContainerNode* StyleScopeResolver::scopeFor(const CSSStyleSheet* sheet)
+{
+    ASSERT(sheet);
+
+    Document* document = sheet->ownerDocument();
+    if (!document)
+        return 0;
+    if (!ContextFeatures::styleScopedEnabled(document))
+        return 0;
+
+    Node* ownerNode = sheet->ownerNode();
+    if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag))
+        return 0;
+
+    HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
+    if (!styleElement->scoped())
+        return styleElement->isInShadowTree()? styleElement->shadowRoot() : 0;
+
+    ContainerNode* parent = styleElement->parentNode();
+    if (!parent)
+        return 0;
+
+    return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
+}
+
+inline RuleSet* StyleScopeResolver::ruleSetFor(const ContainerNode* scope) const
+{
+    if (!scope->hasScopedHTMLStyleChild())
+        return 0;
+    ScopedRuleSetMap::const_iterator it = m_authorStyles.find(scope);
+    return it != m_authorStyles.end() ? it->value.get() : 0; 
+}
+
+RuleSet* StyleScopeResolver::ensureRuleSetFor(const ContainerNode* scope)
+{
+    ScopedRuleSetMap::AddResult addResult = m_authorStyles.add(scope, nullptr);
+    if (addResult.isNewEntry)
+        addResult.iterator->value = RuleSet::create();
+    return addResult.iterator->value.get();
+}
+
+void StyleScopeResolver::setupStack(const ContainerNode* parent)
+{
+    // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
+    ASSERT(!m_authorStyles.isEmpty());
+
+    m_stack.shrink(0);
+    int authorStyleBoundsIndex = 0;
+    for (const ContainerNode* scope = parent; scope; scope = scope->parentOrHostNode()) {
+        RuleSet* ruleSet = ruleSetFor(scope);
+        if (ruleSet)
+            m_stack.append(StackFrame(scope, authorStyleBoundsIndex, ruleSet));
+        if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
+            --authorStyleBoundsIndex;
+    }
+
+    m_stack.reverse();
+    m_stackParent = parent;
+    m_stackParentBoundsIndex = 0;
+}
+
+void StyleScopeResolver::push(const ContainerNode* scope, const ContainerNode* scopeParent)
+{
+    // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
+    if (m_authorStyles.isEmpty()) {
+        ASSERT(!m_stackParent);
+        ASSERT(m_stack.isEmpty());
+        return;
+    }
+
+    // In some wacky cases during style resolve we may get invoked for random elements.
+    // Recreate the whole scoping element stack in such cases.
+    if (!stackIsConsistent(scopeParent)) {
+        setupStack(scope);
+        return;
+    }
+
+    if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
+        ++m_stackParentBoundsIndex;
+    // Otherwise just push the parent onto the stack.
+    RuleSet* ruleSet = ruleSetFor(scope);
+    if (ruleSet)
+        m_stack.append(StackFrame(scope, m_stackParentBoundsIndex, ruleSet));
+    m_stackParent = scope;
+}
+
+void StyleScopeResolver::pop(const ContainerNode* scope)
+{
+    // Only bother to update the scoping element stack if it is consistent.
+    if (stackIsConsistent(scope)) {
+        if (!m_stack.isEmpty() && m_stack.last().m_scope == scope)
+            m_stack.removeLast();
+        if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
+            --m_stackParentBoundsIndex;
+        m_stackParent = scope->parentOrHostNode();
+    }
+}
+
+void StyleScopeResolver::collectFeaturesTo(RuleFeatureSet& features)
+{
+    for (ScopedRuleSetMap::iterator it = m_authorStyles.begin(); it != m_authorStyles.end(); ++it)
+        features.add(it->value->features());
+}
+
+void StyleScopeResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
+    info.addMember(m_authorStyles);
+    info.addMember(m_stack);
+}
+
+}
+
+#endif // ENABLE(STYLE_SCOPED)

Added: trunk/Source/WebCore/css/StyleScopeResolver.h (0 => 130732)


--- trunk/Source/WebCore/css/StyleScopeResolver.h	                        (rev 0)
+++ trunk/Source/WebCore/css/StyleScopeResolver.h	2012-10-09 08:00:53 UTC (rev 130732)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StyleScopeResolver_h
+#define StyleScopeResolver_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class CSSStyleSheet;
+class RuleSet;
+class RuleFeatureSet;
+
+#if ENABLE(STYLE_SCOPED)
+
+class StyleScopeResolver {
+public:
+    typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap;
+
+    struct StackFrame {
+        StackFrame() : m_scope(0), m_authorStyleBoundsIndex(0), m_ruleSet(0) { }
+        StackFrame(const ContainerNode* scope, int authorStyleBoundsIndex, RuleSet* ruleSet)
+            : m_scope(scope), m_authorStyleBoundsIndex(authorStyleBoundsIndex), m_ruleSet(ruleSet)
+        { }
+
+        const ContainerNode* m_scope;
+        int m_authorStyleBoundsIndex;
+        RuleSet* m_ruleSet;
+    };
+
+    StyleScopeResolver();
+    ~StyleScopeResolver();
+
+    static const ContainerNode* scopeFor(const CSSStyleSheet*);
+
+    void push(const ContainerNode* scope, const ContainerNode* scopeParent);
+    void pop(const ContainerNode* scope);
+    bool hasScopedStyles() const { return !m_authorStyles.isEmpty(); }
+    RuleSet* ensureRuleSetFor(const ContainerNode* scope);
+    bool ensureStackConsistency(ContainerNode*);
+    unsigned stackSize() const { return m_stack.size(); }
+    const StackFrame& stackFrameAt(unsigned index) const { return m_stack.at(index); }
+    bool matchesStyleBounds(const StackFrame& frame) const { return frame.m_authorStyleBoundsIndex == m_stackParentBoundsIndex; }
+    void collectFeaturesTo(RuleFeatureSet&);
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    RuleSet* ruleSetFor(const ContainerNode* scope) const;
+    void setupStack(const ContainerNode*);
+    bool stackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_stackParent; }
+
+    ScopedRuleSetMap m_authorStyles;
+
+    // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child)
+    // encountered during tree iteration for style resolution.
+    Vector<StackFrame> m_stack;
+    // Element last seen as parent element when updating m_scopingElementStack.
+    // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack.
+    const ContainerNode* m_stackParent;
+    int m_stackParentBoundsIndex;
+};
+
+inline bool StyleScopeResolver::ensureStackConsistency(ContainerNode* parent)
+{
+    // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
+    if (!stackIsConsistent(parent))
+        setupStack(parent);
+    return !m_stack.isEmpty();
+}
+
+#else
+
+class StyleScopeResolver {
+public:
+    static const ContainerNode* scopeFor(const CSSStyleSheet*) { return 0; }
+    void push(const ContainerNode*, const ContainerNode*) { }
+    void pop(const ContainerNode*) { }
+    void collectFeaturesTo(RuleFeatureSet&) { }
+    RuleSet* ensureRuleSetFor(const ContainerNode*) { return 0; }
+};
+
+#endif // ENABLE(STYLE_SCOPED)
+
+} // namespace WebCore
+
+#endif // StyleScopeResolver_h
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to