mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 04:17:31 +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
|
#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.
|
// Enumerate the rules in a way that cares about the order of the rules.
|
||||||
void
|
void
|
||||||
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
|
|
@ -1097,6 +1134,9 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
|
|
||||||
NS_ASSERTION(mBatching == 0, "rule processors out of date");
|
NS_ASSERTION(mBatching == 0, "rule processors out of date");
|
||||||
|
|
||||||
|
bool skipUserStyles =
|
||||||
|
aElement && aElement->IsInNativeAnonymousSubtree();
|
||||||
|
|
||||||
// Cascading order:
|
// Cascading order:
|
||||||
// [least important]
|
// [least important]
|
||||||
// - UA normal rules = Agent normal
|
// - 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.
|
// this will be either the root or one of the restriction rules.
|
||||||
nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
|
nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
|
||||||
|
|
||||||
aRuleWalker->SetLevel(SheetType::Agent, false, true);
|
nsRuleNode* lastAgentRN = nullptr;
|
||||||
if (mRuleProcessors[SheetType::Agent])
|
nsTArray<nsRuleNode*> lastAgentRNs;
|
||||||
(*aCollectorFunc)(mRuleProcessors[SheetType::Agent], aData);
|
nsTArray<bool> haveImportantAgentRules;
|
||||||
nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode();
|
bool haveAnyImportantAgentRules = false;
|
||||||
bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules();
|
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::Agent],
|
||||||
|
aCollectorFunc,
|
||||||
|
aData,
|
||||||
|
aRuleWalker,
|
||||||
|
SheetType::Agent,
|
||||||
|
lastAgentRN,
|
||||||
|
lastAgentRNs,
|
||||||
|
haveImportantAgentRules,
|
||||||
|
haveAnyImportantAgentRules);
|
||||||
|
if (!lastAgentRN) {
|
||||||
|
lastAgentRN = aRuleWalker->CurrentNode();
|
||||||
|
}
|
||||||
|
|
||||||
aRuleWalker->SetLevel(SheetType::User, false, true);
|
nsRuleNode* lastUserRN = nullptr;
|
||||||
bool skipUserStyles =
|
nsTArray<nsRuleNode*> lastUserRNs;
|
||||||
aElement && aElement->IsInNativeAnonymousSubtree();
|
nsTArray<bool> haveImportantUserRules;
|
||||||
if (!skipUserStyles && mRuleProcessors[SheetType::User]) // NOTE: different
|
bool haveAnyImportantUserRules = false;
|
||||||
(*aCollectorFunc)(mRuleProcessors[SheetType::User], aData);
|
if (!skipUserStyles) { // NOTE: different
|
||||||
nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
|
FileRulesFromAllChildProcessors(mRuleProcessors[SheetType::User],
|
||||||
bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
|
aCollectorFunc,
|
||||||
|
aData,
|
||||||
|
aRuleWalker,
|
||||||
|
SheetType::User,
|
||||||
|
lastUserRN,
|
||||||
|
lastUserRNs,
|
||||||
|
haveImportantUserRules,
|
||||||
|
haveAnyImportantUserRules);
|
||||||
|
}
|
||||||
|
if (!lastUserRN) {
|
||||||
|
lastUserRN = aRuleWalker->CurrentNode();
|
||||||
|
}
|
||||||
|
|
||||||
aRuleWalker->SetLevel(SheetType::PresHint, false, false);
|
aRuleWalker->SetLevel(SheetType::PresHint, false, false);
|
||||||
if (mRuleProcessors[SheetType::PresHint])
|
if (mRuleProcessors[SheetType::PresHint])
|
||||||
|
|
@ -1148,16 +1210,35 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
static_cast<ElementDependentRuleProcessorData*>(aData),
|
static_cast<ElementDependentRuleProcessorData*>(aData),
|
||||||
&cutOffInheritance);
|
&cutOffInheritance);
|
||||||
}
|
}
|
||||||
if (!skipUserStyles && !cutOffInheritance && // NOTE: different
|
bool haveImportantNACRules = !aRuleWalker->GetCheckForImportantRules();
|
||||||
mRuleProcessors[SheetType::Doc])
|
|
||||||
(*aCollectorFunc)(mRuleProcessors[SheetType::Doc], aData);
|
nsRuleNode* lastDocRN = nullptr;
|
||||||
nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
|
nsTArray<nsRuleNode*> lastDocRNs;
|
||||||
bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
|
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<nsRuleNode*> lastScopedRNs;
|
||||||
nsTArray<bool> haveImportantScopedRules;
|
nsTArray<bool> haveImportantScopedRules;
|
||||||
bool haveAnyImportantScopedRules = false;
|
bool haveAnyImportantScopedRules = false;
|
||||||
if (!skipUserStyles && !cutOffInheritance &&
|
if (!skipUserStyles && !cutOffInheritance &&
|
||||||
aElement && aElement->IsElementInStyleScope()) {
|
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());
|
lastScopedRNs.SetLength(mScopedDocSheetRuleProcessors.Length());
|
||||||
haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length());
|
haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length());
|
||||||
for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
|
for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
|
||||||
|
|
@ -1173,6 +1254,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
aData->mScope = nullptr;
|
aData->mScope = nullptr;
|
||||||
}
|
}
|
||||||
nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode();
|
nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode();
|
||||||
|
|
||||||
aRuleWalker->SetLevel(SheetType::StyleAttr, false, true);
|
aRuleWalker->SetLevel(SheetType::StyleAttr, false, true);
|
||||||
if (mRuleProcessors[SheetType::StyleAttr])
|
if (mRuleProcessors[SheetType::StyleAttr])
|
||||||
(*aCollectorFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
|
(*aCollectorFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
|
||||||
|
|
@ -1210,9 +1292,21 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (haveImportantDocRules) {
|
if (haveAnyImportantDocRules) {
|
||||||
aRuleWalker->SetLevel(SheetType::Doc, true, false);
|
for (uint32_t i = lastDocRNs.Length(); i-- != 0; ) {
|
||||||
AddImportantRules(lastDocRN, lastSVGAttrAnimationRN, aRuleWalker); // doc
|
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
|
#ifdef DEBUG
|
||||||
else {
|
else {
|
||||||
|
|
@ -1244,9 +1338,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
AssertNoCSSRules(lastSVGAttrAnimationRN, lastUserRN);
|
AssertNoCSSRules(lastSVGAttrAnimationRN, lastUserRN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (haveImportantUserRules) {
|
if (haveAnyImportantUserRules) {
|
||||||
aRuleWalker->SetLevel(SheetType::User, true, false);
|
for (uint32_t i = lastUserRNs.Length(); i-- != 0;) {
|
||||||
AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user
|
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
|
#ifdef DEBUG
|
||||||
else {
|
else {
|
||||||
|
|
@ -1254,9 +1359,20 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (haveImportantUARules) {
|
if (haveAnyImportantAgentRules) {
|
||||||
aRuleWalker->SetLevel(SheetType::Agent, true, false);
|
for (uint32_t i = lastAgentRNs.Length(); i-- != 0;) {
|
||||||
AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent
|
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
|
#ifdef DEBUG
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue