mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Elide the explicit any namespace prefix when lacking default namespace.
Once again it seems we don't need to preserve the original prefix name, and this lets to_css serialize to the shortest form when there is no default namespace and the *| prefix is used. Selectors § 6.1.1 says: 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. Then if there is no default namespace, *| (which we write as QNamePrefix::ExplicitAnyNamespace) is equivalent to what we write as QNamePrefix::ImplicitAnyNamespace; the latter has a shorter serialization, so we should use that.
This commit is contained in:
parent
bd5ff3b4ce
commit
989b707623
3 changed files with 90 additions and 98 deletions
|
@ -1026,7 +1026,21 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser<
|
||||||
sink.push(Component::ExplicitNoNamespace)
|
sink.push(Component::ExplicitNoNamespace)
|
||||||
}
|
}
|
||||||
QNamePrefix::ExplicitAnyNamespace => {
|
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 => {
|
QNamePrefix::ImplicitNoNamespace => {
|
||||||
unreachable!() // Not returned with in_attr_selector = false
|
unreachable!() // Not returned with in_attr_selector = false
|
||||||
|
@ -1643,6 +1657,15 @@ pub mod tests {
|
||||||
ns_prefixes: HashMap<DummyAtom, DummyAtom>,
|
ns_prefixes: HashMap<DummyAtom, DummyAtom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DummyParser {
|
||||||
|
fn default_with_namespace(default_ns: DummyAtom) -> DummyParser {
|
||||||
|
DummyParser {
|
||||||
|
default_ns: Some(default_ns),
|
||||||
|
ns_prefixes: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SelectorImpl for DummySelectorImpl {
|
impl SelectorImpl for DummySelectorImpl {
|
||||||
type AttrValue = DummyAtom;
|
type AttrValue = DummyAtom;
|
||||||
type Identifier = DummyAtom;
|
type Identifier = DummyAtom;
|
||||||
|
@ -1732,19 +1755,40 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse<'i>(input: &'i str) -> Result<SelectorList<DummySelectorImpl>,
|
fn parse<'i>(input: &'i str)
|
||||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
-> Result<SelectorList<DummySelectorImpl>, ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
parse_ns(input, &DummyParser::default())
|
parse_ns(input, &DummyParser::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_expected<'i, 'a>(input: &'i str, expected: Option<&'a str>)
|
||||||
|
-> Result<SelectorList<DummySelectorImpl>, ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
|
parse_ns_expected(input, &DummyParser::default(), expected)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_ns<'i>(input: &'i str, parser: &DummyParser)
|
fn parse_ns<'i>(input: &'i str, parser: &DummyParser)
|
||||||
-> Result<SelectorList<DummySelectorImpl>,
|
-> Result<SelectorList<DummySelectorImpl>, ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
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<SelectorList<DummySelectorImpl>, ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
let mut parser_input = ParserInput::new(input);
|
let mut parser_input = ParserInput::new(input);
|
||||||
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
||||||
if let Ok(ref selectors) = result {
|
if let Ok(ref selectors) = result {
|
||||||
assert_eq!(selectors.0.len(), 1);
|
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
|
result
|
||||||
}
|
}
|
||||||
|
@ -1783,16 +1827,34 @@ pub mod tests {
|
||||||
lower_name: DummyAtom::from("e")
|
lower_name: DummyAtom::from("e")
|
||||||
})), specificity(0, 0, 1))
|
})), specificity(0, 0, 1))
|
||||||
))));
|
))));
|
||||||
// https://github.com/servo/servo/issues/16020
|
// When the default namespace is not set, *| should be elided.
|
||||||
assert_eq!(parse("*|e"), Ok(SelectorList::from_vec(vec!(
|
// https://github.com/servo/servo/pull/17537
|
||||||
|
assert_eq!(parse_expected("*|e", Some("e")), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
Component::ExplicitAnyNamespace,
|
|
||||||
Component::LocalName(LocalName {
|
Component::LocalName(LocalName {
|
||||||
name: DummyAtom::from("e"),
|
name: DummyAtom::from("e"),
|
||||||
lower_name: DummyAtom::from("e")
|
lower_name: DummyAtom::from("e")
|
||||||
})
|
})
|
||||||
), specificity(0, 0, 1))
|
), 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!(
|
assert_eq!(parse("*"), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
|
@ -1804,12 +1866,22 @@ pub mod tests {
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
), specificity(0, 0, 0))
|
), 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!(
|
Selector::from_vec(vec!(
|
||||||
Component::ExplicitAnyNamespace,
|
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
), specificity(0, 0, 0))
|
), 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!(
|
assert_eq!(parse(".foo:lang(en-US)"), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
Component::Class(DummyAtom::from("foo")),
|
Component::Class(DummyAtom::from("foo")),
|
||||||
|
@ -2029,10 +2101,11 @@ pub mod tests {
|
||||||
].into_boxed_slice()
|
].into_boxed_slice()
|
||||||
)), specificity(0, 0, 0))
|
)), 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(
|
Selector::from_vec(vec!(Component::Negation(
|
||||||
vec![
|
vec![
|
||||||
Component::ExplicitAnyNamespace,
|
|
||||||
Component::ExplicitUniversalType,
|
Component::ExplicitUniversalType,
|
||||||
].into_boxed_slice()
|
].into_boxed_slice()
|
||||||
)), specificity(0, 0, 0))
|
)), specificity(0, 0, 0))
|
||||||
|
@ -2063,7 +2136,10 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_universal() {
|
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());
|
assert!(selector.is_universal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,5 @@
|
||||||
[serialize-namespaced-type-selectors.htm]
|
[serialize-namespaced-type-selectors.htm]
|
||||||
type: testharness
|
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]
|
[Universal selector followed by class]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -51,27 +30,6 @@
|
||||||
[Universal selector in any namespace followed by attribute selector]
|
[Universal selector in any namespace followed by attribute selector]
|
||||||
expected: FAIL
|
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]
|
[Universal selector with namespace equal to default namespace followed by class]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,5 @@
|
||||||
[serialize-namespaced-type-selectors.html]
|
[serialize-namespaced-type-selectors.html]
|
||||||
type: testharness
|
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]
|
[Universal selector followed by class]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -51,27 +30,6 @@
|
||||||
[Universal selector in any namespace followed by attribute selector]
|
[Universal selector in any namespace followed by attribute selector]
|
||||||
expected: FAIL
|
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]
|
[Universal selector with namespace equal to default namespace followed by class]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue