| 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);
|
|
|