mirror of
https://github.com/roytam1/basilisk55.git
synced 2026-05-28 14:47:58 +00:00
import from UXP: Issue #1592 - Part 4: Walk ::slotted()-containing rules for slottables (518c41fd)
This commit is contained in:
@@ -682,6 +682,45 @@ nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||
aData->mElementIsFeatureless = false;
|
||||
aData->mTreeMatchContext.mOnlyMatchHostPseudo = false;
|
||||
|
||||
// Walk the rules in shadow root for ::slotted() pseudo-element rules
|
||||
// if we have an assigned slot.
|
||||
if (aData->mElement->GetAssignedSlot()) {
|
||||
aData->mTreeMatchContext.mRestrictToSlottedPseudo = true;
|
||||
|
||||
AutoTArray<nsXBLBinding*, 2> stack;
|
||||
bool foundTopmostScope = false;
|
||||
for (nsIContent* parent = aData->mElement->GetFlattenedTreeParent();
|
||||
parent;
|
||||
parent = parent->GetFlattenedTreeParent()) {
|
||||
ShadowRoot* currentShadow = parent->GetShadowRoot();
|
||||
if (!currentShadow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsXBLBinding* binding = currentShadow->GetAssociatedBinding();
|
||||
if (!binding) {
|
||||
continue;
|
||||
}
|
||||
stack.AppendElement(binding);
|
||||
|
||||
if (!foundTopmostScope) {
|
||||
aData->mTreeMatchContext.mScopedRoot = parent;
|
||||
foundTopmostScope = true;
|
||||
}
|
||||
}
|
||||
|
||||
while (!stack.IsEmpty()) {
|
||||
uint32_t index = stack.Length() - 1;
|
||||
nsXBLBinding* binding = stack.ElementAt(index);
|
||||
stack.RemoveElementAt(index);
|
||||
|
||||
aData->mTreeMatchContext.mIsTopmostScope = (index == 0);
|
||||
binding->WalkRules(aFunc, aData);
|
||||
}
|
||||
|
||||
aData->mTreeMatchContext.mRestrictToSlottedPseudo = false;
|
||||
}
|
||||
|
||||
// Walk the binding scope chain, starting with the binding attached to our
|
||||
// content, up till we run out of scopes or we get cut off.
|
||||
nsIContent *content = aData->mElement;
|
||||
|
||||
@@ -2656,6 +2656,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
|
||||
@@ -2734,6 +2740,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,
|
||||
@@ -2748,29 +2800,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
|
||||
@@ -3115,35 +3149,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
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user