aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/selectors/parser.rs80
-rw-r--r--tests/wpt/metadata-css/cssom-1_dev/html/serialize-namespaced-type-selectors.htm.ini47
-rw-r--r--tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini47
3 files changed, 77 insertions, 97 deletions
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs
index e6007abe68a..fe4dda0245d 100644
--- a/components/selectors/parser.rs
+++ b/components/selectors/parser.rs
@@ -763,19 +763,93 @@ impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
// NB: A parse-order iterator is a Rev<>, which doesn't expose as_slice(),
// which we need for |split|. So we split by combinators on a match-order
// sequence and then reverse.
- let mut combinators = self.iter_raw_match_order().rev().filter(|x| x.is_combinator());
+
+ let mut combinators = self.iter_raw_match_order().rev().filter(|x| x.is_combinator()).peekable();
let compound_selectors = self.iter_raw_match_order().as_slice().split(|x| x.is_combinator()).rev();
let mut combinators_exhausted = false;
for compound in compound_selectors {
debug_assert!(!combinators_exhausted);
- for item in compound.iter() {
- item.to_css(dest)?;
+
+ // https://drafts.csswg.org/cssom/#serializing-selectors
+
+ if !compound.is_empty() {
+ // 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.
+ let (can_elide_namespace, first_non_namespace) = match &compound[0] {
+ &Component::ExplicitAnyNamespace |
+ &Component::ExplicitNoNamespace |
+ &Component::Namespace(_, _) => (false, 1),
+ &Component::DefaultNamespace(_) => (true, 1),
+ _ => (true, 0),
+ };
+ 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
+ }
+ (_, _) => (),
+ }
+ }
+
+ // 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
+ }
+ }
+ 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.
match combinators.next() {
Some(c) => c.to_css(dest)?,
None => combinators_exhausted = true,
};
+
+ // 4. If this is the last part of the chain of the selector and
+ // there is a pseudo-element, append "::" followed by the name of
+ // the pseudo-element, to s.
+ //
+ // (we handle this above)
}
Ok(())
diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/serialize-namespaced-type-selectors.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/serialize-namespaced-type-selectors.htm.ini
deleted file mode 100644
index 965e00625c9..00000000000
--- a/tests/wpt/metadata-css/cssom-1_dev/html/serialize-namespaced-type-selectors.htm.ini
+++ /dev/null
@@ -1,47 +0,0 @@
-[serialize-namespaced-type-selectors.htm]
- type: testharness
- [Universal selector followed by class]
- expected: FAIL
-
- [Universal selector followed by id]
- expected: FAIL
-
- [Universal selector followed by pseudo class]
- expected: FAIL
-
- [Universal selector followed by pseudo element]
- expected: FAIL
-
- [Universal selector followed by attribute selector]
- expected: FAIL
-
- [Universal selector in any namespace followed by class]
- expected: FAIL
-
- [Universal selector in any namespace followed by id]
- expected: FAIL
-
- [Universal selector in any namespace followed by pseudo class]
- expected: FAIL
-
- [Universal selector in any namespace followed by pseudo element]
- expected: FAIL
-
- [Universal selector in any namespace followed by attribute selector]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by class]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by id]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by pseudo class]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by pseudo element]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by attribute selector]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini b/tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini
deleted file mode 100644
index ad037e747da..00000000000
--- a/tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini
+++ /dev/null
@@ -1,47 +0,0 @@
-[serialize-namespaced-type-selectors.html]
- type: testharness
- [Universal selector followed by class]
- expected: FAIL
-
- [Universal selector followed by id]
- expected: FAIL
-
- [Universal selector followed by pseudo class]
- expected: FAIL
-
- [Universal selector followed by pseudo element]
- expected: FAIL
-
- [Universal selector followed by attribute selector]
- expected: FAIL
-
- [Universal selector in any namespace followed by class]
- expected: FAIL
-
- [Universal selector in any namespace followed by id]
- expected: FAIL
-
- [Universal selector in any namespace followed by pseudo class]
- expected: FAIL
-
- [Universal selector in any namespace followed by pseudo element]
- expected: FAIL
-
- [Universal selector in any namespace followed by attribute selector]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by class]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by id]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by pseudo class]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by pseudo element]
- expected: FAIL
-
- [Universal selector with namespace equal to default namespace followed by attribute selector]
- expected: FAIL
-