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 3b72243fdd7c400765bf48753e575aeafbe5e52d..ca2579fef0591cb62873adb8651a23667e515331 100644 |
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp |
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp |
@@ -47,6 +47,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" |
@@ -113,6 +114,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. |
@@ -452,6 +467,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(); |
} |
@@ -1031,6 +1056,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 compound 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: |