diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index e6c94d0eb87..e6007abe68a 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -1026,7 +1026,21 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser< sink.push(Component::ExplicitNoNamespace) } QNamePrefix::ExplicitAnyNamespace => { - sink.push(Component::ExplicitAnyNamespace) + match parser.default_namespace() { + // Element type selectors that have no namespace + // component (no namespace separator) represent elements + // without regard to the element's namespace (equivalent + // to "*|") unless a default namespace has been declared + // for namespaced selectors (e.g. in CSS, in the style + // sheet). If a default namespace has been declared, + // such selectors will represent only elements in the + // default namespace. + // -- Selectors ยง 6.1.1 + // So we'll have this act the same as the + // QNamePrefix::ImplicitAnyNamespace case. + None => {}, + Some(_) => sink.push(Component::ExplicitAnyNamespace), + } } QNamePrefix::ImplicitNoNamespace => { unreachable!() // Not returned with in_attr_selector = false @@ -1643,6 +1657,15 @@ pub mod tests { ns_prefixes: HashMap, } + impl DummyParser { + fn default_with_namespace(default_ns: DummyAtom) -> DummyParser { + DummyParser { + default_ns: Some(default_ns), + ns_prefixes: Default::default(), + } + } + } + impl SelectorImpl for DummySelectorImpl { type AttrValue = DummyAtom; type Identifier = DummyAtom; @@ -1732,19 +1755,40 @@ pub mod tests { } } - fn parse<'i>(input: &'i str) -> Result, - ParseError<'i, SelectorParseError<'i, ()>>> { + fn parse<'i>(input: &'i str) + -> Result, ParseError<'i, SelectorParseError<'i, ()>>> { parse_ns(input, &DummyParser::default()) } + fn parse_expected<'i, 'a>(input: &'i str, expected: Option<&'a str>) + -> Result, ParseError<'i, SelectorParseError<'i, ()>>> { + parse_ns_expected(input, &DummyParser::default(), expected) + } + fn parse_ns<'i>(input: &'i str, parser: &DummyParser) - -> Result, - ParseError<'i, SelectorParseError<'i, ()>>> { + -> Result, ParseError<'i, SelectorParseError<'i, ()>>> { + parse_ns_expected(input, parser, None) + } + + fn parse_ns_expected<'i, 'a>( + input: &'i str, + parser: &DummyParser, + expected: Option<&'a str> + ) -> Result, ParseError<'i, SelectorParseError<'i, ()>>> { let mut parser_input = ParserInput::new(input); let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input)); if let Ok(ref selectors) = result { assert_eq!(selectors.0.len(), 1); - assert_eq!(selectors.0[0].to_css_string(), input); + // We can't assume that the serialized parsed selector will equal + // the input; for example, if there is no default namespace, '*|foo' + // should serialize to 'foo'. + assert_eq!( + selectors.0[0].to_css_string(), + match expected { + Some(x) => x, + None => input + } + ); } result } @@ -1783,16 +1827,34 @@ pub mod tests { lower_name: DummyAtom::from("e") })), specificity(0, 0, 1)) )))); - // https://github.com/servo/servo/issues/16020 - assert_eq!(parse("*|e"), Ok(SelectorList::from_vec(vec!( + // When the default namespace is not set, *| should be elided. + // https://github.com/servo/servo/pull/17537 + assert_eq!(parse_expected("*|e", Some("e")), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( - Component::ExplicitAnyNamespace, Component::LocalName(LocalName { name: DummyAtom::from("e"), lower_name: DummyAtom::from("e") }) ), specificity(0, 0, 1)) )))); + // When the default namespace is set, *| should _not_ be elided (as foo + // is no longer equivalent to *|foo--the former is only for foo in the + // default namespace). + // https://github.com/servo/servo/issues/16020 + assert_eq!( + parse_ns( + "*|e", + &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org")) + ), + Ok(SelectorList::from_vec(vec!( + Selector::from_vec(vec!( + Component::ExplicitAnyNamespace, + Component::LocalName(LocalName { + name: DummyAtom::from("e"), + lower_name: DummyAtom::from("e") + }) + ), specificity(0, 0, 1))))) + ); assert_eq!(parse("*"), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( Component::ExplicitUniversalType, @@ -1804,12 +1866,22 @@ pub mod tests { Component::ExplicitUniversalType, ), specificity(0, 0, 0)) )))); - assert_eq!(parse("*|*"), Ok(SelectorList::from_vec(vec!( + assert_eq!(parse_expected("*|*", Some("*")), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( - Component::ExplicitAnyNamespace, Component::ExplicitUniversalType, ), specificity(0, 0, 0)) )))); + assert_eq!( + parse_ns( + "*|*", + &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org")) + ), + Ok(SelectorList::from_vec(vec!( + Selector::from_vec(vec!( + Component::ExplicitAnyNamespace, + Component::ExplicitUniversalType, + ), specificity(0, 0, 0))))) + ); assert_eq!(parse(".foo:lang(en-US)"), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( Component::Class(DummyAtom::from("foo")), @@ -2029,10 +2101,11 @@ pub mod tests { ].into_boxed_slice() )), specificity(0, 0, 0)) )))); - assert_eq!(parse_ns(":not(*|*)", &parser), Ok(SelectorList::from_vec(vec!( + // *| should be elided if there is no default namespace. + // https://github.com/servo/servo/pull/17537 + assert_eq!(parse_ns_expected(":not(*|*)", &parser, Some(":not(*)")), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!(Component::Negation( vec![ - Component::ExplicitAnyNamespace, Component::ExplicitUniversalType, ].into_boxed_slice() )), specificity(0, 0, 0)) @@ -2063,7 +2136,10 @@ pub mod tests { #[test] fn test_universal() { - let selector = &parse("*|*::before").unwrap().0[0]; + let selector = &parse_ns( + "*|*::before", + &DummyParser::default_with_namespace(DummyAtom::from("https://mozilla.org")) + ).unwrap().0[0]; assert!(selector.is_universal()); } 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 index 9f40c3d2635..965e00625c9 100644 --- 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 @@ -1,26 +1,5 @@ [serialize-namespaced-type-selectors.htm] type: testharness - [Type selector with any namespace] - expected: FAIL - - [Universal selector in any namespace] - expected: FAIL - - [Type selector with any namespace followed by class] - expected: FAIL - - [Type selector with any namespace followed by id] - expected: FAIL - - [Type selector with any namespace followed by pseudo class] - expected: FAIL - - [Type selector with any namespace followed by pseudo element] - expected: FAIL - - [Type selector with any namespace followed by attribute selector] - expected: FAIL - [Universal selector followed by class] expected: FAIL @@ -51,27 +30,6 @@ [Universal selector in any namespace followed by attribute selector] expected: FAIL - [Type selector with namespace equal to default namespace] - expected: FAIL - - [Universal selector with namespace equal to default namespace] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by class] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by id] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by pseudo class] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by pseudo element] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by attribute selector] - expected: FAIL - [Universal selector with namespace equal to default namespace followed by class] 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 index 41f502aee9a..ad037e747da 100644 --- a/tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini +++ b/tests/wpt/metadata/cssom/serialize-namespaced-type-selectors.html.ini @@ -1,26 +1,5 @@ [serialize-namespaced-type-selectors.html] type: testharness - [Type selector with any namespace] - expected: FAIL - - [Universal selector in any namespace] - expected: FAIL - - [Type selector with any namespace followed by class] - expected: FAIL - - [Type selector with any namespace followed by id] - expected: FAIL - - [Type selector with any namespace followed by pseudo class] - expected: FAIL - - [Type selector with any namespace followed by pseudo element] - expected: FAIL - - [Type selector with any namespace followed by attribute selector] - expected: FAIL - [Universal selector followed by class] expected: FAIL @@ -51,27 +30,6 @@ [Universal selector in any namespace followed by attribute selector] expected: FAIL - [Type selector with namespace equal to default namespace] - expected: FAIL - - [Universal selector with namespace equal to default namespace] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by class] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by id] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by pseudo class] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by pseudo element] - expected: FAIL - - [Type selector with namespace equal to default namespace followed by attribute selector] - expected: FAIL - [Universal selector with namespace equal to default namespace followed by class] expected: FAIL