Issue #2045 - Part 5: Serialize shorthands using "revert" like those containing "unset"

This commit is contained in:
Francis Dominic Fajardo 2025-06-20 10:33:40 +08:00 • committed by roytam1
commit 801d4a2db8
3 changed files with 68 additions and 24 deletions

View file

@ -11,12 +11,13 @@
#include "nsCSSScanner.h" #include "nsCSSScanner.h"
#include "nsRuleData.h" #include "nsRuleData.h"
// These three special string values are used to represent specified values of // These four special string values are used to represent specified values of
// 'initial', 'inherit' and 'unset'. (Note that none of these are valid // 'initial', 'inherit', 'unset', and 'revert'. (Note that none of these are
// variable values.) // valid variable values.)
#define INITIAL_VALUE "!" #define INITIAL_VALUE "!"
#define INHERIT_VALUE ";" #define INHERIT_VALUE ";"
#define UNSET_VALUE ")" #define UNSET_VALUE ")"
#define REVERT_VALUE ">"
namespace mozilla { namespace mozilla {
@ -83,6 +84,9 @@ CSSVariableDeclarations::Get(const nsAString& aName,
} else if (value.EqualsLiteral(UNSET_VALUE)) { } else if (value.EqualsLiteral(UNSET_VALUE)) {
aType = eUnset; aType = eUnset;
aTokenStream.Truncate(); aTokenStream.Truncate();
} else if (value.EqualsLiteral(REVERT_VALUE)) {
aType = eRevert;
aTokenStream.Truncate();
} else { } else {
aType = eTokenStream; aType = eTokenStream;
aTokenStream = value; aTokenStream = value;
@ -96,7 +100,8 @@ CSSVariableDeclarations::PutTokenStream(const nsAString& aName,
{ {
MOZ_ASSERT(!aTokenStream.EqualsLiteral(INITIAL_VALUE) && MOZ_ASSERT(!aTokenStream.EqualsLiteral(INITIAL_VALUE) &&
!aTokenStream.EqualsLiteral(INHERIT_VALUE) && !aTokenStream.EqualsLiteral(INHERIT_VALUE) &&
!aTokenStream.EqualsLiteral(UNSET_VALUE)); !aTokenStream.EqualsLiteral(UNSET_VALUE) &&
!aTokenStream.EqualsLiteral(REVERT_VALUE));
mVariables.Put(aName, aTokenStream); mVariables.Put(aName, aTokenStream);
} }
@ -118,6 +123,12 @@ CSSVariableDeclarations::PutUnset(const nsAString& aName)
mVariables.Put(aName, NS_LITERAL_STRING(UNSET_VALUE)); mVariables.Put(aName, NS_LITERAL_STRING(UNSET_VALUE));
} }
void
CSSVariableDeclarations::PutRevert(const nsAString& aName)
{
mVariables.Put(aName, NS_LITERAL_STRING(REVERT_VALUE));
}
void void
CSSVariableDeclarations::Remove(const nsAString& aName) CSSVariableDeclarations::Remove(const nsAString& aName)
{ {
@ -160,12 +171,13 @@ CSSVariableDeclarations::AddVariablesToResolver(
eCSSTokenSerialization_Nothing, eCSSTokenSerialization_Nothing,
false); false);
} else if (value.EqualsLiteral(INHERIT_VALUE) || } else if (value.EqualsLiteral(INHERIT_VALUE) ||
value.EqualsLiteral(UNSET_VALUE)) { value.EqualsLiteral(UNSET_VALUE) ||
// Values of 'inherit' and 'unset' don't need any handling, since it means value.EqualsLiteral(REVERT_VALUE)) {
// we just need to keep whatever value is currently in the resolver. This // Values of 'inherit', 'unset', and 'revert' don't need any handling,
// is because the specified variable declarations already have only the // since it means we just need to keep whatever value is currently in
// winning declaration for the variable and no longer have any of the // the resolver. This is because the specified variable declarations
// others. // already have only the winning declaration for the variable and no
// longer have any of the others.
} else { } else {
// At this point, we don't know what token types are at the start and end // At this point, we don't know what token types are at the start and end
// of the specified variable value. These will be determined later during // of the specified variable value. These will be determined later during

View file

@ -42,7 +42,8 @@ public:
eTokenStream, // a stream of CSS tokens (the usual type for variables) eTokenStream, // a stream of CSS tokens (the usual type for variables)
eInitial, // 'initial' eInitial, // 'initial'
eInherit, // 'inherit' eInherit, // 'inherit'
eUnset // 'unset' eUnset, // 'unset'
eRevert // 'revert'
}; };
/** /**
@ -53,8 +54,8 @@ public:
* @param aType Out parameter into which the type of the variable value will * @param aType Out parameter into which the type of the variable value will
* be stored. * be stored.
* @param aValue Out parameter into which the value of the variable will * @param aValue Out parameter into which the value of the variable will
* be stored. If the variable is 'initial', 'inherit' or 'unset', this will * be stored. If the variable is 'initial', 'inherit', 'unset', or
* be the empty string. * 'revert', this will be the empty string.
* @return Whether a variable with the given name was found. When false * @return Whether a variable with the given name was found. When false
* is returned, aType and aValue will not be modified. * is returned, aType and aValue will not be modified.
*/ */
@ -87,6 +88,15 @@ public:
*/ */
void PutUnset(const nsAString& aName); void PutUnset(const nsAString& aName);
/**
* Adds or modifies an existing entry in this set of variable declarations
* to have the value 'revert'.
*
* @param aName The variable name (not including any "--" prefix that would
* be part of the custom property name) whose value is to be set.
*/
void PutRevert(const nsAString& aName);
/** /**
* Adds or modifies an existing entry in this set of variable declarations * Adds or modifies an existing entry in this set of variable declarations
* to have a token stream value. * to have a token stream value.

View file

@ -558,9 +558,9 @@ Declaration::GetPropertyValueInternal(
// (1) Since a shorthand sets all sub-properties, if some of its // (1) Since a shorthand sets all sub-properties, if some of its
// subproperties were not specified, we must return the empty // subproperties were not specified, we must return the empty
// string. // string.
// (2) Since 'inherit', 'initial' and 'unset' can only be specified // (2) Since 'inherit', 'initial', 'unset', and 'revert' can only be
// as the values for entire properties, we need to return the // specified as the values for entire properties, we need to return
// empty string if some but not all of the subproperties have one // the empty string if some but not all of the subproperties have one
// of those values. // of those values.
// (3) Since a single value only makes sense with or without // (3) Since a single value only makes sense with or without
// !important, we return the empty string if some values are // !important, we return the empty string if some values are
@ -575,7 +575,7 @@ Declaration::GetPropertyValueInternal(
// assigned to the shorthand. // assigned to the shorthand.
const nsCSSValue* tokenStream = nullptr; const nsCSSValue* tokenStream = nullptr;
uint32_t totalCount = 0, importantCount = 0, uint32_t totalCount = 0, importantCount = 0,
initialCount = 0, inheritCount = 0, unsetCount = 0, initialCount = 0, inheritCount = 0, unsetCount = 0, revertCount = 0,
matchingTokenStreamCount = 0, nonMatchingTokenStreamCount = 0; matchingTokenStreamCount = 0, nonMatchingTokenStreamCount = 0;
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty, CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty,
CSSEnabledState::eForAllContent) { CSSEnabledState::eForAllContent) {
@ -601,6 +601,8 @@ Declaration::GetPropertyValueInternal(
++initialCount; ++initialCount;
} else if (val->GetUnit() == eCSSUnit_Unset) { } else if (val->GetUnit() == eCSSUnit_Unset) {
++unsetCount; ++unsetCount;
} else if (val->GetUnit() == eCSSUnit_Revert) {
++revertCount;
} else if (val->GetUnit() == eCSSUnit_TokenStream) { } else if (val->GetUnit() == eCSSUnit_TokenStream) {
if (val->GetTokenStreamValue()->mShorthandPropertyID == aProperty) { if (val->GetTokenStreamValue()->mShorthandPropertyID == aProperty) {
tokenStream = val; tokenStream = val;
@ -632,9 +634,15 @@ Declaration::GetPropertyValueInternal(
nsCSSValue::eNormalized); nsCSSValue::eNormalized);
return; return;
} }
if (initialCount != 0 || inheritCount != 0 || if (revertCount == totalCount) {
unsetCount != 0 || nonMatchingTokenStreamCount != 0) { // Simplify serialization below by serializing revert up-front.
// Case (2): partially initial, inherit, unset or token stream. nsCSSValue(eCSSUnit_Revert).AppendToString(eCSSProperty_UNKNOWN, aValue,
nsCSSValue::eNormalized);
return;
}
if (initialCount != 0 || inheritCount != 0 || unsetCount != 0 ||
revertCount != 0 || nonMatchingTokenStreamCount != 0) {
// Case (2): partially initial, inherit, unset, revert, or token stream.
return; return;
} }
if (tokenStream) { if (tokenStream) {
@ -1455,6 +1463,7 @@ Declaration::GetPropertyValueInternal(
case eCSSUnit_Inherit: case eCSSUnit_Inherit:
case eCSSUnit_Initial: case eCSSUnit_Initial:
case eCSSUnit_Unset: case eCSSUnit_Unset:
case eCSSUnit_Revert:
return true; return true;
case eCSSUnit_Enumerated: case eCSSUnit_Enumerated:
// return false if there is a fallback value or <overflow-position> // return false if there is a fallback value or <overflow-position>
@ -1563,10 +1572,10 @@ Declaration::GetPropertyValueInternal(
break; break;
} }
case eCSSProperty_all: case eCSSProperty_all:
// If we got here, then we didn't have all "inherit" or "initial" or // If we got here, then we didn't have all "inherit", "initial", "unset",
// "unset" values for all of the longhand property components of 'all'. // or "revert" values for all of the longhand property components of
// There is no other possible value that is valid for all properties, // 'all'. There is no other possible value that is valid for all
// so serialize as the empty string. // properties, so serialize as the empty string.
break; break;
default: default:
MOZ_ASSERT(false, "no other shorthands"); MOZ_ASSERT(false, "no other shorthands");
@ -1663,6 +1672,10 @@ Declaration::AppendVariableAndValueToString(const nsAString& aName,
aResult.AppendLiteral("unset"); aResult.AppendLiteral("unset");
break; break;
case CSSVariableDeclarations::eRevert:
aResult.AppendLiteral("revert");
break;
default: default:
MOZ_ASSERT(false, "unexpected variable value type"); MOZ_ASSERT(false, "unexpected variable value type");
} }
@ -1899,6 +1912,10 @@ Declaration::GetVariableValue(const nsAString& aName, nsAString& aValue) const
aValue.AppendLiteral("unset"); aValue.AppendLiteral("unset");
break; break;
case CSSVariableDeclarations::eRevert:
aValue.AppendLiteral("revert");
break;
default: default:
MOZ_ASSERT(false, "unexpected variable value type"); MOZ_ASSERT(false, "unexpected variable value type");
} }
@ -1964,6 +1981,11 @@ Declaration::AddVariable(const nsAString& aName,
variables->PutUnset(aName); variables->PutUnset(aName);
break; break;
case CSSVariableDeclarations::eRevert:
MOZ_ASSERT(aValue.IsEmpty());
variables->PutRevert(aName);
break;
default: default:
MOZ_ASSERT(false, "unexpected aType value"); MOZ_ASSERT(false, "unexpected aType value");
} }