summaryrefslogtreecommitdiff
path: root/layout
diff options
context:
space:
mode:
authorFranklinDM <mrmineshafter17@gmail.com>2023-03-19 18:48:24 +0800
committerMoonchild <moonchild@palemoon.org>2023-03-23 12:18:01 +0100
commit7c82808510e2cc164ef1e030bbff847416424d28 (patch)
tree95dd17a9b43a32a628a8fcade37e09408258334e /layout
parentc5cb2983e64aa7c2da2b3d504e1298d3a6b42522 (diff)
downloaduxp-7c82808510e2cc164ef1e030bbff847416424d28.tar.gz
Issue #1592 - Part 6: Allow pseudo-classes with a forgiving selector list argument to follow pseudo-elements
Pseudo-classes with a forgiving selector list argument are allowed to follow a pseudo-element, but must treat any selector that is not of the same type as invalid. It doesn't make any sense, but that's the behavior of other tainted browsers.
Diffstat (limited to 'layout')
-rw-r--r--layout/style/nsCSSParser.cpp62
1 files changed, 49 insertions, 13 deletions
diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
index db29dc6441..1483eb0a11 100644
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -119,7 +119,8 @@ enum class SelectorParsingFlags {
eIsForgiving = 1 << 1,
eDisallowCombinators = 1 << 2,
eDisallowPseudoElements = 1 << 3,
- eInheritNamespace = 1 << 4
+ eInheritNamespace = 1 << 4,
+ eForceEmptyList = 1 << 5
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SelectorParsingFlags)
@@ -6107,6 +6108,8 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
nsCSSPseudoClasses::GetPseudoType(pseudo, enabledState);
bool pseudoClassIsUserAction =
nsCSSPseudoClasses::IsUserActionPseudoClass(pseudoClassType);
+ bool pseudoClassHasForgivingSelectorListArg =
+ nsCSSPseudoClasses::HasForgivingSelectorListArg(pseudoClassType);
if (nsCSSAnonBoxes::IsNonElement(pseudo)) {
// Non-element anonymous boxes should not match any rule.
@@ -6199,6 +6202,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
return eSelectorParsingStatus_Error;
}
+ bool forceEmptyList = false;
if (aSelector.IsPseudoElement() || aSelector.IsHybridPseudoElement()) {
CSSPseudoElementType type = aSelector.IsPseudoElement() ?
aSelector.PseudoType() :
@@ -6216,13 +6220,20 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
return eSelectorParsingStatus_Error;
}
- if (isPseudoClass &&
- (!supportsUserAction || !pseudoClassIsUserAction)) {
- // CSS 4 Selectors says that pseudo-elements can only be followed by
- // a user action pseudo-class.
- REPORT_UNEXPECTED_TOKEN(PEPseudoClassNotUserAction);
- UngetToken();
- return eSelectorParsingStatus_Error;
+ if (isPseudoClass) {
+ if (pseudoClassHasForgivingSelectorListArg) {
+ // XXX: Pseudo-classes with a forgiving selector list argument are
+ // allowed to follow a pseudo-element, but must treat any selector
+ // that is not of the same type as invalid. It doesn't make any
+ // sense, but that's the behavior of other tainted browsers.
+ forceEmptyList = true;
+ } else if (!supportsUserAction || !pseudoClassIsUserAction) {
+ // CSS 4 Selectors says that pseudo-elements can only be followed by
+ // a user action pseudo-class.
+ REPORT_UNEXPECTED_TOKEN(PEPseudoClassNotUserAction);
+ UngetToken();
+ return eSelectorParsingStatus_Error;
+ }
} else if (isPseudoElement &&
(!supportsTreeAbiding || !pseudoElementIsTreeAbiding)) {
REPORT_UNEXPECTED_TOKEN(PEPseudoClassNotUserAction);
@@ -6235,13 +6246,30 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
!!(aFlags & SelectorParsingFlags::eDisallowPseudoElements);
if (!parsingPseudoElement && isPseudoClass) {
aDataMask |= SEL_MASK_PCLASS;
+
+ // Only pseudo-classes with a forgiving selector list argument
+ // are allowed if we're forced to be empty.
+ if ((aFlags & SelectorParsingFlags::eForceEmptyList) &&
+ !pseudoClassHasForgivingSelectorListArg) {
+ if (eCSSToken_Function == mToken.mType) {
+ SkipUntil(')');
+ }
+ return eSelectorParsingStatus_Continue;
+ }
+
if (eCSSToken_Function == mToken.mType) {
nsSelectorParsingStatus parsingStatus;
- // Only the combinators restriction should be passed down the chain.
- SelectorParsingFlags flags =
- (aFlags & SelectorParsingFlags::eDisallowCombinators) ?
- SelectorParsingFlags::eDisallowCombinators :
- SelectorParsingFlags::eNone;
+
+ // Pass only a few parsing flags down the chain.
+ SelectorParsingFlags flags = SelectorParsingFlags::eNone;
+ if (aFlags & SelectorParsingFlags::eDisallowCombinators) {
+ flags |= SelectorParsingFlags::eDisallowCombinators;
+ }
+ if (aFlags & SelectorParsingFlags::eForceEmptyList ||
+ forceEmptyList) {
+ flags |= SelectorParsingFlags::eForceEmptyList;
+ }
+
if (sLegacyNegationPseudoClassEnabled &&
CSSPseudoClassType::negation == pseudoClassType) {
// :not() can't be itself negated
@@ -6801,6 +6829,14 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList,
}
}
+ // Treat every other selector as invalid.
+ if ((aFlags & SelectorParsingFlags::eForceEmptyList) &&
+ (selector->mIDList || selector->mClassList ||
+ selector->mAttrList || selector->mNegations ||
+ !selector->mPseudoClassList)) {
+ return false;
+ }
+
if (parsingStatus == eSelectorParsingStatus_Error) {
return false;
}