Index: Source/core/css/SelectorChecker.cpp |
diff --git a/Source/core/css/SelectorChecker.cpp b/Source/core/css/SelectorChecker.cpp |
index fab750f124da13a2209bad1a0073bdc62821e2d4..339598720ed3a329f9be3994a3242b79e71aa153 100644 |
--- a/Source/core/css/SelectorChecker.cpp |
+++ b/Source/core/css/SelectorChecker.cpp |
@@ -83,8 +83,8 @@ Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, |
if (allowToCrossBoundary) |
return context.element->parentOrShadowHostElement(); |
- // If context.scope is a shadow host, we should walk up from a shadow root to its shadow host. |
- if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost) && context.scope == context.element->shadowHost()) |
+ // If context.scope is a shadow root, we should walk up to its shadow host. |
+ if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot) && context.scope == context.element->containingShadowRoot()) |
return context.element->parentOrShadowHostElement(); |
if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) |
@@ -106,12 +106,12 @@ bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont |
return true; |
ASSERT(context.scope); |
- // If behaviorAtBoundary is not ScopeIsShadowHost, we can use "contains". |
- if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost)) |
+ // If behaviorAtBoundary is not ScopeIsShadowRoot, we can use "contains". |
+ if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot)) |
return context.scope->contains(context.element); |
// If a given element is scope, i.e. shadow host, matches. |
- if (context.element == context.scope && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element))) |
+ if (context.element == context.scope->shadowHost() && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element))) |
return true; |
ShadowRoot* root = context.element->containingShadowRoot(); |
@@ -119,16 +119,14 @@ bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont |
return false; |
// If a host of the containing shadow root is scope, matches. |
- return root->host() == context.scope; |
+ return root == context.scope; |
} |
static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheckingContext& context) |
{ |
- if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) |
- return context.element == context.scope; |
- |
if (context.scope && context.scope->isInShadowTree()) |
- return context.element == context.scope->containingShadowRoot()->host(); |
+ return context.element == context.scope->shadowHost(); |
+ |
return false; |
} |
@@ -342,7 +340,7 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC |
case CSSSelector::ShadowPseudo: |
{ |
// If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope. |
- if (context.scope && context.scope->treeScope() == context.element->treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithinTreeScope) |
+ if (context.scope && context.scope->shadowHost() && context.scope->shadowHost()->treeScope() == context.element->treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithinTreeScope) |
return SelectorFailsCompletely; |
Element* shadowHost = context.element->shadowHost(); |
@@ -389,15 +387,16 @@ SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* |
for (size_t i = 0; i < insertionPoints.size(); ++i) { |
nextContext.element = insertionPoints[i]; |
- // If a given scope is a shadow host of an insertion point but behaviorAtBoundary doesn't have ScopeIsShadowHost, |
+ // If a given scope is a shadow host of an insertion point but behaviorAtBoundary doesn't have ScopeIsShadowRoot, |
// we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly. |
if (m_mode == SharingRules) { |
- nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowHost); |
- nextContext.scope = insertionPoints[i]->containingShadowRoot()->shadowHost(); |
- } else if (scope == insertionPoints[i]->containingShadowRoot()->shadowHost() && !(behaviorAtBoundary & ScopeIsShadowHost)) |
- nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowHost); |
- else |
+ nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot); |
+ nextContext.scope = insertionPoints[i]->containingShadowRoot(); |
+ } else if (scope == insertionPoints[i]->containingShadowRoot() && !(behaviorAtBoundary & ScopeIsShadowRoot)) { |
+ nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot); |
+ } else { |
nextContext.behaviorAtBoundary = behaviorAtBoundary; |
+ } |
nextContext.isSubSelector = false; |
nextContext.elementStyle = 0; |
@@ -537,7 +536,8 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib |
bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.behaviorAtBoundary, context.scope); |
// Only :host and :ancestor should match the host: http://drafts.csswg.org/css-scoping/#host-element |
- if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass()) |
+ if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass() |
+ && !(context.behaviorAtBoundary & TreatShadowHostAsNormalScope)) |
return false; |
if (selector.match() == CSSSelector::Tag) |
@@ -929,7 +929,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib |
// :host only matches a shadow host when :host is in a shadow tree of the shadow host. |
if (!context.scope) |
return false; |
- const ContainerNode* shadowHost = (context.behaviorAtBoundary & ScopeIsShadowHost) ? context.scope : (context.scope->isInShadowTree() ? context.scope->shadowHost() : 0); |
+ const ContainerNode* shadowHost = context.scope->shadowHost(); |
if (!shadowHost || shadowHost != element) |
return false; |
ASSERT(element.shadow()); |
@@ -947,7 +947,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib |
// If one of simple selectors matches an element, returns SelectorMatches. Just "OR". |
for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { |
subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHostParameter; |
- subContext.scope = shadowHost; |
+ subContext.scope = context.scope; |
// Use NodeRenderingTraversal to traverse a composed ancestor list of a given element. |
Element* nextElement = &element; |
SelectorCheckingContext hostContext(subContext); |