Bug 1391169 Part 1: Servo-side change Selector to_css function to handle combinators in between universal selectors.
MozReview-Commit-ID: EyVrSAICPm
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -777,66 +777,70 @@ impl<Impl: SelectorImpl> ToCss for Selec
// 1. If there is only one simple selector in the compound selectors
// which is a universal selector, append the result of
// serializing the universal selector to s.
//
// Check if `!compound.empty()` first--this can happen if we have
// something like `... > ::before`, because we store `>` and `::`
// both as combinators internally.
//
- // If we are in this case, we continue to the next iteration of the
- // `for compound in compound_selectors` loop.
+ // If we are in this case, after we have serialized the universal
+ // selector, we skip Step 2 and continue with the algorithm.
let (can_elide_namespace, first_non_namespace) = match &compound[0] {
&Component::ExplicitAnyNamespace |
&Component::ExplicitNoNamespace |
&Component::Namespace(_, _) => (false, 1),
&Component::DefaultNamespace(_) => (true, 1),
_ => (true, 0),
};
+ let mut perform_step_2 = true;
if first_non_namespace == compound.len() - 1 {
match (combinators.peek(), &compound[first_non_namespace]) {
// We have to be careful here, because if there is a pseudo
// element "combinator" there isn't really just the one
// simple selector. Technically this compound selector
// contains the pseudo element selector as
// well--Combinator::PseudoElement doesn't exist in the
// spec.
(Some(&&Component::Combinator(Combinator::PseudoElement)), _) => (),
(_, &Component::ExplicitUniversalType) => {
// Iterate over everything so we serialize the namespace
// too.
for simple in compound.iter() {
simple.to_css(dest)?;
}
- continue
+ // Skip step 2, which is an "otherwise".
+ perform_step_2 = false;
}
(_, _) => (),
}
}
// 2. Otherwise, for each simple selector in the compound selectors
// that is not a universal selector of which the namespace prefix
// maps to a namespace that is not the default namespace
// serialize the simple selector and append the result to s.
//
// See https://github.com/w3c/csswg-drafts/issues/1606, which is
// proposing to change this to match up with the behavior asserted
// in cssom/serialize-namespaced-type-selectors.html, which the
// following code tries to match.
- for simple in compound.iter() {
- if let Component::ExplicitUniversalType = *simple {
- // Can't have a namespace followed by a pseudo-element
- // selector followed by a universal selector in the same
- // compound selector, so we don't have to worry about the
- // real namespace being in a different `compound`.
- if can_elide_namespace {
- continue
+ if perform_step_2 {
+ for simple in compound.iter() {
+ if let Component::ExplicitUniversalType = *simple {
+ // Can't have a namespace followed by a pseudo-element
+ // selector followed by a universal selector in the same
+ // compound selector, so we don't have to worry about the
+ // real namespace being in a different `compound`.
+ if can_elide_namespace {
+ continue
+ }
}
+ simple.to_css(dest)?;
}
- simple.to_css(dest)?;
}
}
// 3. If this is not the last part of the chain of the selector
// append a single SPACE (U+0020), followed by the combinator
// ">", "+", "~", ">>", "||", as appropriate, followed by another
// single SPACE (U+0020) if the combinator was not whitespace, to
// s.
--- a/servo/tests/unit/style/parsing/selectors.rs
+++ b/servo/tests/unit/style/parsing/selectors.rs
@@ -20,9 +20,11 @@ fn parse_selector<'i, 't>(input: &mut Pa
}
#[test]
fn test_selectors() {
assert_roundtrip!(parse_selector, "div");
assert_roundtrip!(parse_selector, "svg|circle");
assert_roundtrip!(parse_selector, "p:before", "p::before");
assert_roundtrip!(parse_selector, "[border=\"0\"]:-servo-nonzero-border ~ ::-servo-details-summary");
+ assert_roundtrip!(parse_selector, "* > *");
+ assert_roundtrip!(parse_selector, "*|* + *", "* + *");
}