Chromium Code Reviews| Index: Source/core/css/TreeBoundaryCrossingRules.cpp |
| diff --git a/Source/core/css/TreeBoundaryCrossingRules.cpp b/Source/core/css/TreeBoundaryCrossingRules.cpp |
| index 4184d9f568108a3d9e6f7122bb872fae445ee1f9..1cacd2c2a8dfa01ca920cd5960ff9281be813825 100644 |
| --- a/Source/core/css/TreeBoundaryCrossingRules.cpp |
| +++ b/Source/core/css/TreeBoundaryCrossingRules.cpp |
| @@ -29,21 +29,73 @@ |
| #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/ShadowRoot.h" |
| namespace WebCore { |
| -void TreeBoundaryCrossingRules::addRule(StyleRule* rule, size_t selectorIndex, ContainerNode* scopingNode, AddRuleFlags addRuleFlags) |
| +static void addRules(RuleSet* ruleSet, const WillBeHeapVector<MinimalRuleData>& rules) |
| { |
| - if (m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) { |
| - m_treeBoundaryCrossingRuleSetMap.get(scopingNode)->addRule(rule, selectorIndex, addRuleFlags); |
| - } else { |
| - OwnPtrWillBeRawPtr<RuleSet> ruleSetForScope = RuleSet::create(); |
| - ruleSetForScope->addRule(rule, selectorIndex, addRuleFlags); |
| - m_treeBoundaryCrossingRuleSetMap.add(scopingNode, ruleSetForScope.release()); |
| + for (unsigned i = 0; i < rules.size(); ++i) { |
| + const MinimalRuleData& info = rules[i]; |
| + ruleSet->addRule(info.m_rule, info.m_selectorIndex, info.m_flags); |
| + } |
| +} |
| + |
| +void TreeBoundaryCrossingRules::addTreeBoundaryCrossingRules(const RuleSet& authorRules, ContainerNode* scopingNode, CSSStyleSheet* parentStyleSheet) |
| +{ |
| + OwnPtrWillBeRawPtr<RuleSet> ruleSetForScope = RuleSet::create(); |
| + addRules(ruleSetForScope.get(), authorRules.treeBoundaryCrossingRules()); |
| + if (scopingNode && !scopingNode->isDocumentNode()) |
| + addRules(ruleSetForScope.get(), authorRules.shadowDistributedRules()); |
| + if (!ruleSetForScope->ruleCount()) |
| + return; |
|
esprehn
2014/04/03 09:57:17
How did the old code deal with this being empty? I
lushnikov
2014/04/03 13:53:13
The old code here was "addRule" method which was c
|
| + |
| + if (!m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) { |
|
esprehn
2014/04/03 09:57:17
Can scopingNode actually be null? You check it abo
lushnikov
2014/04/03 13:53:13
My bad; it cannot be null. Removed checking for nu
|
| + m_treeBoundaryCrossingRuleSetMap.add(scopingNode, adoptPtr(new CSSStyleSheetRuleSubSet())); |
| m_scopingNodes.add(scopingNode); |
| } |
| + CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode); |
| + ruleSubSet->append(std::make_pair(parentStyleSheet, ruleSetForScope.release())); |
| +} |
| + |
| +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); |
| + CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.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 (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) { |
| + CSSStyleSheet* parentStyleSheet = it->first; |
| + RuleSet* ruleSet = it->second.get(); |
| + collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder); |
| + } |
| + ++innerCascadeOrder; |
| + --outerCascadeOrder; |
| + } |
| } |
| void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode) |
| @@ -52,11 +104,19 @@ void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode) |
| m_scopingNodes.remove(scopingNode); |
| } |
| +void TreeBoundaryCrossingRules::collectFeaturesFromRuleSubSet(CSSStyleSheetRuleSubSet* ruleSubSet, RuleFeatureSet& features) |
| +{ |
| + for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) { |
| + RuleSet* ruleSet = it->second.get(); |
| + features.add(ruleSet->features()); |
|
esprehn
2014/04/03 09:57:17
I'd just do it->second->features() and make this o
lushnikov
2014/04/03 13:53:13
Done.
|
| + } |
| +} |
| + |
| void TreeBoundaryCrossingRules::collectFeaturesTo(RuleFeatureSet& features) |
| { |
| for (TreeBoundaryCrossingRuleSetMap::iterator::Values it = m_treeBoundaryCrossingRuleSetMap.values().begin(); it != m_treeBoundaryCrossingRuleSetMap.values().end(); ++it) { |
| - RuleSet* ruleSet = it->get(); |
| - features.add(ruleSet->features()); |
| + CSSStyleSheetRuleSubSet* ruleSubSet = it->get(); |
| + collectFeaturesFromRuleSubSet(ruleSubSet, features); |
|
esprehn
2014/04/03 09:57:17
Same, this can be one line and remove the braces
lushnikov
2014/04/03 13:53:13
Done.
|
| } |
| } |