Skip to content
Permalink
Browse files

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.
  • Loading branch information...
jyc committed Jul 13, 2017
1 parent bd5ff3b commit 989b70762300334ed87113107eea34bd2611ca20
@@ -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<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 {
type AttrValue = DummyAtom;
type Identifier = DummyAtom;
@@ -1732,19 +1755,40 @@ pub mod tests {
}
}

fn parse<'i>(input: &'i str) -> Result<SelectorList<DummySelectorImpl>,
ParseError<'i, SelectorParseError<'i, ()>>> {
fn parse<'i>(input: &'i str)
-> Result<SelectorList<DummySelectorImpl>, ParseError<'i, SelectorParseError<'i, ()>>> {
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)
-> Result<SelectorList<DummySelectorImpl>,
ParseError<'i, SelectorParseError<'i, ()>>> {
-> Result<SelectorList<DummySelectorImpl>, 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 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());
}

@@ -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

@@ -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

0 comments on commit 989b707

Please sign in to comment.
You can’t perform that action at this time.