diff options
author | FranklinDM <mrmineshafter17@gmail.com> | 2023-03-18 12:43:51 +0800 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2023-03-23 12:18:00 +0100 |
commit | 9c5999c8bc7fb3598b7b572a57da4afbb0048a18 (patch) | |
tree | 7bf00eb3426e7eaa4ea0e149bcce88b824431727 /layout | |
parent | 8313fea7c5bbb54339bbde9b20024bc17c7341e8 (diff) | |
download | uxp-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.cpp | 104 | ||||
-rw-r--r-- | layout/style/nsRuleProcessorData.h | 8 |
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(); |