Index: Source/core/css/SelectorChecker.cpp |
diff --git a/Source/core/css/SelectorChecker.cpp b/Source/core/css/SelectorChecker.cpp |
index 36d9f5f8c2ddee0301070505f5bd4d84b48fe9e4..5dbb69ca71d004e0cef91b5c7463b6a0f5748594 100644 |
--- a/Source/core/css/SelectorChecker.cpp |
+++ b/Source/core/css/SelectorChecker.cpp |
@@ -154,6 +154,9 @@ SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con |
} else if (context.selector->isContentPseudoElement()) { |
if (!context.element->isInShadowTree() || !context.element->isInsertionPoint()) |
return SelectorFailsLocally; |
+ } else if (context.selector->isShadowPseudoElement()) { |
+ if (!context.element->isInShadowTree()) |
+ return SelectorFailsLocally; |
rune
2014/03/25 20:58:21
You're just checking for isInShadowTree(). Won't t
tasak
2014/03/26 11:01:46
If we have "::shadow ::shadow ::shadow span", CSSP
|
} else { |
if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules) |
return SelectorFailsLocally; |
@@ -211,6 +214,11 @@ static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela |
return nextContext; |
} |
+static inline bool isAuthorShadowRoot(const Node* node) |
+{ |
+ return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowRoot::AuthorShadowRoot; |
+} |
+ |
template<typename SiblingTraversalStrategy> |
SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const |
{ |
@@ -231,6 +239,11 @@ SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki |
return match(nextContext, siblingTraversalStrategy, result); |
} |
+static bool selectorMatchesShadowRoot(const CSSSelector* selector) |
+{ |
+ return selector && selector->isShadowPseudoElement(); |
+} |
+ |
template<typename SiblingTraversalStrategy> |
SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const |
{ |
@@ -255,6 +268,14 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC |
} |
nextContext.isSubSelector = false; |
nextContext.elementStyle = 0; |
+ |
+ if (selectorMatchesShadowRoot(nextContext.selector)) { |
+ if (!isAuthorShadowRoot(context.element->containingShadowRoot())) |
+ return SelectorFailsCompletely; |
+ nextContext.element = context.element; |
+ return this->match(nextContext, siblingTraversalStrategy, result); |
+ } |
+ |
for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) { |
Match match = this->match(nextContext, siblingTraversalStrategy, result); |
if (match == SelectorMatches || match == SelectorFailsCompletely) |
@@ -268,12 +289,18 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC |
if (context.selector->relationIsAffectedByPseudoContent()) |
return matchForShadowDistributed(context.element, siblingTraversalStrategy, nextContext, result); |
- nextContext.element = parentElement(context); |
- if (!nextContext.element) |
- return SelectorFailsCompletely; |
- |
nextContext.isSubSelector = false; |
nextContext.elementStyle = 0; |
+ nextContext.element = parentElement(context); |
+ if (!nextContext.element) { |
+ if (!selectorMatchesShadowRoot(nextContext.selector)) |
dglazkov
2014/03/25 17:10:53
This is effectively copy-paste code from CSSSelect
tasak
2014/03/26 11:01:46
I see. I created a new method for this.
|
+ return SelectorFailsCompletely; |
+ if (isAuthorShadowRoot(context.element->parentNode())) { |
+ nextContext.element = context.element; |
+ return match(nextContext, siblingTraversalStrategy, result); |
+ } |
+ return SelectorFailsCompletely; |
+ } |
return match(nextContext, siblingTraversalStrategy, result); |
} |
case CSSSelector::DirectAdjacent: |
@@ -304,7 +331,6 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC |
return SelectorFailsAllSiblings; |
case CSSSelector::ShadowPseudo: |
- case CSSSelector::Shadow: |
{ |
// 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) |