diff --git a/dom/view-transitions/ViewTransition.cpp b/dom/view-transitions/ViewTransition.cpp index f3175cba7428..a2e4e7d87de6 100644 --- a/dom/view-transitions/ViewTransition.cpp +++ b/dom/view-transitions/ViewTransition.cpp @@ -339,7 +339,7 @@ void ViewTransition::SetupTransitionPseudoElements() { // Let new be a new ::view-transition-new(), with its view transition // name set to transitionName. RefPtr new_ = MakePseudo( - *mDocument, PseudoStyleType::viewTransitionOld, transitionName); + *mDocument, PseudoStyleType::viewTransitionNew, transitionName); // Append new to imagePair. imagePair->AppendChildTo(new_, kNotify, IgnoreErrors()); } diff --git a/layout/style/nsCSSPseudoElements.cpp b/layout/style/nsCSSPseudoElements.cpp index bad58daae1e3..bbc0e419e53a 100644 --- a/layout/style/nsCSSPseudoElements.cpp +++ b/layout/style/nsCSSPseudoElements.cpp @@ -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 nsCSSPseudoElements::ParsePseudoElement( const nsAString& aPseudoElement, CSSEnabledState aEnabledState) { @@ -78,7 +83,7 @@ Maybe nsCSSPseudoElements::ParsePseudoElement( auto type = static_cast(*index); RefPtr functionalPseudoParameter; if (hasParameter) { - if (type != PseudoStyleType::highlight) { + if (!IsFunctionalPseudo(type)) { return Nothing(); } functionalPseudoParameter = @@ -92,6 +97,13 @@ Maybe 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 && diff --git a/servo/components/style/gecko/pseudo_element_definition.mako.rs b/servo/components/style/gecko/pseudo_element_definition.mako.rs index f2097997936a..a143a2b72624 100644 --- a/servo/components/style/gecko/pseudo_element_definition.mako.rs +++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs @@ -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 { diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs index 7b34aef59bb4..4101d31dc11c 100644 --- a/servo/components/style/gecko/wrapper.rs +++ b/servo/components/style/gecko/wrapper.rs @@ -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] diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 64724887dfe6..22e45582d621 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -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 diff --git a/testing/web-platform/meta/css/css-view-transitions/only-child-group.html.ini b/testing/web-platform/meta/css/css-view-transitions/only-child-group.html.ini index 2d4d15c6541e..a5777b092f29 100644 --- a/testing/web-platform/meta/css/css-view-transitions/only-child-group.html.ini +++ b/testing/web-platform/meta/css/css-view-transitions/only-child-group.html.ini @@ -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 diff --git a/testing/web-platform/meta/css/css-view-transitions/only-child-new.html.ini b/testing/web-platform/meta/css/css-view-transitions/only-child-new.html.ini index fb8e0a195aef..e105495d6f43 100644 --- a/testing/web-platform/meta/css/css-view-transitions/only-child-new.html.ini +++ b/testing/web-platform/meta/css/css-view-transitions/only-child-new.html.ini @@ -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 diff --git a/testing/web-platform/meta/css/css-view-transitions/only-child-old.html.ini b/testing/web-platform/meta/css/css-view-transitions/only-child-old.html.ini index 1c44e4ee2c99..28f3029a50c7 100644 --- a/testing/web-platform/meta/css/css-view-transitions/only-child-old.html.ini +++ b/testing/web-platform/meta/css/css-view-transitions/only-child-old.html.ini @@ -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