Index: third_party/WebKit/Source/core/css/SelectorChecker.cpp |
diff --git a/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/third_party/WebKit/Source/core/css/SelectorChecker.cpp |
index 47401171eea1c4d1ec48449d785dff6edfd4287e..1792aa9425cc0b72717f4374dd31deaab60f5851 100644 |
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp |
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp |
@@ -48,6 +48,7 @@ |
#include "core/html/HTMLInputElement.h" |
#include "core/html/HTMLOptionElement.h" |
#include "core/html/HTMLSelectElement.h" |
+#include "core/html/HTMLSlotElement.h" |
#include "core/html/parser/HTMLParserIdioms.h" |
#include "core/html/track/vtt/VTTElement.h" |
#include "core/inspector/InspectorInstrumentation.h" |
@@ -114,6 +115,20 @@ static Element* parentElement(const SelectorChecker::SelectorCheckingContext& co |
return context.element->parentElement(); |
} |
+static const HTMLSlotElement* findSlotElementInScope(const SelectorChecker::SelectorCheckingContext& context) |
+{ |
+ if (!context.scope) |
+ return nullptr; |
+ |
+ const HTMLSlotElement* slot = context.element->assignedSlot(); |
+ while (slot) { |
+ if (slot->treeScope() == context.scope->treeScope()) |
+ return slot; |
+ slot = slot->assignedSlot(); |
+ } |
+ return nullptr; |
+} |
+ |
static bool scopeContainsLastMatchedElement(const SelectorChecker::SelectorCheckingContext& context) |
{ |
// If this context isn't scoped, skip checking. |
@@ -453,6 +468,16 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC |
return SelectorFailsCompletely; |
} |
+ case CSSSelector::ShadowSlot: |
+ { |
+ const HTMLSlotElement* slot = findSlotElementInScope(context); |
+ if (!slot) |
+ return SelectorFailsCompletely; |
+ |
+ nextContext.element = const_cast<HTMLSlotElement*>(slot); |
+ return matchSelector(nextContext, result); |
+ } |
+ |
case CSSSelector::SubSelector: |
ASSERT_NOT_REACHED(); |
} |
@@ -1024,6 +1049,19 @@ bool SelectorChecker::checkPseudoElement(const SelectorCheckingContext& context, |
return root->type() == ShadowRootType::UserAgent && element.shadowPseudoId() == selector.value(); |
return false; |
} |
+ case CSSSelector::PseudoSlotted: |
+ { |
+ SelectorCheckingContext subContext(context); |
+ subContext.isSubSelector = true; |
+ subContext.scope = nullptr; |
+ subContext.treatShadowHostAsNormalScope = false; |
+ |
+ // ::slotted() only allows one simple selector. |
+ ASSERT(selector.selectorList()->first()); |
+ ASSERT(!CSSSelectorList::next(*selector.selectorList()->first())); |
+ subContext.selector = selector.selectorList()->first(); |
+ return match(subContext); |
+ } |
case CSSSelector::PseudoContent: |
return element.isInShadowTree() && element.isInsertionPoint(); |
case CSSSelector::PseudoShadow: |