mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-26 00:57:30 +09:00
Issue #2691: Refactored ParseSupportsSelector
This commit is contained in:
parent
ea580ec54b
commit
f2d6170830
1 changed files with 168 additions and 150 deletions
|
|
@ -4851,6 +4851,166 @@ CSSParserImpl::ParseSupportsMozBoolPrefName(bool& aConditionMet)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
builds selector strings with proper formatting and spacing.
|
||||||
|
reconstructs selectors from tokens.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
AppendSelectorToken(const nsCSSToken& aToken,
|
||||||
|
nsAutoString& aSelectorText,
|
||||||
|
int32_t& aParenDepth,
|
||||||
|
bool& aHasContent)
|
||||||
|
{
|
||||||
|
aHasContent = true;
|
||||||
|
|
||||||
|
// space calculation depending on paren nesting
|
||||||
|
bool needSpace = false;
|
||||||
|
if (!aSelectorText.IsEmpty()) {
|
||||||
|
char16_t lastChar = aSelectorText.Last();
|
||||||
|
|
||||||
|
// nth-child formulas: no spaces inside paren
|
||||||
|
if (aParenDepth > 0) {
|
||||||
|
// add space before and after 'of'
|
||||||
|
if (aToken.mType == eCSSToken_Ident && aToken.mIdent.LowerCaseEqualsLiteral("of")) {
|
||||||
|
needSpace = true;
|
||||||
|
}
|
||||||
|
else if (aToken.mType != eCSSToken_Ident && lastChar != '(' && lastChar != ' ' &&
|
||||||
|
aSelectorText.Length() >= 2) {
|
||||||
|
nsAutoString lastTwo;
|
||||||
|
if (aSelectorText.Length() >= 2) {
|
||||||
|
lastTwo = Substring(aSelectorText, aSelectorText.Length() - 2, 2);
|
||||||
|
if (lastTwo.EqualsLiteral("of")) {
|
||||||
|
needSpace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// normal case: standard spacing rules (add space before
|
||||||
|
// identifiers/classes if last char is alphanumeric)
|
||||||
|
if ((aToken.mType == eCSSToken_Ident || aToken.mType == eCSSToken_Symbol) &&
|
||||||
|
lastChar != ' ' && lastChar != ':' && lastChar != '.' && lastChar != '#' &&
|
||||||
|
lastChar != '[' && lastChar != '(' && lastChar != '>' && lastChar != '+' &&
|
||||||
|
lastChar != '~' && lastChar != ',') {
|
||||||
|
|
||||||
|
// special case: if it follows an identifier, add space before '.'
|
||||||
|
if (aToken.mType == eCSSToken_Symbol && aToken.mSymbol == '.' &&
|
||||||
|
((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z'))) {
|
||||||
|
needSpace = true;
|
||||||
|
}
|
||||||
|
// add space between consecutive identifiers
|
||||||
|
else if (aToken.mType == eCSSToken_Ident &&
|
||||||
|
((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z') ||
|
||||||
|
(lastChar >= '0' && lastChar <= '9') || lastChar == ')')) {
|
||||||
|
needSpace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// token reconstruction
|
||||||
|
switch (aToken.mType) {
|
||||||
|
case eCSSToken_Ident:
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_AtKeyword:
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
aSelectorText.Append('@');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_ID:
|
||||||
|
aSelectorText.Append('#');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_Hash:
|
||||||
|
aSelectorText.Append('#');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_Symbol:
|
||||||
|
if ((aToken.mSymbol == '+' || aToken.mSymbol == '-') && aParenDepth > 0) {
|
||||||
|
aSelectorText.Append(aToken.mSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add spaces around combinators (at top level)
|
||||||
|
else if ((aToken.mSymbol == '+' || aToken.mSymbol == '>' || aToken.mSymbol == '~') && aParenDepth == 0) {
|
||||||
|
if (!aSelectorText.IsEmpty() && aSelectorText.Last() != ' ') {
|
||||||
|
aSelectorText.Append(' ');
|
||||||
|
}
|
||||||
|
aSelectorText.Append(aToken.mSymbol);
|
||||||
|
aSelectorText.Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (aToken.mSymbol == '.' && !aSelectorText.IsEmpty()) {
|
||||||
|
char16_t lastChar = aSelectorText.Last();
|
||||||
|
if ((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z')) {
|
||||||
|
aSelectorText.Append(' ');
|
||||||
|
}
|
||||||
|
aSelectorText.Append(aToken.mSymbol);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aSelectorText.Append(aToken.mSymbol);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_String:
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
aSelectorText.Append('"');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
aSelectorText.Append('"');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_Function:
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
aSelectorText.Append('(');
|
||||||
|
aParenDepth++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_Number:
|
||||||
|
if (aToken.mHasSign && aParenDepth > 0) {
|
||||||
|
if (aToken.mNumber >= 0) {
|
||||||
|
aSelectorText.Append('+');
|
||||||
|
} else {
|
||||||
|
aSelectorText.Append('-');
|
||||||
|
}
|
||||||
|
if (std::abs(aToken.mNumber) == floor(std::abs(aToken.mNumber))) {
|
||||||
|
aSelectorText.AppendInt(int32_t(std::abs(aToken.mNumber)));
|
||||||
|
} else {
|
||||||
|
aSelectorText.AppendFloat(std::abs(aToken.mNumber));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
if (aToken.mNumber == floor(aToken.mNumber)) {
|
||||||
|
aSelectorText.AppendInt(int32_t(aToken.mNumber));
|
||||||
|
} else {
|
||||||
|
aSelectorText.AppendFloat(aToken.mNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eCSSToken_Dimension:
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
if (aToken.mNumber == floor(aToken.mNumber)) {
|
||||||
|
aSelectorText.AppendInt(int32_t(aToken.mNumber));
|
||||||
|
} else {
|
||||||
|
aSelectorText.AppendFloat(aToken.mNumber);
|
||||||
|
}
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (!aToken.mIdent.IsEmpty()) {
|
||||||
|
if (needSpace) aSelectorText.Append(' ');
|
||||||
|
aSelectorText.Append(aToken.mIdent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// supports_selector
|
// supports_selector
|
||||||
// : 'selector(' single_selector ')'
|
// : 'selector(' single_selector ')'
|
||||||
// ;
|
// ;
|
||||||
|
|
@ -4864,9 +5024,10 @@ CSSParserImpl::ParseSupportsSelector(bool& aConditionMet)
|
||||||
bool hasContent = false;
|
bool hasContent = false;
|
||||||
int32_t parenDepth = 0;
|
int32_t parenDepth = 0;
|
||||||
|
|
||||||
|
// fail unexpected EOF
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!GetToken(true)) {
|
if (!GetToken(true)) {
|
||||||
return false; // fail unexpected EOF
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mToken.IsSymbol(')')) {
|
if (mToken.IsSymbol(')')) {
|
||||||
|
|
@ -4881,152 +5042,7 @@ CSSParserImpl::ParseSupportsSelector(bool& aConditionMet)
|
||||||
parenDepth++;
|
parenDepth++;
|
||||||
selectorText.Append(mToken.mSymbol);
|
selectorText.Append(mToken.mSymbol);
|
||||||
} else {
|
} else {
|
||||||
hasContent = true;
|
AppendSelectorToken(mToken, selectorText, parenDepth, hasContent);
|
||||||
|
|
||||||
bool needSpace = false;
|
|
||||||
if (!selectorText.IsEmpty()) {
|
|
||||||
char16_t lastChar = selectorText.Last();
|
|
||||||
|
|
||||||
// Don't add spaces inside parentheses for nth-child formulas
|
|
||||||
if (parenDepth > 0) {
|
|
||||||
// Inside parentheses, only add space before "of" keyword
|
|
||||||
if (mToken.mType == eCSSToken_Ident && mToken.mIdent.LowerCaseEqualsLiteral("of")) {
|
|
||||||
needSpace = true;
|
|
||||||
}
|
|
||||||
// Also add space after "of"
|
|
||||||
else if (mToken.mType != eCSSToken_Ident && lastChar != '(' && lastChar != ' ' &&
|
|
||||||
selectorText.Length() >= 2) {
|
|
||||||
// Check if previous token was "of"
|
|
||||||
nsAutoString lastTwo;
|
|
||||||
if (selectorText.Length() >= 2) {
|
|
||||||
lastTwo = Substring(selectorText, selectorText.Length() - 2, 2);
|
|
||||||
if (lastTwo.EqualsLiteral("of")) {
|
|
||||||
needSpace = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Outside parentheses, use normal spacing rules
|
|
||||||
// Add space before identifiers and classes if last char was alphanumeric
|
|
||||||
if ((mToken.mType == eCSSToken_Ident || mToken.mType == eCSSToken_Symbol) &&
|
|
||||||
lastChar != ' ' && lastChar != ':' && lastChar != '.' && lastChar != '#' &&
|
|
||||||
lastChar != '[' && lastChar != '(' && lastChar != '>' && lastChar != '+' &&
|
|
||||||
lastChar != '~' && lastChar != ',') {
|
|
||||||
// Special case: add space before '.' if it follows an identifier
|
|
||||||
if (mToken.mType == eCSSToken_Symbol && mToken.mSymbol == '.' &&
|
|
||||||
((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z'))) {
|
|
||||||
needSpace = true;
|
|
||||||
}
|
|
||||||
// Add space between consecutive identifiers
|
|
||||||
else if (mToken.mType == eCSSToken_Ident &&
|
|
||||||
((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z') ||
|
|
||||||
(lastChar >= '0' && lastChar <= '9') || lastChar == ')')) {
|
|
||||||
needSpace = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mToken.mType) {
|
|
||||||
case eCSSToken_Ident:
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_AtKeyword:
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
selectorText.Append('@');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_ID:
|
|
||||||
selectorText.Append('#');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_Hash:
|
|
||||||
selectorText.Append('#');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_Symbol:
|
|
||||||
if ((mToken.mSymbol == '+' || mToken.mSymbol == '-') && parenDepth > 0) {
|
|
||||||
selectorText.Append(mToken.mSymbol);
|
|
||||||
}
|
|
||||||
// add spaces around combinators (only at top level)
|
|
||||||
else if ((mToken.mSymbol == '+' || mToken.mSymbol == '>' || mToken.mSymbol == '~') && parenDepth == 0) {
|
|
||||||
if (!selectorText.IsEmpty() && selectorText.Last() != ' ') {
|
|
||||||
selectorText.Append(' ');
|
|
||||||
}
|
|
||||||
selectorText.Append(mToken.mSymbol);
|
|
||||||
selectorText.Append(' ');
|
|
||||||
}
|
|
||||||
// add spaces around top-level combinators
|
|
||||||
else if (mToken.mSymbol == '.' && !selectorText.IsEmpty()) {
|
|
||||||
char16_t lastChar = selectorText.Last();
|
|
||||||
if ((lastChar >= 'a' && lastChar <= 'z') || (lastChar >= 'A' && lastChar <= 'Z')) {
|
|
||||||
selectorText.Append(' ');
|
|
||||||
}
|
|
||||||
selectorText.Append(mToken.mSymbol);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selectorText.Append(mToken.mSymbol);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_String:
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
selectorText.Append('"');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
selectorText.Append('"');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_Function:
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
selectorText.Append('(');
|
|
||||||
parenDepth++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_Number:
|
|
||||||
if (mToken.mHasSign && parenDepth > 0) {
|
|
||||||
if (mToken.mNumber >= 0) {
|
|
||||||
selectorText.Append('+');
|
|
||||||
} else {
|
|
||||||
selectorText.Append('-');
|
|
||||||
}
|
|
||||||
if (std::abs(mToken.mNumber) == floor(std::abs(mToken.mNumber))) {
|
|
||||||
selectorText.AppendInt(int32_t(std::abs(mToken.mNumber)));
|
|
||||||
} else {
|
|
||||||
selectorText.AppendFloat(std::abs(mToken.mNumber));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
if (mToken.mNumber == floor(mToken.mNumber)) {
|
|
||||||
selectorText.AppendInt(int32_t(mToken.mNumber));
|
|
||||||
} else {
|
|
||||||
selectorText.AppendFloat(mToken.mNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eCSSToken_Dimension:
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
if (mToken.mNumber == floor(mToken.mNumber)) {
|
|
||||||
selectorText.AppendInt(int32_t(mToken.mNumber));
|
|
||||||
} else {
|
|
||||||
selectorText.AppendFloat(mToken.mNumber);
|
|
||||||
}
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (!mToken.mIdent.IsEmpty()) {
|
|
||||||
if (needSpace) selectorText.Append(' ');
|
|
||||||
selectorText.Append(mToken.mIdent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5046,7 +5062,8 @@ CSSParserImpl::ParseSupportsSelector(bool& aConditionMet)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
parenDepth = 0; // reset parenDepth for comma checking
|
// reset parenDepth for comma checking
|
||||||
|
parenDepth = 0;
|
||||||
for (uint32_t i = 0; i < selectorText.Length(); i++) {
|
for (uint32_t i = 0; i < selectorText.Length(); i++) {
|
||||||
char16_t c = selectorText.CharAt(i);
|
char16_t c = selectorText.CharAt(i);
|
||||||
if (c == '(') {
|
if (c == '(') {
|
||||||
|
|
@ -5055,12 +5072,14 @@ CSSParserImpl::ParseSupportsSelector(bool& aConditionMet)
|
||||||
if (parenDepth > 0) {
|
if (parenDepth > 0) {
|
||||||
parenDepth--;
|
parenDepth--;
|
||||||
}
|
}
|
||||||
} else if (c == ',' && parenDepth == 0) { // top-level comma found
|
} else if (c == ',' && parenDepth == 0) {
|
||||||
|
// top-level comma found
|
||||||
aConditionMet = false;
|
aConditionMet = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// catch ::-webkit- pseudo-elements
|
||||||
if (selectorText.Find(NS_LITERAL_STRING("::-webkit-")) >= 0) {
|
if (selectorText.Find(NS_LITERAL_STRING("::-webkit-")) >= 0) {
|
||||||
aConditionMet = false;
|
aConditionMet = false;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -5081,7 +5100,6 @@ CSSParserImpl::ParseSupportsSelector(bool& aConditionMet)
|
||||||
delete selectorList;
|
delete selectorList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aConditionMet = supportSuccess;
|
aConditionMet = supportSuccess;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue