| Index: Source/core/css/TreeBoundaryCrossingRules.cpp
|
| diff --git a/Source/core/css/TreeBoundaryCrossingRules.cpp b/Source/core/css/TreeBoundaryCrossingRules.cpp
|
| index 4184d9f568108a3d9e6f7122bb872fae445ee1f9..428a5d560b5ad8a9f6a6a1a93c180ae00fd80c5e 100644
|
| --- a/Source/core/css/TreeBoundaryCrossingRules.cpp
|
| +++ b/Source/core/css/TreeBoundaryCrossingRules.cpp
|
| @@ -29,21 +29,36 @@
|
| #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::addTreeBoundaryCrossingRules(const RuleSet& rules, ContainerNode* scope, CSSStyleSheet* parentStyleSheet)
|
| {
|
| - 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());
|
| + addRules(rules.treeBoundaryCrossingRules(), scope, parentStyleSheet);
|
| + if (scope && !scope->isDocumentNode())
|
| + addRules(rules.shadowDistributedRules(), scope, parentStyleSheet);
|
| +}
|
| +
|
| +void TreeBoundaryCrossingRules::addRules(const WillBeHeapVector<MinimalRuleData>& rules, ContainerNode* scopingNode, CSSStyleSheet* parentStyleSheet)
|
| +{
|
| + if (!m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) {
|
| + OwnPtrWillBeRawPtr<CSSStyleSheetRuleSubSet> styleSheetRuleSubSetForScope = adoptPtr(new CSSStyleSheetRuleSubSet());
|
| + m_treeBoundaryCrossingRuleSetMap.add(scopingNode, styleSheetRuleSubSetForScope.release());
|
| m_scopingNodes.add(scopingNode);
|
| }
|
| + CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode);
|
| +
|
| + OwnPtrWillBeRawPtr<RuleSet> ruleSetForScope = RuleSet::create();
|
| + for (unsigned i = 0; i < rules.size(); ++i) {
|
| + const MinimalRuleData& info = rules[i];
|
| + ruleSetForScope->addRule(info.m_rule, info.m_selectorIndex, info.m_flags);
|
| + }
|
| + ruleSubSet->append(std::make_pair(parentStyleSheet, ruleSetForScope.release()));
|
| }
|
|
|
| void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode)
|
| @@ -52,12 +67,64 @@ void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode)
|
| m_scopingNodes.remove(scopingNode);
|
| }
|
|
|
| +void TreeBoundaryCrossingRules::collectFeaturesFromStyleSheetSubSet(TreeBoundaryCrossingRules::CSSStyleSheetRuleSubSet* styleSheetSubSet, RuleFeatureSet& features)
|
| +{
|
| + for (TreeBoundaryCrossingRules::CSSStyleSheetRuleSubSet::iterator it = styleSheetSubSet->begin(); it != styleSheetSubSet->end(); ++it) {
|
| + RuleSet* ruleSet = it->second.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) {
|
| - RuleSet* ruleSet = it->get();
|
| - features.add(ruleSet->features());
|
| + 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);
|
| + 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 = styleSheetsRuleSubSets->begin(); it != styleSheetsRuleSubSets->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;
|
| + }
|
| +}
|
| +
|
| +
|
| } // namespace WebCore
|
|
|