::parse(&parser, input)
+ .map_err(|_| input.new_custom_error(()))?;
+
+ #[cfg(feature = "gecko")]
+ {
+ use selectors::parser::Component;
+ use selector_parser::PseudoElement;
+
+ let has_any_unknown_webkit_pseudo =
+ selector.has_pseudo_element() &&
+ selector.iter_raw_match_order().any(|component| {
+ matches!(
+ *component,
+ Component::PseudoElement(PseudoElement::UnknownWebkit(..))
+ )
+ });
+ if has_any_unknown_webkit_pseudo {
+ return Err(input.new_custom_error(()));
+ }
+ }
+
+ Ok(())
+ }).is_ok()
+ }
+}
+
#[derive(Clone, Debug)]
/// A possibly-invalid property declaration
pub struct Declaration(pub String);
@@ -313,21 +412,20 @@ impl Declaration {
let mut input = ParserInput::new(&self.0);
let mut input = Parser::new(&mut input);
- input
- .parse_entirely(|input| -> Result<(), CssParseError<()>> {
- let prop = input.expect_ident_cloned().unwrap();
- input.expect_colon().unwrap();
+ input.parse_entirely(|input| -> Result<(), CssParseError<()>> {
+ let prop = input.expect_ident_cloned().unwrap();
+ input.expect_colon().unwrap();
- let id =
- PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
+ let id =
+ PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
- let mut declarations = SourcePropertyDeclaration::new();
- input.parse_until_before(Delimiter::Bang, |input| {
- PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
- .map_err(|_| input.new_custom_error(()))
- })?;
- let _ = input.try(parse_important);
- Ok(())
- }).is_ok()
+ let mut declarations = SourcePropertyDeclaration::new();
+ input.parse_until_before(Delimiter::Bang, |input| {
+ PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
+ .map_err(|_| input.new_custom_error(()))
+ })?;
+ let _ = input.try(parse_important);
+ Ok(())
+ }).is_ok()
}
}
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
index 0569ecd199ad..63fe0f7759aa 100644
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -4499,24 +4499,26 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
let condition = unsafe { cond.as_ref().unwrap().as_str_unchecked() };
let mut input = ParserInput::new(&condition);
let mut input = Parser::new(&mut input);
- let cond = input.parse_entirely(|i| parse_condition_or_declaration(i));
- if let Ok(cond) = cond {
- let url_data = unsafe { dummy_url_data() };
- // NOTE(emilio): The supports API is not associated to any stylesheet,
- // so the fact that there is no namespace map here is fine.
- let context = ParserContext::new_for_cssom(
- url_data,
- Some(CssRuleType::Style),
- ParsingMode::DEFAULT,
- QuirksMode::NoQuirks,
- None,
- None,
- );
+ let cond = match input.parse_entirely(parse_condition_or_declaration) {
+ Ok(c) => c,
+ Err(..) => return false,
+ };
- cond.eval(&context)
- } else {
- false
- }
+ let url_data = unsafe { dummy_url_data() };
+
+ // NOTE(emilio): The supports API is not associated to any stylesheet,
+ // so the fact that there is no namespace map here is fine.
+ let context = ParserContext::new_for_cssom(
+ url_data,
+ Some(CssRuleType::Style),
+ ParsingMode::DEFAULT,
+ QuirksMode::NoQuirks,
+ None,
+ None,
+ );
+
+ let namespaces = Default::default();
+ cond.eval(&context, &namespaces)
}
#[no_mangle]
diff --git a/testing/web-platform/tests/css/css-conditional/at-supports-040.html b/testing/web-platform/tests/css/css-conditional/at-supports-040.html
new file mode 100644
index 000000000000..6c4a58f346ba
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/at-supports-040.html
@@ -0,0 +1,18 @@
+
+CSS Conditional Test: @supports selector() with pseudo-elements.
+
+
+
+
+
+Test passes if there is a filled green square and no red.
+
diff --git a/testing/web-platform/tests/css/css-conditional/at-supports-041.html b/testing/web-platform/tests/css/css-conditional/at-supports-041.html
new file mode 100644
index 000000000000..804fb3c38353
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/at-supports-041.html
@@ -0,0 +1,18 @@
+
+CSS Conditional Test: @supports selector() with -webkit- unknown pseudo-elements and negation.
+
+
+
+
+
+Test passes if there is a filled green square and no red.
+
diff --git a/testing/web-platform/tests/css/css-conditional/at-supports-042.html b/testing/web-platform/tests/css/css-conditional/at-supports-042.html
new file mode 100644
index 000000000000..47241f37a357
--- /dev/null
+++ b/testing/web-platform/tests/css/css-conditional/at-supports-042.html
@@ -0,0 +1,18 @@
+
+CSS Conditional Test: @supports selector() with multiple selectors doesn't work.
+
+
+
+
+
+Test passes if there is a filled green square and no red.
+
diff --git a/testing/web-platform/tests/css/cssom/CSS.html b/testing/web-platform/tests/css/cssom/CSS.html
index fd2966a104c0..7d558f04466f 100644
--- a/testing/web-platform/tests/css/cssom/CSS.html
+++ b/testing/web-platform/tests/css/cssom/CSS.html
@@ -35,4 +35,12 @@
assert_equals(CSS.supports("width", "blah"), false, "CSS.supports: two argument form fails for invalid value");
assert_equals(CSS.supports("--foo", "blah"), true, "CSS.supports: two argument form succeeds for custom property");
}, "CSS.supports, two argument form");
+ test(function () {
+ assert_equals(CSS.supports("selector(div)"), true, "CSS.supports: selector() function accepts a selector");
+ assert_equals(CSS.supports("selector(div, div)"), false, "CSS.supports: selector() function doesn't accept a selector list");
+ assert_equals(CSS.supports("selector(::-webkit-unknown-pseudo-element)"), false, "CSS.supports: selector() function rejects unknown webkit pseudo-elements.");
+ assert_equals(CSS.supports("selector(::before)"), true, "CSS.supports: selector() function accepts known pseudo-elements");
+ assert_equals(CSS.supports("selector(div + .c)"), true, "CSS.supports: selector() with simple combinators");
+ assert_equals(CSS.supports("selector(div | .c)"), false, "CSS.supports: selector() with unknown combinators");
+ }, "CSS.supports, selector function");