Bug 1919347 - Support getComputedStyle() for named view transition pseudo elements if the style is not available. r=view-transitions-reviewers,emilio

First, we have to allow the functional parameter for named view
transition pseudo elements.

In this patch, we fix the case when `getComputedStyle()` resolve the style
lazily (i.e. call `Servo_ResolveStyleLazily()`) if its style is not available.
In this case, we have to make sure the matching function work.

We will make sure `aElement->GetPseudoElement(aPseudo)` work in the next
patch so we can retrieve the computed style from the pseudo elements
directly.

Differential Revision: https://phabricator.services.mozilla.com/D230354
This commit is contained in:
Boris Chiou 2024-11-28 22:19:45 +00:00
parent ced8477ee5
commit c82a2b5c08
8 changed files with 59 additions and 69 deletions

View File

@ -339,7 +339,7 @@ void ViewTransition::SetupTransitionPseudoElements() {
// Let new be a new ::view-transition-new(), with its view transition
// name set to transitionName.
RefPtr<Element> new_ = MakePseudo(
*mDocument, PseudoStyleType::viewTransitionOld, transitionName);
*mDocument, PseudoStyleType::viewTransitionNew, transitionName);
// Append new to imagePair.
imagePair->AppendChildTo(new_, kNotify, IgnoreErrors());
}

View File

@ -38,6 +38,11 @@ nsAtom* nsCSSPseudoElements::GetPseudoAtom(Type aType) {
return nsGkAtoms::GetAtomByIndex(index);
}
static bool IsFunctionalPseudo(PseudoStyleType aType) {
return aType == PseudoStyleType::highlight ||
PseudoStyle::IsNamedViewTransitionPseudoElement(aType);
}
/* static */
Maybe<PseudoStyleRequest> nsCSSPseudoElements::ParsePseudoElement(
const nsAString& aPseudoElement, CSSEnabledState aEnabledState) {
@ -78,7 +83,7 @@ Maybe<PseudoStyleRequest> nsCSSPseudoElements::ParsePseudoElement(
auto type = static_cast<Type>(*index);
RefPtr<nsAtom> functionalPseudoParameter;
if (hasParameter) {
if (type != PseudoStyleType::highlight) {
if (!IsFunctionalPseudo(type)) {
return Nothing();
}
functionalPseudoParameter =
@ -92,6 +97,13 @@ Maybe<PseudoStyleRequest> nsCSSPseudoElements::ParsePseudoElement(
}
return NS_Atomize(Substring(start, end));
}();
// The universal selector is pre-defined and should not be a valid name for
// a named view-transition pseudo element.
if (PseudoStyle::IsNamedViewTransitionPseudoElement(type) &&
functionalPseudoParameter == nsGkAtoms::_asterisk) {
return Nothing();
}
}
if (!haveTwoColons &&

View File

@ -247,6 +247,47 @@ impl PseudoElement {
% endfor
None
}
/// Returns true if this pseudo-element matches the given selector.
pub fn matches(&self, pseudo_selector: &PseudoElement) -> bool {
if *self == *pseudo_selector {
return true;
}
if std::mem::discriminant(self) != std::mem::discriminant(pseudo_selector) {
return false;
}
match (self, pseudo_selector) {
(
&Self::ViewTransitionGroup(ref _name),
&Self::ViewTransitionGroup(ref selector_name),
)
| (
&Self::ViewTransitionImagePair(ref _name),
&Self::ViewTransitionImagePair(ref selector_name),
)
| (
&Self::ViewTransitionOld(ref _name),
&Self::ViewTransitionOld(ref selector_name),
)
| (
&Self::ViewTransitionNew(ref _name),
&Self::ViewTransitionNew(ref selector_name),
) => {
// Named view transition pseudos accept the universal selector as the name, so we
// check it first.
// https://drafts.csswg.org/css-view-transitions-1/#named-view-transition-pseudo
if selector_name.0 == atom!("*") {
return true;
}
// We don't need to check if `*_name == *selector_name` here because we already
// check if the enums are equal above.
false
},
_ => false,
}
}
}
impl ToCss for PseudoElement {

View File

@ -2172,43 +2172,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
None => return false,
};
if pseudo == *pseudo_selector {
return true;
}
if std::mem::discriminant(&pseudo) != std::mem::discriminant(pseudo_selector) {
return false;
}
match (&pseudo, pseudo_selector) {
(
&PseudoElement::ViewTransitionGroup(ref _name),
&PseudoElement::ViewTransitionGroup(ref selector_name),
)
| (
&PseudoElement::ViewTransitionImagePair(ref _name),
&PseudoElement::ViewTransitionImagePair(ref selector_name),
)
| (
&PseudoElement::ViewTransitionOld(ref _name),
&PseudoElement::ViewTransitionOld(ref selector_name),
)
| (
&PseudoElement::ViewTransitionNew(ref _name),
&PseudoElement::ViewTransitionNew(ref selector_name),
) => {
// Named view transition pseudos accept the universal selector as the name, so we
// check it first.
// https://drafts.csswg.org/css-view-transitions-1/#named-view-transition-pseudo
if selector_name.0 == atom!("*") {
return true;
}
// We don't need to check if `*_name == *selector_name` here because we already
// check if the enums are equal above.
false
},
_ => false,
}
pseudo.matches(pseudo_selector)
}
#[inline]

View File

@ -6139,8 +6139,8 @@ pub extern "C" fn Servo_ResolveStyleLazily(
get_functional_pseudo_parameter_atom(functional_pseudo_parameter),
);
let matching_fn = |pseudo: &PseudoElement| match pseudo_element {
Some(ref p) => *pseudo == *p,
let matching_fn = |pseudo_selector: &PseudoElement| match pseudo_element {
Some(ref p) => p.matches(pseudo_selector),
_ => false,
};
@ -6162,7 +6162,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(
/* inherited_styles = */ None,
&stylist,
is_probe,
if pseudo.is_highlight() {
if pseudo.is_highlight() || pseudo.is_named_view_transition() {
Some(&matching_fn)
} else {
None

View File

@ -2,11 +2,6 @@
[:only-child should match because ::view-transition-group is generated for root element only]
expected: FAIL
[:only-child should not match because ::view-transition-group is generated for multiple elements]
expected: FAIL
[:only-child should match because ::view-transition-group is generated for sub element only]
expected: FAIL
[:only-child should not match because ::view-transition-group is generated for multiple sub elements]
expected: FAIL

View File

@ -2,17 +2,6 @@
[:only-child should match because ::view-transition-old is not generated (none to root)]
expected: FAIL
[:only-child should not match because ::view-transition-old is generated (root to root)]
expected: FAIL
[:only-child should not match because ::view-transition-old is generated (element to root)]
expected: FAIL
[:only-child should match because ::view-transition-old is not generated (none to element)]
expected: FAIL
[:only-child should not match because ::view-transition-old is generated (root to element)]
expected: FAIL
[:only-child should not match because ::view-transition-old is generated (element to element)]
expected: FAIL

View File

@ -2,17 +2,6 @@
[:only-child should match because ::view-transition-new is not generated (root to none)]
expected: FAIL
[:only-child should not match because ::view-transition-new is generated (root to root)]
expected: FAIL
[:only-child should not match because ::view-transition-new is generated (root to element)]
expected: FAIL
[:only-child should match because ::view-transition-new is not generated (element to none)]
expected: FAIL
[:only-child should not match because ::view-transition-new is generated (element to root)]
expected: FAIL
[:only-child should not match because ::view-transition-new is generated (element to element)]
expected: FAIL