diff options
author | Matt A. Tobin <email@mattatobin.com> | 2021-12-05 20:16:02 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2021-12-05 20:16:02 -0500 |
commit | 31022b58f3c139e48636a8cf8cb2c36812c72114 (patch) | |
tree | 7bb6538d2514b65a438ff777b53f02dc4ea9caa7 /layout | |
parent | b93e885e46986f57e6bdff55327511122a0a4786 (diff) | |
download | aura-central-31022b58f3c139e48636a8cf8cb2c36812c72114.tar.gz |
Issue %3024 - First pass support for :host and :host-context
Diffstat (limited to 'layout')
-rw-r--r-- | layout/style/StyleRule.cpp | 23 | ||||
-rw-r--r-- | layout/style/StyleRule.h | 7 | ||||
-rw-r--r-- | layout/style/nsCSSParser.cpp | 5 | ||||
-rw-r--r-- | layout/style/nsCSSPseudoClassList.h | 6 | ||||
-rw-r--r-- | layout/style/nsCSSPseudoClasses.h | 7 | ||||
-rw-r--r-- | layout/style/nsCSSRuleProcessor.cpp | 230 | ||||
-rw-r--r-- | layout/style/nsRuleProcessorData.h | 35 | ||||
-rw-r--r-- | layout/style/nsStyleSet.cpp | 3 |
8 files changed, 291 insertions, 25 deletions
diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 6fad62f8b..c8f1a0a91 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -148,7 +148,8 @@ nsPseudoClassList::nsPseudoClassList(CSSPseudoClassType aType, : mType(aType), mNext(nullptr) { - NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType), + NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType) || + nsCSSPseudoClasses::HasOptionalSelectorListArg(aType), "unexpected pseudo-class"); NS_ASSERTION(aSelectorList, "selector list expected"); MOZ_COUNT_CTOR(nsPseudoClassList); @@ -313,6 +314,7 @@ nsCSSSelector::nsCSSSelector(void) mPseudoClassList(nullptr), mAttrList(nullptr), mNegations(nullptr), + mExplicitUniversal(false), mNext(nullptr), mNameSpace(kNameSpaceID_Unknown), mOperator(0), @@ -382,6 +384,17 @@ void nsCSSSelector::Reset(void) mOperator = char16_t(0); } +bool nsCSSSelector::HasFeatureSelectors() +{ + return mExplicitUniversal || mLowercaseTag || mCasedTag || + mIDList || mClassList || mAttrList; +} + +void nsCSSSelector::SetHasExplicitUniversal() +{ + mExplicitUniversal = true; +} + void nsCSSSelector::SetNameSpace(int32_t aNameSpace) { mNameSpace = aNameSpace; @@ -742,9 +755,9 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations // Universal selector: avoid writing the universal selector when we // can avoid it, especially since we're required to avoid it for the // inside of :not() - if (wroteNamespace || + if (wroteNamespace || mExplicitUniversal || (!mIDList && !mClassList && !mPseudoClassList && !mAttrList && - (aIsNegated || !mNegations))) { + aIsNegated)) { aString.Append(char16_t('*')); } } else { @@ -752,9 +765,7 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations nsAutoString tag; (isPseudoElement ? mLowercaseTag : mCasedTag)->ToString(tag); if (isPseudoElement) { - if (!mNext) { - // Lone pseudo-element selector -- toss in a wildcard type selector - // XXXldb Why? + if (mExplicitUniversal) { aString.Append(char16_t('*')); } // While our atoms use one colon, most pseudo-elements require two diff --git a/layout/style/StyleRule.h b/layout/style/StyleRule.h index 907e55448..dbf4e0840 100644 --- a/layout/style/StyleRule.h +++ b/layout/style/StyleRule.h @@ -151,6 +151,8 @@ public: nsCSSSelector* Clone() const { return Clone(true, true); } void Reset(void); + bool HasFeatureSelectors(); + void SetHasExplicitUniversal(); void SetNameSpace(int32_t aNameSpace); void SetTag(const nsString& aTag); void AddID(const nsString& aID); @@ -231,9 +233,10 @@ public: // the argument to functional pseudos nsAttrSelector* mAttrList; nsCSSSelector* mNegations; - nsCSSSelector* mNext; + bool mExplicitUniversal; // True if universal selector explicitly + nsCSSSelector* mNext; // appears in the selector int32_t mNameSpace; - char16_t mOperator; + char mOperator; private: // The underlying type of CSSPseudoElementType is uint8_t and // it packs well with mOperator. (char16_t + uint8_t is less than 32bits.) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 3d5edbd0e..2e2700c38 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -5639,6 +5639,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(int32_t& aDataMask, aSelector.SetTag(mToken.mIdent); } else if (mToken.IsSymbol('*')) { // universal selector + aSelector.SetHasExplicitUniversal(); aDataMask |= SEL_MASK_ELEM; // don't set tag } @@ -5650,6 +5651,7 @@ CSSParserImpl::ParseTypeOrUniversalSelector(int32_t& aDataMask, } else { // was universal element selector SetDefaultNamespaceOnSelector(aSelector); + aSelector.SetHasExplicitUniversal(); aDataMask |= SEL_MASK_ELEM; // don't set any tag in the selector } @@ -6089,7 +6091,8 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, CSSPseudoClassType::negation == pseudoClassType || nsCSSPseudoClasses::HasStringArg(pseudoClassType) || nsCSSPseudoClasses::HasNthPairArg(pseudoClassType) || - nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType))) { + nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType)) && + !nsCSSPseudoClasses::HasOptionalSelectorListArg(pseudoClassType)) { // There are no other function pseudos REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc); UngetToken(); diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index 7f620ec32..c57c28bc0 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -133,6 +133,12 @@ CSS_PSEUDO_CLASS(scope, ":scope", 0, "layout.css.scope-pseudo.enabled") // it doesn't actually get directly matched on in SelectorMatches. CSS_PSEUDO_CLASS(negation, ":not", 0, "") +// http://drafts.csswg.org/css-scoping/#selectordef-host-context +CSS_PSEUDO_CLASS(hostContext, ":host-context", 0, "dom.webcomponents.enabled") + +// http://drafts.csswg.org/css-scoping/#selectordef-host-context +CSS_PSEUDO_CLASS(host, ":host", 0, "dom.webcomponents.enabled") + // :dir(ltr) and :dir(rtl) match elements whose resolved // directionality in the markup language is ltr or rtl respectively. CSS_STATE_DEPENDENT_PSEUDO_CLASS(dir, ":dir", 0, "", diff --git a/layout/style/nsCSSPseudoClasses.h b/layout/style/nsCSSPseudoClasses.h index 55e5bf9d2..05f67b05c 100644 --- a/layout/style/nsCSSPseudoClasses.h +++ b/layout/style/nsCSSPseudoClasses.h @@ -59,7 +59,12 @@ public: static bool HasStringArg(Type aType); static bool HasNthPairArg(Type aType); static bool HasSelectorListArg(Type aType) { - return aType == Type::any; + return aType == Type::any || + aType == Type::host || + aType == Type::hostContext; + } + static bool HasOptionalSelectorListArg(Type aType) { + return aType == Type::host; } static bool IsUserActionPseudoClass(Type aType); diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index aed26a1c0..f49b9d325 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/ShadowRoot.h" #include "nsNthIndexCache.h" #include "mozilla/ArrayUtils.h" #include "mozilla/EventStates.h" @@ -1321,9 +1322,17 @@ struct NodeMatchContext { // mForStyling is false, we have to assume we don't know.) const bool mIsRelevantLink; - NodeMatchContext(EventStates aStateMask, bool aIsRelevantLink) + // If the node should be considered featureless (as specified in + // selectors 4), then mIsFeature should be set to true to prevent + // matching unless the selector is a special pseudo class or pseudo + // element that matches featureless elements. + const bool mIsFeatureless; + + NodeMatchContext(EventStates aStateMask, bool aIsRelevantLink, + bool aIsFeatureless = false) : mStateMask(aStateMask) , mIsRelevantLink(aIsRelevantLink) + , mIsFeatureless(aIsFeatureless) { } }; @@ -1610,6 +1619,11 @@ StateSelectorMatches(Element* aElement, return true; } +static bool AnySelectorInArgListMatches(Element* aElement, + nsPseudoClassList* aList, + NodeMatchContext& aNodeMatchContext, + TreeMatchContext& aTreeMatchContext); + static bool StateSelectorMatches(Element* aElement, nsCSSSelector* aSelector, @@ -1631,6 +1645,26 @@ StateSelectorMatches(Element* aElement, return true; } +// Returns whether aSelector can match featureless elements. +static bool CanMatchFeaturelessElement(nsCSSSelector* aSelector) +{ + if (aSelector->HasFeatureSelectors()) { + return false; + } + + for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList; + pseudoClass; + pseudoClass = pseudoClass->mNext) { + if (pseudoClass->mType == CSSPseudoClassType::host || + pseudoClass->mType == CSSPseudoClassType::hostContext) { + return true; + } + } + + return false; +} + + // |aDependence| has two functions: // * when non-null, it indicates that we're processing a negation, // which is done only when SelectorMatches calls itself recursively @@ -1651,6 +1685,11 @@ static bool SelectorMatches(Element* aElement, "is false since we don't know how to set it correctly in " "Has(Attribute|State)DependentStyle"); + if (aNodeMatchContext.mIsFeatureless && + !CanMatchFeaturelessElement(aSelector)) { + return false; + } + // namespace/tag match // optimization : bail out early if we can if ((kNameSpaceID_Unknown != aSelector->mNameSpace && @@ -1849,18 +1888,89 @@ static bool SelectorMatches(Element* aElement, case CSSPseudoClassType::any: { - nsCSSSelectorList *l; - for (l = pseudoClass->u.mSelectors; l; l = l->mNext) { - nsCSSSelector *s = l->mSelectors; - MOZ_ASSERT(!s->mNext && !s->IsPseudoElement(), - "parser failed"); - if (SelectorMatches( - aElement, s, aNodeMatchContext, aTreeMatchContext, - SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT)) { + if (!AnySelectorInArgListMatches(aElement, pseudoClass, + aNodeMatchContext, + aTreeMatchContext)) { + return false; + } + } + break; + + case CSSPseudoClassType::host: + { + // In order to match :host, the element must be a shadow root host, + // we must be matching only against host pseudo selectors, and the + // selector's context must be the shadow root (the selector must be + // featureless, the left-most selector, and be in a shadow root + // style). The :host selector may also be be functional, with a + // compound selector. If this is the case, then also ensure that the + // host element matches against the compound + // selector. + + // We match automatically if GetParent() and GetShadowRoot() have + // the same result. Without special casing this ahead of all other + // selector matching, it fails. Have not determined the cause. + + if (aElement->GetParent() == aElement->GetShadowRoot()) { + break; + } + + // Match if any selector in the argument list matches. + + NodeMatchContext nodeContext(EventStates(), + nsCSSRuleProcessor::IsLink(aElement)); + if (AnySelectorInArgListMatches(aElement, pseudoClass, + nodeContext, + aTreeMatchContext)) { + break; + } + + // Finally, with the exception of the two above cases, make sure we + // don't match if GetContainingShadow() returns null. For whatever + // reason, we can't test for this case first. + + if (aElement->GetContainingShadow() == nullptr) { + return false; + } + + } + break; + + + case CSSPseudoClassType::hostContext: + { + // In order to match host-context, the element must be a + // shadow root host and the selector's context must be the + // shadow root (aTreeMatchContext.mScopedRoot is set to the + // host of the shadow root where the style is contained, + // thus the element must be mScopedRoot). If the UNKNOWN + // selector flag is set, relax the shadow root host + // requirement because this pseudo class walks through + // ancestors looking for a match, thus the selector can be + // dependant on aElement even though it is not the host. The + // dependency would otherwise be missed because when UNKNOWN + // is set, selector matching may not have started from the top. + if (!((aElement->GetShadowRoot() && + aElement == aTreeMatchContext.mScopedRoot) || + aSelectorFlags & SelectorMatchesFlags::UNKNOWN)) { + return false; + } + + Element* currentElement = aElement; + while (currentElement) { + NodeMatchContext nodeContext(EventStates(), + nsCSSRuleProcessor::IsLink(currentElement)); + if (AnySelectorInArgListMatches(currentElement, pseudoClass, + nodeContext, + aTreeMatchContext)) { break; } + + nsIContent* flattenedParent = currentElement->GetFlattenedTreeParent(); + currentElement = flattenedParent && flattenedParent->IsElement() ? + flattenedParent->AsElement() : nullptr; } - if (!l) { + if (!currentElement) { return false; } } @@ -2242,6 +2352,26 @@ static bool SelectorMatches(Element* aElement, return result; } +static bool AnySelectorInArgListMatches(Element* aElement, + nsPseudoClassList* aList, + NodeMatchContext& aNodeMatchContext, + TreeMatchContext& aTreeMatchContext) +{ + nsCSSSelectorList *l; + for (l = aList->u.mSelectors; l; l = l->mNext) { + nsCSSSelector *s = l->mSelectors; + MOZ_ASSERT(!s->mNext && !s->IsPseudoElement(), + "parser failed"); + if (SelectorMatches( + aElement, s, aNodeMatchContext, aTreeMatchContext, + SelectorMatchesFlags::IS_PSEUDO_CLASS_ARGUMENT)) { + break; + } + } + + return !!l; +} + #undef STATE_CHECK #ifdef DEBUG @@ -2331,7 +2461,9 @@ SelectorMatchesTree(Element* aPrevElement, MOZ_ASSERT(!aSelector || !aSelector->IsPseudoElement()); nsCSSSelector* selector = aSelector; Element* prevElement = aPrevElement; + bool crossedShadowRootBoundary = false; while (selector) { // check compound selectors + bool contentIsFeatureless = false; NS_ASSERTION(!selector->mNext || selector->mNext->mOperator != char16_t(0), "compound selector without combinator"); @@ -2362,6 +2494,20 @@ SelectorMatchesTree(Element* aPrevElement, // to test against is the parent else { nsIContent *content = prevElement->GetParent(); + + // In the shadow tree, the shadow host behaves as if it + // is a featureless parent of top-level elements of the shadow + // tree. Only cross shadow root boundary when the selector is the + // left most selector because ancestors of the host are not in + // the selector match list. + ShadowRoot* shadowRoot = content ? + ShadowRoot::FromNode(content) : nullptr; + if (shadowRoot && !selector->mNext && !crossedShadowRootBoundary) { + content = shadowRoot->GetHost(); + crossedShadowRootBoundary = true; + contentIsFeatureless = true; + } + // GetParent could return a document fragment; we only want // element parents. if (content && content->IsElement()) { @@ -2413,7 +2559,8 @@ SelectorMatchesTree(Element* aPrevElement, } const bool isRelevantLink = (aFlags & eLookForRelevantLink) && nsCSSRuleProcessor::IsLink(element); - NodeMatchContext nodeContext(EventStates(), isRelevantLink); + + NodeMatchContext nodeContext(EventStates(), isRelevantLink, contentIsFeatureless); if (isRelevantLink) { // If we find an ancestor of the matched node that is a link // during the matching process, then it's the relevant link (see @@ -2483,6 +2630,29 @@ 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 (!data->mTreeMatchContext.SetStyleScopeForSelectorMatching(data->mElement, data->mScope)) { // The selector is for a rule in a scoped style sheet, and the subject @@ -2542,7 +2712,8 @@ nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData) if (cascade) { NodeMatchContext nodeContext(EventStates(), - nsCSSRuleProcessor::IsLink(aData->mElement)); + nsCSSRuleProcessor::IsLink(aData->mElement), + aData->mElementIsFeatureless); cascade->mRuleHash.EnumerateAllRules(aData->mElement, aData, nodeContext); } } @@ -2824,6 +2995,34 @@ 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, ignoring eRestyle_SomeDescendants, enumData->change already includes // all the bits of possibleChange, don't bother calling SelectorMatches, since @@ -3295,10 +3494,12 @@ AddSelector(RuleCascadeData* aCascade, } } - // Recur through any :-moz-any selectors + // Recur through any :-moz-any or :host-context selectors for (nsPseudoClassList* pseudoClass = negation->mPseudoClassList; pseudoClass; pseudoClass = pseudoClass->mNext) { - if (pseudoClass->mType == CSSPseudoClassType::any) { + if (pseudoClass->mType == CSSPseudoClassType::any || + pseudoClass->mType == CSSPseudoClassType::host || + pseudoClass->mType == CSSPseudoClassType::hostContext) { for (nsCSSSelectorList *l = pseudoClass->u.mSelectors; l; l = l->mNext) { nsCSSSelector *s = l->mSelectors; if (!AddSelector(aCascade, aSelectorInTopLevel, s, @@ -3943,6 +4144,7 @@ TreeMatchContext::InitAncestors(Element *aElement) for (uint32_t i = ancestors.Length(); i-- != 0; ) { mAncestorFilter.PushAncestor(ancestors[i]); PushStyleScope(ancestors[i]); + PushShadowHost(ancestors[i]); } } } diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index fbaa768cc..f6d977100 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -164,6 +164,23 @@ struct MOZ_STACK_CLASS TreeMatchContext { mStyleScopes.TruncateLength(mStyleScopes.Length() - 1); } } + + void PushShadowHost(mozilla::dom::Element* aElement) + { + NS_PRECONDITION(aElement, "aElement must not be null"); + if (aElement->GetShadowRoot()) { + mShadowHosts.AppendElement(aElement); + } + } + + void PopShadowHost(mozilla::dom::Element* aElement) + { + NS_PRECONDITION(aElement, "aElement must not be null"); + if (mShadowHosts.SafeLastElement(nullptr) == aElement) { + mShadowHosts.TruncateLength(mShadowHosts.Length() - 1); + } + } + bool PopStyleScopeForSelectorMatching(mozilla::dom::Element* aElement) { @@ -233,6 +250,7 @@ struct MOZ_STACK_CLASS TreeMatchContext { MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : mPushedAncestor(false) , mPushedStyleScope(false) + , mPushedShadowHost(false) , mTreeMatchContext(aTreeMatchContext) , mElement(nullptr) { @@ -245,8 +263,10 @@ struct MOZ_STACK_CLASS TreeMatchContext { mElement = aElement; mPushedAncestor = true; mPushedStyleScope = true; + mPushedShadowHost = true; mTreeMatchContext.mAncestorFilter.PushAncestor(aElement); mTreeMatchContext.PushStyleScope(aElement); + mTreeMatchContext.PushShadowHost(aElement); } } @@ -278,11 +298,15 @@ struct MOZ_STACK_CLASS TreeMatchContext { if (mPushedStyleScope) { mTreeMatchContext.PopStyleScope(mElement); } + if (mPushedShadowHost) { + mTreeMatchContext.PopShadowHost(mElement); + } } private: bool mPushedAncestor; bool mPushedStyleScope; + bool mPushedShadowHost; TreeMatchContext& mTreeMatchContext; mozilla::dom::Element* mElement; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER @@ -342,6 +366,11 @@ struct MOZ_STACK_CLASS TreeMatchContext { // The document we're working with. nsIDocument* const mDocument; + // Only selectors that contain :host or :host-context pseudo class + // should be matched against elements. All other selectors should not + // match. + bool mOnlyMatchHostPseudo; + // Root of scoped stylesheet (set and unset by the supplier of the // scoped stylesheet). nsIContent* mScopedRoot; @@ -383,6 +412,9 @@ struct MOZ_STACK_CLASS TreeMatchContext { // <style scoped> child). AutoTArray<mozilla::dom::Element*, 1> mStyleScopes; + // List of ancestor elements that are a shadow root host. + AutoTArray<mozilla::dom::Element*, 1> mShadowHosts; + // The current style scope element for selector matching. mozilla::dom::Element* mCurrentStyleScope; @@ -396,6 +428,7 @@ struct MOZ_STACK_CLASS TreeMatchContext { , mHaveSpecifiedScope(false) , mVisitedHandling(aVisitedHandling) , mDocument(aDocument) + , mOnlyMatchHostPseudo(false) , mScopedRoot(nullptr) , mIsHTMLDocument(aDocument->IsHTMLDocument()) , mCompatMode(aDocument->GetCompatibilityMode()) @@ -437,6 +470,7 @@ struct MOZ_STACK_CLASS ElementDependentRuleProcessorData : : RuleProcessorData(aPresContext, aRuleWalker) , mElement(aElement) , mTreeMatchContext(aTreeMatchContext) + , mElementIsFeatureless(false) { NS_ASSERTION(aElement, "null element leaked into SelectorMatches"); NS_ASSERTION(aElement->OwnerDoc(), "Document-less node here?"); @@ -446,6 +480,7 @@ struct MOZ_STACK_CLASS ElementDependentRuleProcessorData : mozilla::dom::Element* const mElement; // weak ref, must not be null TreeMatchContext& mTreeMatchContext; + bool mElementIsFeatureless; }; struct MOZ_STACK_CLASS ElementRuleProcessorData : diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 5890100eb..edf61d2f9 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -1311,8 +1311,9 @@ nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc, if (mBindingManager) { // We can supply additional document-level sheets that should be walked. if (aWalkAllXBLStylesheets) { - mBindingManager->WalkAllRules(aFunc, aData); + mBindingManager->WalkAllRules(aFunc, aData, false); } else { + mBindingManager->WalkAllShadowRootHostRules(aFunc, aData); mBindingManager->WalkRules(aFunc, aData, &cutOffInheritance); } } |