mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 11:37:30 +09:00
Issue #1592 - Part 2: Parse ::slotted() pseudo-element as if it were a pseudo-class
- Block slot elements from being matched by ::slotted - Ensure ::slotted() is serialized as a pseudo-element - Add pref to control whether the pseudo-class is enabled
This commit is contained in:
parent
ab63b7b946
commit
77ad970db6
8 changed files with 81 additions and 3 deletions
|
|
@ -915,6 +915,11 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
|
||||||
|
|
||||||
// Append each pseudo-class in the linked list
|
// Append each pseudo-class in the linked list
|
||||||
for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
|
for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
|
||||||
|
// Serialize pseudo-elements that were treated as if they were a
|
||||||
|
// pseudo-class to the two colon syntax.
|
||||||
|
if (nsCSSPseudoClasses::IsHybridPseudoElement(list->mType)) {
|
||||||
|
aString.Append(char16_t(':'));
|
||||||
|
}
|
||||||
nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
|
nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
|
||||||
// This should not be escaped since (a) the pseudo-class string
|
// This should not be escaped since (a) the pseudo-class string
|
||||||
// has a ":" that can't be escaped and (b) all pseudo-classes at
|
// has a ":" that can't be escaped and (b) all pseudo-classes at
|
||||||
|
|
|
||||||
|
|
@ -6121,6 +6121,21 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We handle the ::slotted() pseudo-element as if it it were a pseudo-class.
|
||||||
|
// This is because the spec allows it to be followed by ::after/::before,
|
||||||
|
// but our platform does not have a mechanism to handle multiple
|
||||||
|
// pseudo-elements. It would be tedious to refactor pseudo-element
|
||||||
|
// handling to accommodate for an edge case like this.
|
||||||
|
bool isSlotPseudo = false;
|
||||||
|
if (parsingPseudoElement &&
|
||||||
|
pseudoElementType == CSSPseudoElementType::slotted) {
|
||||||
|
parsingPseudoElement = false;
|
||||||
|
pseudoElementType = CSSPseudoElementType::NotPseudo;
|
||||||
|
pseudoClassType = CSSPseudoClassType::slotted;
|
||||||
|
isSlotPseudo = true;
|
||||||
|
aFlags |= SelectorParsingFlags::eDisallowCombinators;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
isTreePseudo = (pseudoElementType == CSSPseudoElementType::XULTree);
|
isTreePseudo = (pseudoElementType == CSSPseudoElementType::XULTree);
|
||||||
// If a tree pseudo-element is using the function syntax, it will
|
// If a tree pseudo-element is using the function syntax, it will
|
||||||
|
|
@ -6198,6 +6213,8 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool disallowPseudoElements =
|
||||||
|
!!(aFlags & SelectorParsingFlags::eDisallowPseudoElements);
|
||||||
if (!parsingPseudoElement && isPseudoClass) {
|
if (!parsingPseudoElement && isPseudoClass) {
|
||||||
aDataMask |= SEL_MASK_PCLASS;
|
aDataMask |= SEL_MASK_PCLASS;
|
||||||
if (eCSSToken_Function == mToken.mType) {
|
if (eCSSToken_Function == mToken.mType) {
|
||||||
|
|
@ -6222,6 +6239,13 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
||||||
return parsingStatus;
|
return parsingStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (CSSPseudoClassType::slotted == pseudoClassType &&
|
||||||
|
!isSlotPseudo) {
|
||||||
|
// Reject the :slotted() pseudo-class form.
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
|
||||||
|
UngetToken();
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
else if (nsCSSPseudoClasses::HasStringArg(pseudoClassType)) {
|
else if (nsCSSPseudoClasses::HasStringArg(pseudoClassType)) {
|
||||||
parsingStatus =
|
parsingStatus =
|
||||||
ParsePseudoClassWithIdentArg(aSelector, pseudoClassType);
|
ParsePseudoClassWithIdentArg(aSelector, pseudoClassType);
|
||||||
|
|
@ -6233,6 +6257,13 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
||||||
else {
|
else {
|
||||||
MOZ_ASSERT(nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType),
|
MOZ_ASSERT(nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType),
|
||||||
"unexpected pseudo with function token");
|
"unexpected pseudo with function token");
|
||||||
|
// Ensure that the ::slotted() pseudo-element is rejected if
|
||||||
|
// pseudo-elements are disallowed.
|
||||||
|
if (CSSPseudoClassType::slotted == pseudoClassType &&
|
||||||
|
disallowPseudoElements) {
|
||||||
|
UngetToken();
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
parsingStatus = ParsePseudoClassWithSelectorListArg(aSelector,
|
parsingStatus = ParsePseudoClassWithSelectorListArg(aSelector,
|
||||||
pseudoClassType,
|
pseudoClassType,
|
||||||
flags);
|
flags);
|
||||||
|
|
@ -6259,7 +6290,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask,
|
||||||
}
|
}
|
||||||
// Pseudo-elements might not be allowed from appearing
|
// Pseudo-elements might not be allowed from appearing
|
||||||
// (e.g. as an argument to the functional part of a pseudo-class).
|
// (e.g. as an argument to the functional part of a pseudo-class).
|
||||||
if (aFlags & SelectorParsingFlags::eDisallowPseudoElements) {
|
if (disallowPseudoElements) {
|
||||||
UngetToken();
|
UngetToken();
|
||||||
return eSelectorParsingStatus_Error;
|
return eSelectorParsingStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ CSS_PSEUDO_CLASS(nthLastChild, ":nth-last-child", 0, "")
|
||||||
CSS_PSEUDO_CLASS(nthOfType, ":nth-of-type", 0, "")
|
CSS_PSEUDO_CLASS(nthOfType, ":nth-of-type", 0, "")
|
||||||
CSS_PSEUDO_CLASS(nthLastOfType, ":nth-last-of-type", 0, "")
|
CSS_PSEUDO_CLASS(nthLastOfType, ":nth-last-of-type", 0, "")
|
||||||
|
|
||||||
|
// Match slot nodes.
|
||||||
|
CSS_PSEUDO_CLASS(slotted, ":slotted", 0, "layout.css.slotted-pseudo.enabled")
|
||||||
|
|
||||||
// Match nodes that are HTML but not XHTML
|
// Match nodes that are HTML but not XHTML
|
||||||
CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html", 0, "")
|
CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html", 0, "")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,8 @@ bool
|
||||||
nsCSSPseudoClasses::HasSingleSelectorArg(Type aType)
|
nsCSSPseudoClasses::HasSingleSelectorArg(Type aType)
|
||||||
{
|
{
|
||||||
return aType == Type::host ||
|
return aType == Type::host ||
|
||||||
aType == Type::hostContext;
|
aType == Type::hostContext ||
|
||||||
|
aType == Type::slotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -126,7 +127,8 @@ nsCSSPseudoClasses::HasSelectorListArg(Type aType)
|
||||||
aType == Type::mozAny ||
|
aType == Type::mozAny ||
|
||||||
aType == Type::mozAnyPrivate ||
|
aType == Type::mozAnyPrivate ||
|
||||||
aType == Type::host ||
|
aType == Type::host ||
|
||||||
aType == Type::hostContext;
|
aType == Type::hostContext ||
|
||||||
|
aType == Type::slotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -169,3 +171,9 @@ nsCSSPseudoClasses::IsUserActionPseudoClass(Type aType)
|
||||||
aType == Type::active ||
|
aType == Type::active ||
|
||||||
aType == Type::focus;
|
aType == Type::focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
nsCSSPseudoClasses::IsHybridPseudoElement(Type aType)
|
||||||
|
{
|
||||||
|
return aType == Type::slotted;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ public:
|
||||||
static bool HasOptionalSelectorListArg(Type aType);
|
static bool HasOptionalSelectorListArg(Type aType);
|
||||||
static bool IsHiddenFromSerialization(Type aType);
|
static bool IsHiddenFromSerialization(Type aType);
|
||||||
static bool IsUserActionPseudoClass(Type aType);
|
static bool IsUserActionPseudoClass(Type aType);
|
||||||
|
static bool IsHybridPseudoElement(Type aType);
|
||||||
|
|
||||||
// Should only be used on types other than Count and NotPseudoClass
|
// Should only be used on types other than Count and NotPseudoClass
|
||||||
static void PseudoTypeToString(Type aType, nsAString& aString);
|
static void PseudoTypeToString(Type aType, nsAString& aString);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@
|
||||||
CSS_PSEUDO_ELEMENT(after, ":after", CSS_PSEUDO_ELEMENT_IS_CSS2)
|
CSS_PSEUDO_ELEMENT(after, ":after", CSS_PSEUDO_ELEMENT_IS_CSS2)
|
||||||
CSS_PSEUDO_ELEMENT(before, ":before", CSS_PSEUDO_ELEMENT_IS_CSS2)
|
CSS_PSEUDO_ELEMENT(before, ":before", CSS_PSEUDO_ELEMENT_IS_CSS2)
|
||||||
|
|
||||||
|
// XXX: ::slotted() is treated as if it were a pseudo-class, and
|
||||||
|
// is never parsed as a pseudo-element.
|
||||||
|
CSS_PSEUDO_ELEMENT(slotted, ":slotted", 0)
|
||||||
|
|
||||||
CSS_PSEUDO_ELEMENT(backdrop, ":backdrop", 0)
|
CSS_PSEUDO_ELEMENT(backdrop, ":backdrop", 0)
|
||||||
|
|
||||||
CSS_PSEUDO_ELEMENT(firstLetter, ":first-letter",
|
CSS_PSEUDO_ELEMENT(firstLetter, ":first-letter",
|
||||||
|
|
|
||||||
|
|
@ -1963,6 +1963,29 @@ static bool SelectorMatches(Element* aElement,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CSSPseudoClassType::slotted:
|
||||||
|
{
|
||||||
|
// Slot elements cannot be matched.
|
||||||
|
if (aElement->IsHTMLElement(nsGkAtoms::slot)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The current element must have an assigned slot.
|
||||||
|
if (!aElement->GetAssignedSlot()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeMatchContext nodeContext(EventStates(),
|
||||||
|
aNodeMatchContext.mIsRelevantLink);
|
||||||
|
if (!SelectorListMatches(aElement,
|
||||||
|
pseudoClass,
|
||||||
|
nodeContext,
|
||||||
|
aTreeMatchContext)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CSSPseudoClassType::host:
|
case CSSPseudoClassType::host:
|
||||||
{
|
{
|
||||||
ShadowRoot* shadow = aElement->GetShadowRoot();
|
ShadowRoot* shadow = aElement->GetShadowRoot();
|
||||||
|
|
|
||||||
|
|
@ -2557,6 +2557,9 @@ pref("layout.css.legacy-negation-pseudo.enabled", false);
|
||||||
// Is support for the :is() and :where() selectors enabled?
|
// Is support for the :is() and :where() selectors enabled?
|
||||||
pref("layout.css.is-where-pseudo.enabled", true);
|
pref("layout.css.is-where-pseudo.enabled", true);
|
||||||
|
|
||||||
|
// Is support for the ::slotted() selector enabled?
|
||||||
|
pref("layout.css.slotted-pseudo.enabled", true);
|
||||||
|
|
||||||
// Is support for the :scope selector enabled?
|
// Is support for the :scope selector enabled?
|
||||||
pref("layout.css.scope-pseudo.enabled", true);
|
pref("layout.css.scope-pseudo.enabled", true);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue