Issue #2045 - Part 8: Remap revert keyword values to a higher cascade level

This commit is contained in:
Francis Dominic Fajardo 2025-07-03 17:51:18 +08:00 • committed by roytam1
commit a47f44e93d
3 changed files with 45 additions and 24 deletions

View file

@ -174,7 +174,8 @@ MapSinglePropertyInto(nsCSSPropertyID aTargetProp,
// then records any resulting ImageValue objects in the // then records any resulting ImageValue objects in the
// CSSVariableImageTable, to give them the appropriate lifetime. // CSSVariableImageTable, to give them the appropriate lifetime.
MOZ_ASSERT(aTargetValue->GetUnit() == eCSSUnit_TokenStream || MOZ_ASSERT(aTargetValue->GetUnit() == eCSSUnit_TokenStream ||
aTargetValue->GetUnit() == eCSSUnit_Null, aTargetValue->GetUnit() == eCSSUnit_Null ||
aTargetValue->GetUnit() == eCSSUnit_Revert,
"aTargetValue must only be a token stream (when re-parsing " "aTargetValue must only be a token stream (when re-parsing "
"properties with variable references) or null"); "properties with variable references) or null");
@ -316,7 +317,13 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
EnsurePhysicalProperty(iProp, aRuleData); EnsurePhysicalProperty(iProp, aRuleData);
} }
nsCSSValue* target = aRuleData->ValueFor(iProp); nsCSSValue* target = aRuleData->ValueFor(iProp);
if (target->GetUnit() == eCSSUnit_Null) { if (target->GetUnit() == eCSSUnit_Revert) {
if (aRuleData->mLevel >= target->GetCascadeOriginValue()) {
continue;
}
} else if (target->GetUnit() != eCSSUnit_Null) {
continue;
}
const nsCSSValue* val = ValueAtIndex(i); const nsCSSValue* val = ValueAtIndex(i);
// In order for variable resolution to have the right information // In order for variable resolution to have the right information
// about the stylesheet level of a value, that level needs to be // about the stylesheet level of a value, that level needs to be
@ -326,12 +333,13 @@ nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const
// the rule walking will have just updated aRuleData. // the rule walking will have just updated aRuleData.
if (val->GetUnit() == eCSSUnit_TokenStream) { if (val->GetUnit() == eCSSUnit_TokenStream) {
val->GetTokenStreamValue()->mLevel = aRuleData->mLevel; val->GetTokenStreamValue()->mLevel = aRuleData->mLevel;
} else if (val->GetUnit() == eCSSUnit_Revert) {
aRuleData->mConditions.SetUncacheable();
} }
MapSinglePropertyInto(iProp, val, target, aRuleData); MapSinglePropertyInto(iProp, val, target, aRuleData);
} }
} }
} }
}
const nsCSSValue* const nsCSSValue*
nsCSSCompressedDataBlock::ValueFor(nsCSSPropertyID aProperty) const nsCSSCompressedDataBlock::ValueFor(nsCSSPropertyID aProperty) const

View file

@ -2248,7 +2248,8 @@ AreAllMathMLPropertiesUndefined(const nsRuleData* aRuleData)
inline nsRuleNode::RuleDetail inline nsRuleNode::RuleDetail
nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
const nsRuleData* aRuleData) const nsRuleData* aRuleData,
bool& ignoreRuleCache)
{ {
// Build a count of the: // Build a count of the:
uint32_t total = 0, // total number of props in the struct uint32_t total = 0, // total number of props in the struct
@ -2323,6 +2324,8 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
result = (*cb)(aRuleData, result); result = (*cb)(aRuleData, result);
} }
ignoreRuleCache = revert > 0;
return result; return result;
} }
@ -2491,6 +2494,7 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
// will be the root. (XXX misnamed) // will be the root. (XXX misnamed)
RuleDetail detail = eRuleNone; RuleDetail detail = eRuleNone;
uint32_t bit = nsCachedStyleData::GetBitForSID(aSID); uint32_t bit = nsCachedStyleData::GetBitForSID(aSID);
bool ignoreRuleCache = false;
while (ruleNode) { while (ruleNode) {
// See if this rule node has cached the fact that the remaining // See if this rule node has cached the fact that the remaining
@ -2517,9 +2521,16 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
// we'll miss it. // we'll miss it.
startStruct = ruleNode->mStyleData.GetStyleData(aSID); startStruct = ruleNode->mStyleData.GetStyleData(aSID);
if (startStruct) { if (startStruct) {
break; // We found a rule with fully specified data. We don't // XXX: Ignore cached data if the previous rule node has revert values.
} // need to go up the tree any further, since the remainder if (ignoreRuleCache) {
startStruct = nullptr;
} else {
// We found a rule with fully specified data. We don't
// need to go up the tree any further, since the remainder
// of this branch has already been computed. // of this branch has already been computed.
break;
}
}
// Ask the rule to fill in the properties that it specifies. // Ask the rule to fill in the properties that it specifies.
nsIStyleRule *rule = ruleNode->mRule; nsIStyleRule *rule = ruleNode->mRule;
@ -2532,15 +2543,15 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
// Now we check to see how many properties have been specified by // Now we check to see how many properties have been specified by
// the rules we've examined so far. // the rules we've examined so far.
RuleDetail oldDetail = detail; RuleDetail oldDetail = detail;
detail = CheckSpecifiedProperties(aSID, &ruleData); detail = CheckSpecifiedProperties(aSID, &ruleData, ignoreRuleCache);
if (oldDetail == eRuleNone && detail != eRuleNone) { if (oldDetail == eRuleNone && (detail != eRuleNone || ignoreRuleCache)) {
highestNode = ruleNode; highestNode = ruleNode;
} }
if (detail == eRuleFullReset || if (!ignoreRuleCache && (detail == eRuleFullReset ||
detail == eRuleFullMixed || detail == eRuleFullMixed ||
detail == eRuleFullInherited) { detail == eRuleFullInherited)) {
break; // We don't need to examine any more rules. All properties break; // We don't need to examine any more rules. All properties
} // have been fully specified. } // have been fully specified.
@ -2576,7 +2587,7 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
} }
if (recomputeDetail) { if (recomputeDetail) {
detail = CheckSpecifiedProperties(aSID, &ruleData); detail = CheckSpecifiedProperties(aSID, &ruleData, ignoreRuleCache);
} }
NS_ASSERTION(!startStruct || (detail != eRuleFullReset && NS_ASSERTION(!startStruct || (detail != eRuleFullReset &&
@ -10804,7 +10815,8 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
for (uint32_t i = 0; i < nValues; ++i) { for (uint32_t i = 0; i < nValues; ++i) {
if (values[i]->GetUnit() != eCSSUnit_Null && if (values[i]->GetUnit() != eCSSUnit_Null &&
values[i]->GetUnit() != eCSSUnit_Dummy && // see above values[i]->GetUnit() != eCSSUnit_Dummy && // see above
values[i]->GetUnit() != eCSSUnit_DummyInherit) { values[i]->GetUnit() != eCSSUnit_DummyInherit &&
values[i]->GetUnit() != eCSSUnit_Revert) {
// If author colors are not allowed, only claim to have // If author colors are not allowed, only claim to have
// author-specified rules if we're looking at a non-color // author-specified rules if we're looking at a non-color
// property or if we're looking at the background color and it's // property or if we're looking at the background color and it's

View file

@ -787,7 +787,8 @@ protected:
nsStyleFont* aFont); nsStyleFont* aFont);
inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID, inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
const nsRuleData* aRuleData); const nsRuleData* aRuleData,
bool& ignoreRuleCache);
private: private:
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent, nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,