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