summaryrefslogtreecommitdiff
path: root/layout/style
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style')
-rw-r--r--layout/style/nsCSSRuleProcessor.cpp51
-rw-r--r--layout/style/nsRuleProcessorData.h5
2 files changed, 41 insertions, 15 deletions
diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp
index a13b35214d..ff8b8ec032 100644
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -48,6 +48,7 @@
#include "nsCSSRules.h"
#include "nsStyleSet.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsNthIndexCache.h"
#include "mozilla/ArrayUtils.h"
@@ -684,6 +685,7 @@ void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcesso
filter->AssertHasAllAncestors(aElement);
}
#endif
+ bool isForAssignedSlot = aData->mTreeMatchContext.mForAssignedSlot;
// Merge the lists while there are still multiple lists to merge.
while (valueCount > 1) {
int32_t valueIndex = 0;
@@ -696,6 +698,7 @@ void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcesso
}
}
const RuleValue *cur = mEnumList[valueIndex].mCurValue;
+ aData->mTreeMatchContext.mForAssignedSlot = isForAssignedSlot;
ContentEnumFunc(*cur, cur->mSelector, aData, aNodeContext, filter);
cur++;
if (cur == mEnumList[valueIndex].mEnd) {
@@ -709,6 +712,7 @@ void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcesso
for (const RuleValue *value = mEnumList[0].mCurValue,
*end = mEnumList[0].mEnd;
value != end; ++value) {
+ aData->mTreeMatchContext.mForAssignedSlot = isForAssignedSlot;
ContentEnumFunc(*value, value->mSelector, aData, aNodeContext, filter);
}
}
@@ -1706,24 +1710,29 @@ static bool SelectorMatches(Element* aElement,
return false;
}
+ Element* targetElement = aElement;
+ if (aTreeMatchContext.mForAssignedSlot) {
+ targetElement = aElement->GetAssignedSlot()->AsElement();
+ }
+
// namespace/tag match
// optimization : bail out early if we can
if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
- aElement->GetNameSpaceID() != aSelector->mNameSpace))
+ targetElement->GetNameSpaceID() != aSelector->mNameSpace))
return false;
if (aSelector->mLowercaseTag) {
nsIAtom* selectorTag =
- (aTreeMatchContext.mIsHTMLDocument && aElement->IsHTMLElement()) ?
+ (aTreeMatchContext.mIsHTMLDocument && targetElement->IsHTMLElement()) ?
aSelector->mLowercaseTag : aSelector->mCasedTag;
- if (selectorTag != aElement->NodeInfo()->NameAtom()) {
+ if (selectorTag != targetElement->NodeInfo()->NameAtom()) {
return false;
}
}
nsAtomList* IDList = aSelector->mIDList;
if (IDList) {
- nsIAtom* id = aElement->GetID();
+ nsIAtom* id = targetElement->GetID();
if (id) {
// case sensitivity: bug 93371
const bool isCaseSensitive =
@@ -1758,7 +1767,7 @@ static bool SelectorMatches(Element* aElement,
nsAtomList* classList = aSelector->mClassList;
if (classList) {
// test for class match
- const nsAttrValue *elementClasses = aElement->GetClasses();
+ const nsAttrValue *elementClasses = targetElement->GetClasses();
if (!elementClasses) {
// Element has no classes but we have a class selector
return false;
@@ -1948,6 +1957,10 @@ static bool SelectorMatches(Element* aElement,
case CSSPseudoClassType::slotted:
{
+ if (aTreeMatchContext.mForAssignedSlot) {
+ aTreeMatchContext.mForAssignedSlot = false;
+ }
+
// Slottables cannot be matched from the outer tree.
if (isOutsideShadowTree) {
return false;
@@ -2349,7 +2362,7 @@ static bool SelectorMatches(Element* aElement,
bool result = true;
if (aSelector->mAttrList) {
// test for attribute match
- if (!aElement->HasAttrs()) {
+ if (!targetElement->HasAttrs()) {
// if no attributes on the content, no match
return false;
} else {
@@ -2359,7 +2372,7 @@ static bool SelectorMatches(Element* aElement,
do {
bool isHTML =
- (aTreeMatchContext.mIsHTMLDocument && aElement->IsHTMLElement());
+ (aTreeMatchContext.mIsHTMLDocument && targetElement->IsHTMLElement());
matchAttribute = isHTML ? attr->mLowercaseAttr : attr->mCasedAttr;
if (attr->mNameSpace == kNameSpaceID_Unknown) {
// Attr selector with a wildcard namespace. We have to examine all
@@ -2371,7 +2384,7 @@ static bool SelectorMatches(Element* aElement,
// actually has attributes in), short-circuiting if we ever match.
result = false;
const nsAttrName* attrName;
- for (uint32_t i = 0; (attrName = aElement->GetAttrNameAt(i)); ++i) {
+ for (uint32_t i = 0; (attrName = targetElement->GetAttrNameAt(i)); ++i) {
if (attrName->LocalName() != matchAttribute) {
continue;
}
@@ -2382,7 +2395,7 @@ static bool SelectorMatches(Element* aElement,
#ifdef DEBUG
bool hasAttr =
#endif
- aElement->GetAttr(attrName->NamespaceID(),
+ targetElement->GetAttr(attrName->NamespaceID(),
attrName->LocalName(), value);
NS_ASSERTION(hasAttr, "GetAttrNameAt lied");
result = AttrMatchesValue(attr, value, isHTML);
@@ -2400,12 +2413,12 @@ static bool SelectorMatches(Element* aElement,
}
else if (attr->mFunction == NS_ATTR_FUNC_EQUALS) {
result =
- aElement->
+ targetElement->
AttrValueIs(attr->mNameSpace, matchAttribute, attr->mValue,
attr->IsValueCaseSensitive(isHTML) ? eCaseMatters
: eIgnoreCase);
}
- else if (!aElement->HasAttr(attr->mNameSpace, matchAttribute)) {
+ else if (!targetElement->HasAttr(attr->mNameSpace, matchAttribute)) {
result = false;
}
else if (attr->mFunction != NS_ATTR_FUNC_SET) {
@@ -2413,7 +2426,7 @@ static bool SelectorMatches(Element* aElement,
#ifdef DEBUG
bool hasAttr =
#endif
- aElement->GetAttr(attr->mNameSpace, matchAttribute, value);
+ targetElement->GetAttr(attr->mNameSpace, matchAttribute, value);
NS_ASSERTION(hasAttr, "HasAttr lied");
result = AttrMatchesValue(attr, value, isHTML);
}
@@ -2428,7 +2441,7 @@ static bool SelectorMatches(Element* aElement,
for (nsCSSSelector *negation = aSelector->mNegations;
result && negation; negation = negation->mNegations) {
bool dependence = false;
- result = !SelectorMatches(aElement, negation, aNodeMatchContext,
+ result = !SelectorMatches(targetElement, negation, aNodeMatchContext,
aTreeMatchContext,
SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT,
&dependence);
@@ -2822,7 +2835,9 @@ void ContentEnumFunc(const RuleValue& value, nsCSSSelector* aSelector,
if (nodeContext.mIsRelevantLink) {
data->mTreeMatchContext.SetHaveRelevantLink();
}
- if (ancestorFilter &&
+ // XXX: Ignore the ancestor filter if we're testing the assigned slot.
+ bool useAncestorFilter = !(data->mTreeMatchContext.mForAssignedSlot);
+ if (useAncestorFilter && ancestorFilter &&
!ancestorFilter->MightHaveMatchingAncestor<RuleValue::eMaxAncestorHashes>(
value.mAncestorSelectorHashes)) {
// We won't match; nothing else to do here
@@ -2894,7 +2909,13 @@ nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
NodeMatchContext nodeContext(EventStates(),
nsCSSRuleProcessor::IsLink(aData->mElement),
aData->mElementIsFeatureless);
- cascade->mRuleHash.EnumerateAllRules(aData->mElement, aData, nodeContext);
+ // Test against the assigned slot rather than the slottable if we're
+ // matching the ::slotted() pseudo.
+ Element* targetElement = aData->mElement;
+ if (aData->mTreeMatchContext.mForAssignedSlot) {
+ targetElement = aData->mElement->GetAssignedSlot()->AsElement();
+ }
+ cascade->mRuleHash.EnumerateAllRules(targetElement, aData, nodeContext);
}
}
diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h
index 07c885994f..94ec400cfc 100644
--- a/layout/style/nsRuleProcessorData.h
+++ b/layout/style/nsRuleProcessorData.h
@@ -409,6 +409,10 @@ struct MOZ_STACK_CLASS TreeMatchContext {
// Whether we're currently in the topmost scope for shadow DOM.
bool mIsTopmostScope;
+ // Whether we're testing for the assigned slot instead of the slottable
+ // when matching type/class/ID/attribute.
+ bool mForAssignedSlot;
+
enum MatchVisited {
eNeverMatchVisited,
eMatchVisitedDefault
@@ -444,6 +448,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
, mForScopedStyle(false)
, mCurrentStyleScope(nullptr)
, mIsTopmostScope(false)
+ , mForAssignedSlot(false)
{
if (aMatchVisited != eNeverMatchVisited) {
nsILoadContext* loadContext = mDocument->GetLoadContext();