mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Issue #2828 - Part 7: Walk child rule processors separately and ensure inverted cascade layer order is enforced for important rules
Excluding @layers declared in scoped styles because those aren't specced and are in an entirely separate cascade origin.
This commit is contained in:
parent
d3b305b819
commit
ec57be653a
1 changed files with 143 additions and 27 deletions
|
|
@ -1086,6 +1086,43 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
|
|||
}
|
||||
#endif
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
FileRulesFromAllChildProcessors(
|
||||
nsCOMPtr<nsIStyleRuleProcessor> aParentProcessor,
|
||||
nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData,
|
||||
nsRuleWalker* aRuleWalker,
|
||||
mozilla::SheetType aLevel,
|
||||
nsRuleNode*& aLastRN,
|
||||
nsTArray<nsRuleNode*>& aLastRNs,
|
||||
nsTArray<bool>& aHaveImportantOriginRules,
|
||||
bool& aHaveAnyImportantOriginRules)
|
||||
{
|
||||
if (!aParentProcessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* processors =
|
||||
aParentProcessor->GetChildRuleProcessors();
|
||||
if (!processors) {
|
||||
(*aCollectorFunc)(aParentProcessor, aData);
|
||||
return;
|
||||
}
|
||||
|
||||
for (nsCOMPtr<nsIStyleRuleProcessor> processor : *processors) {
|
||||
aRuleWalker->SetLevel(aLevel, false, true);
|
||||
(*aCollectorFunc)(processor, aData);
|
||||
|
||||
aLastRN = aRuleWalker->CurrentNode();
|
||||
aLastRNs.AppendElement(aLastRN);
|
||||
|
||||
bool haveImportantRules = !aRuleWalker->GetCheckForImportantRules();
|
||||
aHaveImportantOriginRules.AppendElement(haveImportantRules);
|
||||
aHaveAnyImportantOriginRules =
|
||||
aHaveAnyImportantOriginRules || haveImportantRules;
|
||||
}
|
||||
}
|
||||
|
||||
// Enumerate the rules in a way that cares about the order of the rules.
|
||||
void
|
||||
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
|
|
@ -1097,6 +1134,9 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
|
||||
NS_ASSERTION(mBatching == 0, "rule processors out of date");
|
||||
|
||||
bool skipUserStyles =
|
||||
aElement && aElement->IsInNativeAnonymousSubtree();
|
||||
|
||||
// Cascading order:
|
||||
// [least important]
|
||||
// - UA normal rules = Agent normal
|
||||
|
|
@ -1117,19 +1157,41 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
// this will be either the root or one of the restriction rules.
|
||||
nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
|
||||
|
||||
aRuleWalker->SetLevel(SheetType::Agent, false, true);
|
||||
if (mRuleProcessors[SheetType::Agent])
|
||||
(*aCollectorFunc)(mRuleProcessors[SheetType::Agent], aData);
|
||||
nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode();
|
||||
bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules();
|
||||
nsRuleNode* lastAgentRN = nullptr;
|
||||
nsTArray<nsRuleNode*> lastAgentRNs;
|
||||
nsTArray<bool> haveImportantAgentRules;
|
||||
bool haveAnyImportantAgentRules = false;
|
||||
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::Agent],
|
||||
aCollectorFunc,
|
||||
aData,
|
||||
aRuleWalker,
|
||||
SheetType::Agent,
|
||||
lastAgentRN,
|
||||
lastAgentRNs,
|
||||
haveImportantAgentRules,
|
||||
haveAnyImportantAgentRules);
|
||||
if (!lastAgentRN) {
|
||||
lastAgentRN = aRuleWalker->CurrentNode();
|
||||
}
|
||||
|
||||
aRuleWalker->SetLevel(SheetType::User, false, true);
|
||||
bool skipUserStyles =
|
||||
aElement && aElement->IsInNativeAnonymousSubtree();
|
||||
if (!skipUserStyles && mRuleProcessors[SheetType::User]) // NOTE: different
|
||||
(*aCollectorFunc)(mRuleProcessors[SheetType::User], aData);
|
||||
nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
|
||||
bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
|
||||
nsRuleNode* lastUserRN = nullptr;
|
||||
nsTArray<nsRuleNode*> lastUserRNs;
|
||||
nsTArray<bool> haveImportantUserRules;
|
||||
bool haveAnyImportantUserRules = false;
|
||||
if (!skipUserStyles) { // NOTE: different
|
||||
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::User],
|
||||
aCollectorFunc,
|
||||
aData,
|
||||
aRuleWalker,
|
||||
SheetType::User,
|
||||
lastUserRN,
|
||||
lastUserRNs,
|
||||
haveImportantUserRules,
|
||||
haveAnyImportantUserRules);
|
||||
}
|
||||
if (!lastUserRN) {
|
||||
lastUserRN = aRuleWalker->CurrentNode();
|
||||
}
|
||||
|
||||
aRuleWalker->SetLevel(SheetType::PresHint, false, false);
|
||||
if (mRuleProcessors[SheetType::PresHint])
|
||||
|
|
@ -1148,16 +1210,35 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
static_cast<ElementDependentRuleProcessorData*>(aData),
|
||||
&cutOffInheritance);
|
||||
}
|
||||
if (!skipUserStyles && !cutOffInheritance && // NOTE: different
|
||||
mRuleProcessors[SheetType::Doc])
|
||||
(*aCollectorFunc)(mRuleProcessors[SheetType::Doc], aData);
|
||||
nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
|
||||
bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
|
||||
bool haveImportantNACRules = !aRuleWalker->GetCheckForImportantRules();
|
||||
|
||||
nsRuleNode* lastDocRN = nullptr;
|
||||
nsTArray<nsRuleNode*> lastDocRNs;
|
||||
nsTArray<bool> haveImportantDocRules;
|
||||
bool haveAnyImportantDocRules = haveImportantNACRules;
|
||||
if (!skipUserStyles && !cutOffInheritance) { // NOTE: different
|
||||
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::Doc],
|
||||
aCollectorFunc,
|
||||
aData,
|
||||
aRuleWalker,
|
||||
SheetType::Doc,
|
||||
lastDocRN,
|
||||
lastDocRNs,
|
||||
haveImportantDocRules,
|
||||
haveAnyImportantDocRules);
|
||||
}
|
||||
if (!lastDocRN) {
|
||||
lastDocRN = aRuleWalker->CurrentNode();
|
||||
}
|
||||
|
||||
nsTArray<nsRuleNode*> lastScopedRNs;
|
||||
nsTArray<bool> haveImportantScopedRules;
|
||||
bool haveAnyImportantScopedRules = false;
|
||||
if (!skipUserStyles && !cutOffInheritance &&
|
||||
aElement && aElement->IsElementInStyleScope()) {
|
||||
// XXX: Scoped style sheets will add important rules from cascade
|
||||
// layers in reverse order. Behavior for layers inside this isn't
|
||||
// specced and isn't worth the additional complexity.
|
||||
lastScopedRNs.SetLength(mScopedDocSheetRuleProcessors.Length());
|
||||
haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length());
|
||||
for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
|
||||
|
|
@ -1173,6 +1254,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
aData->mScope = nullptr;
|
||||
}
|
||||
nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode();
|
||||
|
||||
aRuleWalker->SetLevel(SheetType::StyleAttr, false, true);
|
||||
if (mRuleProcessors[SheetType::StyleAttr])
|
||||
(*aCollectorFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
|
||||
|
|
@ -1210,9 +1292,21 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (haveImportantDocRules) {
|
||||
aRuleWalker->SetLevel(SheetType::Doc, true, false);
|
||||
AddImportantRules(lastDocRN, lastSVGAttrAnimationRN, aRuleWalker); // doc
|
||||
if (haveAnyImportantDocRules) {
|
||||
for (uint32_t i = lastDocRNs.Length(); i-- != 0; ) {
|
||||
aRuleWalker->SetLevel(SheetType::Doc, true, false);
|
||||
nsRuleNode* startRN = lastDocRNs[i];
|
||||
nsRuleNode* endRN = i == 0 ? lastSVGAttrAnimationRN : lastDocRNs[i - 1];
|
||||
bool isNearestToNACWithImportantRules = i == 0 && haveImportantNACRules;
|
||||
if (haveImportantDocRules[i] || isNearestToNACWithImportantRules) {
|
||||
AddImportantRules(startRN, endRN, aRuleWalker); // doc
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
AssertNoImportantRules(startRN, endRN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
|
|
@ -1244,9 +1338,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
AssertNoCSSRules(lastSVGAttrAnimationRN, lastUserRN);
|
||||
#endif
|
||||
|
||||
if (haveImportantUserRules) {
|
||||
aRuleWalker->SetLevel(SheetType::User, true, false);
|
||||
AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user
|
||||
if (haveAnyImportantUserRules) {
|
||||
for (uint32_t i = lastUserRNs.Length(); i-- != 0;) {
|
||||
aRuleWalker->SetLevel(SheetType::User, true, false);
|
||||
nsRuleNode* startRN = lastUserRNs[i];
|
||||
nsRuleNode* endRN = i == 0 ? lastAgentRN : lastUserRNs[i - 1];
|
||||
if (haveImportantUserRules[i]) {
|
||||
AddImportantRules(startRN, endRN, aRuleWalker); // user
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
AssertNoImportantRules(startRN, endRN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
|
|
@ -1254,9 +1359,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (haveImportantUARules) {
|
||||
aRuleWalker->SetLevel(SheetType::Agent, true, false);
|
||||
AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent
|
||||
if (haveAnyImportantAgentRules) {
|
||||
for (uint32_t i = lastAgentRNs.Length(); i-- != 0;) {
|
||||
aRuleWalker->SetLevel(SheetType::Agent, true, false);
|
||||
nsRuleNode* startRN = lastAgentRNs[i];
|
||||
nsRuleNode* endRN = i == 0 ? lastRestrictionRN : lastAgentRNs[i - 1];
|
||||
if (haveImportantAgentRules[i]) {
|
||||
AddImportantRules(startRN, endRN, aRuleWalker); // agent
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
AssertNoImportantRules(startRN, endRN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue