summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorFranklinDM <mrmineshafter17@gmail.com>2023-03-18 12:43:51 +0800
committerMoonchild <moonchild@palemoon.org>2023-03-23 12:18:00 +0100
commit9c5999c8bc7fb3598b7b572a57da4afbb0048a18 (patch)
tree7bf00eb3426e7eaa4ea0e149bcce88b824431727 /layout
parent8313fea7c5bbb54339bbde9b20024bc17c7341e8 (diff)
downloaduxp-9c5999c8bc7fb3598b7b572a57da4afbb0048a18.tar.gz
Issue #1592 - Part 4: Walk ::slotted()-containing rules for slottables
- Check against all selector parts and not the leftmost selector only for ::slotted() - Walk rules for ::slotted() regardless if the shadow root is opened/closed - Ensure that ::slotted() rules are walked in the right order - Fix ::slotted inheritance from topmost shadow root
Diffstat (limited to 'layout')
-rw-r--r--layout/style/nsCSSRuleProcessor.cpp104
-rw-r--r--layout/style/nsRuleProcessorData.h8
2 files changed, 65 insertions, 47 deletions
diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp
index fb35b65bd6..a4a2e537c4 100644
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2665,6 +2665,12 @@ SelectorMatchesTree(Element* aPrevElement,
aTreeMatchContext.mCurrentStyleScope = styleScope;
}
selector = selector->mNext;
+ if (!selector &&
+ !aTreeMatchContext.mIsTopmostScope &&
+ aTreeMatchContext.mRestrictToSlottedPseudo &&
+ aTreeMatchContext.mScopedRoot != element) {
+ return false;
+ }
}
else {
// for adjacent sibling and child combinators, if we didn't find
@@ -2743,6 +2749,52 @@ static bool SelectorListMatches(Element* aElement,
aPreventComplexSelectors);
}
+static
+inline bool LookForTargetPseudo(nsCSSSelector* aSelector,
+ TreeMatchContext* aMatchContext,
+ nsRestyleHint* possibleChange) {
+ if (aMatchContext->mOnlyMatchHostPseudo) {
+ while (aSelector && aSelector->mNext != nullptr) {
+ aSelector = aSelector->mNext;
+ }
+
+ for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
+ pseudoClass;
+ pseudoClass = pseudoClass->mNext) {
+ if (pseudoClass->mType == CSSPseudoClassType::host ||
+ pseudoClass->mType == CSSPseudoClassType::hostContext) {
+ if (possibleChange) {
+ // :host-context will walk ancestors looking for a match of a
+ // compound selector, thus any changes to ancestors may require
+ // restyling the subtree.
+ *possibleChange |= eRestyle_Subtree;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ else if (aMatchContext->mRestrictToSlottedPseudo) {
+ for (nsCSSSelector* selector = aSelector;
+ selector;
+ selector = selector->mNext) {
+ if (!selector->mPseudoClassList) {
+ continue;
+ }
+ for (nsPseudoClassList* pseudoClass = selector->mPseudoClassList;
+ pseudoClass;
+ pseudoClass = pseudoClass->mNext) {
+ if (pseudoClass->mType == CSSPseudoClassType::slotted) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ // We're not restricted to a specific pseudo-class.
+ return true;
+}
+
static inline
void ContentEnumFunc(const RuleValue& value, nsCSSSelector* aSelector,
ElementDependentRuleProcessorData* data, NodeMatchContext& nodeContext,
@@ -2757,29 +2809,11 @@ void ContentEnumFunc(const RuleValue& value, nsCSSSelector* aSelector,
// We won't match; nothing else to do here
return;
}
- // If mOnlyMatchHostPseudo is set, then we only want to match against
- // selectors that contain a :host-context pseudo class.
- if (data->mTreeMatchContext.mOnlyMatchHostPseudo) {
- nsCSSSelector* selector = aSelector;
- while (selector && selector->mNext != nullptr) {
- selector = selector->mNext;
- }
- bool seenHostPseudo = false;
- for (nsPseudoClassList* pseudoClass = selector->mPseudoClassList;
- pseudoClass;
- pseudoClass = pseudoClass->mNext) {
- if (pseudoClass->mType == CSSPseudoClassType::host ||
- pseudoClass->mType == CSSPseudoClassType::hostContext) {
- seenHostPseudo = true;
- break;
- }
- }
-
- if (!seenHostPseudo) {
- return;
- }
+ if (!LookForTargetPseudo(aSelector, &data->mTreeMatchContext, nullptr)) {
+ return;
}
+
if (!data->mTreeMatchContext.SetStyleScopeForSelectorMatching(data->mElement,
data->mScope)) {
// The selector is for a rule in a scoped style sheet, and the subject
@@ -3122,35 +3156,11 @@ AttributeEnumFunc(nsCSSSelector* aSelector,
nsRestyleHint possibleChange =
RestyleHintForSelectorWithAttributeChange(aData->change,
aSelector, aRightmostSelector);
- // If mOnlyMatchHostPseudo is set, then we only want to match against
- // selectors that contain a :host-context pseudo class.
- if (data->mTreeMatchContext.mOnlyMatchHostPseudo) {
- nsCSSSelector* selector = aSelector;
- while (selector && selector->mNext != nullptr) {
- selector = selector->mNext;
- }
- bool seenHostPseudo = false;
- for (nsPseudoClassList* pseudoClass = selector->mPseudoClassList;
- pseudoClass;
- pseudoClass = pseudoClass->mNext) {
- if (pseudoClass->mType == CSSPseudoClassType::host ||
- pseudoClass->mType == CSSPseudoClassType::hostContext) {
- // :host-context will walk ancestors looking for a match of a compound
- // selector, thus any changes to ancestors may require restyling the
- // subtree.
- possibleChange |= eRestyle_Subtree;
- seenHostPseudo = true;
- break;
- }
- }
-
- if (!seenHostPseudo) {
- return;
- }
+ if (!LookForTargetPseudo(aSelector, &data->mTreeMatchContext, &possibleChange)) {
+ return;
}
-
// If, ignoring eRestyle_SomeDescendants, enumData->change already includes
// all the bits of possibleChange, don't bother calling SelectorMatches, since
// even if it returns false enumData->change won't change. If possibleChange
diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h
index 938c2f9d35..07c885994f 100644
--- a/layout/style/nsRuleProcessorData.h
+++ b/layout/style/nsRuleProcessorData.h
@@ -371,6 +371,9 @@ struct MOZ_STACK_CLASS TreeMatchContext {
// match.
bool mOnlyMatchHostPseudo;
+ // Restrict matching to selectors that contain a :slotted() pseudo-class.
+ bool mRestrictToSlottedPseudo;
+
// Root of scoped stylesheet (set and unset by the supplier of the
// scoped stylesheet).
nsIContent* mScopedRoot;
@@ -403,6 +406,9 @@ struct MOZ_STACK_CLASS TreeMatchContext {
// for an HTML5 scoped style sheet.
bool mForScopedStyle;
+ // Whether we're currently in the topmost scope for shadow DOM.
+ bool mIsTopmostScope;
+
enum MatchVisited {
eNeverMatchVisited,
eMatchVisitedDefault
@@ -429,6 +435,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
, mVisitedHandling(aVisitedHandling)
, mDocument(aDocument)
, mOnlyMatchHostPseudo(false)
+ , mRestrictToSlottedPseudo(false)
, mScopedRoot(nullptr)
, mIsHTMLDocument(aDocument->IsHTMLDocument())
, mCompatMode(aDocument->GetCompatibilityMode())
@@ -436,6 +443,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
, mSkippingParentDisplayBasedStyleFixup(false)
, mForScopedStyle(false)
, mCurrentStyleScope(nullptr)
+ , mIsTopmostScope(false)
{
if (aMatchVisited != eNeverMatchVisited) {
nsILoadContext* loadContext = mDocument->GetLoadContext();