Index: Source/core/css/TreeBoundaryCrossingRules.cpp |
diff --git a/Source/core/css/TreeBoundaryCrossingRules.cpp b/Source/core/css/TreeBoundaryCrossingRules.cpp |
index 4184d9f568108a3d9e6f7122bb872fae445ee1f9..e055848df5c4f5162c23f5c4cf9cdc126ccb33e0 100644 |
--- a/Source/core/css/TreeBoundaryCrossingRules.cpp |
+++ b/Source/core/css/TreeBoundaryCrossingRules.cpp |
@@ -29,35 +29,101 @@ |
#include "config.h" |
#include "core/css/TreeBoundaryCrossingRules.h" |
+#include "core/css/ElementRuleCollector.h" |
#include "core/css/RuleFeature.h" |
#include "core/dom/StyleEngine.h" |
+#include "core/dom/shadow/ElementShadow.h" |
+#include "core/dom/shadow/ShadowRoot.h" |
namespace WebCore { |
-void TreeBoundaryCrossingRules::addRule(StyleRule* rule, size_t selectorIndex, ContainerNode* scopingNode, AddRuleFlags addRuleFlags) |
+void TreeBoundaryCrossingRules::addRule(StyleRule* rule, size_t selectorIndex, ContainerNode* scopingNode, CSSStyleSheet* parentStyleSheet, AddRuleFlags addRuleFlags) |
{ |
- if (m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) { |
- m_treeBoundaryCrossingRuleSetMap.get(scopingNode)->addRule(rule, selectorIndex, addRuleFlags); |
+ if (!m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) { |
+ OwnPtrWillBeRawPtr<CSSStyleSheetRuleSubSet> styleSheetRuleSubSetForScope = adoptPtr(new CSSStyleSheetRuleSubSet()); |
+ m_treeBoundaryCrossingRuleSetMap.add(scopingNode, styleSheetRuleSubSetForScope.release()); |
+ OwnPtrWillBeRawPtr<CSSStyleSheetOrder> styleSheetOrderMap = adoptPtr(new CSSStyleSheetOrder()); |
+ m_styleSheetsOrder.add(scopingNode, styleSheetOrderMap.release()); |
+ m_scopingNodes.add(scopingNode); |
+ } |
+ CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode); |
+ |
+ if (ruleSubSet->contains(parentStyleSheet)) { |
+ ruleSubSet->get(parentStyleSheet)->addRule(rule, selectorIndex, addRuleFlags); |
} else { |
OwnPtrWillBeRawPtr<RuleSet> ruleSetForScope = RuleSet::create(); |
ruleSetForScope->addRule(rule, selectorIndex, addRuleFlags); |
- m_treeBoundaryCrossingRuleSetMap.add(scopingNode, ruleSetForScope.release()); |
- m_scopingNodes.add(scopingNode); |
+ ruleSubSet->add(parentStyleSheet, ruleSetForScope.release()); |
+ m_styleSheetsOrder.get(scopingNode)->add(parentStyleSheet); |
} |
} |
void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode) |
{ |
m_treeBoundaryCrossingRuleSetMap.remove(scopingNode); |
+ m_styleSheetsOrder.remove(scopingNode); |
m_scopingNodes.remove(scopingNode); |
} |
-void TreeBoundaryCrossingRules::collectFeaturesTo(RuleFeatureSet& features) |
+void TreeBoundaryCrossingRules::collectFeaturesFromStyleSheetSubSet(TreeBoundaryCrossingRules::CSSStyleSheetRuleSubSet* styleSheetSubSet, RuleFeatureSet& features) |
{ |
- for (TreeBoundaryCrossingRuleSetMap::iterator::Values it = m_treeBoundaryCrossingRuleSetMap.values().begin(); it != m_treeBoundaryCrossingRuleSetMap.values().end(); ++it) { |
+ for (TreeBoundaryCrossingRules::CSSStyleSheetRuleSubSet::iterator::Values it = styleSheetSubSet->values().begin(); it != styleSheetSubSet->values().end(); ++it) { |
RuleSet* ruleSet = it->get(); |
features.add(ruleSet->features()); |
} |
} |
+void TreeBoundaryCrossingRules::collectFeaturesTo(RuleFeatureSet& features) |
+{ |
+ for (TreeBoundaryCrossingRuleSetMap::iterator::Values it = m_treeBoundaryCrossingRuleSetMap.values().begin(); it != m_treeBoundaryCrossingRuleSetMap.values().end(); ++it) { |
+ CSSStyleSheetRuleSubSet* styleSheetSubSet = it->get(); |
+ collectFeaturesFromStyleSheetSubSet(styleSheetSubSet, features); |
+ } |
+} |
+ |
+void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules) |
+{ |
+ if (m_treeBoundaryCrossingRuleSetMap.isEmpty()) |
+ return; |
+ |
+ RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); |
+ |
+ // When comparing rules declared in outer treescopes, outer's rules win. |
+ CascadeOrder outerCascadeOrder = size() + size(); |
+ // When comparing rules declared in inner treescopes, inner's rules win. |
+ CascadeOrder innerCascadeOrder = size(); |
+ |
+ for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) { |
+ const ContainerNode* scopingNode = toContainerNode(*it); |
+ |
+ if (ShadowRoot* shadowRoot = scopingNode->containingShadowRoot()) { |
+ if (!shadowRoot->isActiveForStyling()) |
+ continue; |
+ } |
+ |
+ TreeBoundaryCrossingRules::CSSStyleSheetRuleSubSet* styleSheetsRuleSubSets = m_treeBoundaryCrossingRuleSetMap.get(scopingNode); |
+ CSSStyleSheetOrder* styleSheetsOrder = m_styleSheetsOrder.get(scopingNode); |
+ unsigned boundaryBehavior = SelectorChecker::ScopeContainsLastMatchedElement; |
+ bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope()); |
+ |
+ // If a given scoping node is a shadow root and a given element is in a descendant tree of tree hosted by |
+ // the scoping node's shadow host, we should use ScopeIsShadowHost. |
+ if (scopingNode && scopingNode->isShadowRoot()) { |
+ if (element->isInDescendantTreeOf(toShadowRoot(scopingNode)->host())) |
+ boundaryBehavior |= SelectorChecker::ScopeIsShadowHost; |
+ scopingNode = toShadowRoot(scopingNode)->host(); |
+ } |
+ |
+ CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder; |
+ for (CSSStyleSheetOrder::iterator it = styleSheetsOrder->begin(); it != styleSheetsOrder->end(); ++it) { |
+ CSSStyleSheet* parentStyleSheet = *it; |
+ RuleSet* ruleSet = styleSheetsRuleSubSets->get(parentStyleSheet); |
+ collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder); |
+ } |
+ ++innerCascadeOrder; |
+ --outerCascadeOrder; |
+ } |
+} |
+ |
+ |
} // namespace WebCore |