aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-05-16 20:03:53 -0500
committerGitHub <noreply@github.com>2017-05-16 20:03:53 -0500
commitc96245898418ff91de6fd51edca288ecace44d2b (patch)
treec28887c36ec05ac94fda0c1a8490c53a536bc3e1
parent1312ab2b284c1a988c5029e1ec28ee9f3ea5e912 (diff)
parent685b9efed645871877ad83ae3f3e51f9ca9af94d (diff)
downloadservo-c96245898418ff91de6fd51edca288ecace44d2b.tar.gz
servo-c96245898418ff91de6fd51edca288ecace44d2b.zip
Auto merge of #16890 - servo:qname, r=emilio
Fix serialization of namespace and universal selectors Fix #16017 Fix #16020 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16890) <!-- Reviewable:end -->
-rw-r--r--components/selectors/matching.rs16
-rw-r--r--components/selectors/parser.rs352
-rw-r--r--components/style/stylist.rs4
-rw-r--r--tests/unit/style/stylesheets.rs25
-rw-r--r--tests/unit/style/stylist.rs4
5 files changed, 313 insertions, 88 deletions
diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs
index ebc31fa7b53..c4e19f47fd3 100644
--- a/components/selectors/matching.rs
+++ b/components/selectors/matching.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use bloom::BloomFilter;
use parser::{CaseSensitivity, Combinator, ComplexSelector, Component, LocalName};
-use parser::{Selector, SelectorInner, SelectorIter};
+use parser::{Selector, SelectorInner, SelectorIter, SelectorImpl};
use std::borrow::Borrow;
use tree::Element;
@@ -310,8 +310,18 @@ fn matches_simple_selector<E, F>(
let name = if element.is_html_element_in_html_document() { lower_name } else { name };
element.get_local_name() == name.borrow()
}
- Component::Namespace(ref namespace) => {
- element.get_namespace() == namespace.url.borrow()
+ Component::ExplicitUniversalType |
+ Component::ExplicitAnyNamespace => {
+ true
+ }
+ Component::Namespace(_, ref url) |
+ Component::DefaultNamespace(ref url) => {
+ element.get_namespace() == url.borrow()
+ }
+ Component::ExplicitNoNamespace => {
+ // Rust type’s default, not default namespace
+ let empty_string = <E::Impl as SelectorImpl>::NamespaceUrl::default();
+ element.get_namespace() == empty_string.borrow()
}
// TODO: case-sensitivity depends on the document type and quirks mode
Component::ID(ref id) => {
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs
index 82571d9bd5e..34ed4418b3d 100644
--- a/components/selectors/parser.rs
+++ b/components/selectors/parser.rs
@@ -182,6 +182,18 @@ pub struct Selector<Impl: SelectorImpl> {
pub specificity: u32,
}
+impl<Impl: SelectorImpl> Selector<Impl> {
+ /// Whether this selector (pseudo-element part excluded) matches every element.
+ ///
+ /// Used for "pre-computed" pseudo-elements in components/style/stylist.rs
+ pub fn is_universal(&self) -> bool {
+ self.inner.complex.iter_raw().all(|c| matches!(*c,
+ Component::ExplicitUniversalType |
+ Component::ExplicitAnyNamespace
+ ))
+ }
+}
+
pub trait SelectorMethods {
type Impl: SelectorImpl;
@@ -431,10 +443,17 @@ impl Combinator {
#[derive(Eq, PartialEq, Clone)]
pub enum Component<Impl: SelectorImpl> {
Combinator(Combinator),
+
+ ExplicitAnyNamespace,
+ ExplicitNoNamespace,
+ DefaultNamespace(Impl::NamespaceUrl),
+ Namespace(Impl::NamespacePrefix, Impl::NamespaceUrl),
+
+ ExplicitUniversalType,
+ LocalName(LocalName<Impl>),
+
ID(Impl::Identifier),
Class(Impl::ClassName),
- LocalName(LocalName<Impl>),
- Namespace(Namespace<Impl>),
// Attribute selectors
AttrExists(AttrSelector<Impl>), // [foo]
@@ -489,8 +508,9 @@ impl<Impl: SelectorImpl> Component<Impl> {
None
}
},
- Component::Namespace(ref namespace) => {
- Some(namespace.url.precomputed_hash())
+ Component::DefaultNamespace(ref url) |
+ Component::Namespace(_, ref url) => {
+ Some(url.precomputed_hash())
},
Component::ID(ref id) => {
Some(id.precomputed_hash())
@@ -646,7 +666,15 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
display_to_css_identifier(s, dest)
}
LocalName(ref s) => s.to_css(dest),
- Namespace(ref ns) => ns.to_css(dest),
+ ExplicitUniversalType => dest.write_char('*'),
+
+ DefaultNamespace(_) => Ok(()),
+ ExplicitNoNamespace => dest.write_char('|'),
+ ExplicitAnyNamespace => dest.write_str("*|"),
+ Namespace(ref prefix, _) => {
+ display_to_css_identifier(prefix, dest)?;
+ dest.write_char('|')
+ }
// Attribute selectors
AttrExists(ref a) => {
@@ -673,7 +701,7 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
// Pseudo-classes
Negation(ref arg) => {
dest.write_str(":not(")?;
- debug_assert!(arg.len() <= 1 || (arg.len() == 2 && matches!(arg[0], Component::Namespace(_))));
+ debug_assert!(single_simple_selector(arg));
for component in arg.iter() {
component.to_css(dest)?;
}
@@ -832,10 +860,12 @@ fn complex_selector_specificity<Impl>(selector: &ComplexSelector<Impl>)
where Impl: SelectorImpl {
match *simple_selector {
Component::Combinator(..) => unreachable!(),
- Component::LocalName(..) =>
- specificity.element_selectors += 1,
- Component::ID(..) =>
- specificity.id_selectors += 1,
+ Component::LocalName(..) => {
+ specificity.element_selectors += 1
+ }
+ Component::ID(..) => {
+ specificity.id_selectors += 1
+ }
Component::Class(..) |
Component::AttrExists(..) |
Component::AttrEqual(..) |
@@ -859,10 +889,16 @@ fn complex_selector_specificity<Impl>(selector: &ComplexSelector<Impl>)
Component::NthLastOfType(..) |
Component::FirstOfType | Component::LastOfType |
Component::OnlyOfType |
- Component::NonTSPseudoClass(..) =>
- specificity.class_like_selectors += 1,
-
- Component::Namespace(..) => (),
+ Component::NonTSPseudoClass(..) => {
+ specificity.class_like_selectors += 1
+ }
+ Component::ExplicitUniversalType |
+ Component::ExplicitAnyNamespace |
+ Component::ExplicitNoNamespace |
+ Component::DefaultNamespace(..) |
+ Component::Namespace(..) => {
+ // Does not affect specificity
+ }
Component::Negation(ref negated) => {
for ss in negated.iter() {
simple_selector_specificity(&ss, specificity);
@@ -990,10 +1026,22 @@ fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mu
None => Ok(false),
Some((namespace, local_name)) => {
match namespace {
- NamespaceConstraint::Specific(ns) => {
- sequence.push(Component::Namespace(ns))
- },
- NamespaceConstraint::Any => (),
+ QNamePrefix::ImplicitAnyNamespace => {}
+ QNamePrefix::ImplicitDefaultNamespace(url) => {
+ sequence.push(Component::DefaultNamespace(url))
+ }
+ QNamePrefix::ExplicitNamespace(prefix, url) => {
+ sequence.push(Component::Namespace(prefix, url))
+ }
+ QNamePrefix::ExplicitNoNamespace => {
+ sequence.push(Component::ExplicitNoNamespace)
+ }
+ QNamePrefix::ExplicitAnyNamespace => {
+ sequence.push(Component::ExplicitAnyNamespace)
+ }
+ QNamePrefix::ImplicitNoNamespace => {
+ unreachable!() // Not returned with in_attr_selector = false
+ }
}
match local_name {
Some(name) => {
@@ -1002,7 +1050,9 @@ fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mu
name: from_cow_str(name),
}))
}
- None => (),
+ None => {
+ sequence.push(Component::ExplicitUniversalType)
+ }
}
Ok(true)
}
@@ -1015,22 +1065,29 @@ enum SimpleSelectorParseResult<Impl: SelectorImpl> {
PseudoElement(Impl::PseudoElementSelector),
}
+#[derive(Debug)]
+enum QNamePrefix<Impl: SelectorImpl> {
+ ImplicitNoNamespace, // `foo` in attr selectors
+ ImplicitAnyNamespace, // `foo` in type selectors, without a default ns
+ ImplicitDefaultNamespace(Impl::NamespaceUrl), // `foo` in type selectors, with a default ns
+ ExplicitNoNamespace, // `|foo`
+ ExplicitAnyNamespace, // `*|foo`
+ ExplicitNamespace(Impl::NamespacePrefix, Impl::NamespaceUrl), // `prefix|foo`
+}
+
/// * `Err(())`: Invalid selector, abort
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
/// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
fn parse_qualified_name<'i, 't, P, Impl>
(parser: &P, input: &mut CssParser<'i, 't>,
in_attr_selector: bool)
- -> Result<Option<(NamespaceConstraint<Impl>, Option<Cow<'i, str>>)>, ()>
+ -> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>, ()>
where P: Parser<Impl=Impl>, Impl: SelectorImpl
{
let default_namespace = |local_name| {
let namespace = match parser.default_namespace() {
- Some(url) => NamespaceConstraint::Specific(Namespace {
- prefix: None,
- url: url
- }),
- None => NamespaceConstraint::Any,
+ Some(url) => QNamePrefix::ImplicitDefaultNamespace(url),
+ None => QNamePrefix::ImplicitAnyNamespace,
};
Ok(Some((namespace, local_name)))
};
@@ -1056,15 +1113,12 @@ fn parse_qualified_name<'i, 't, P, Impl>
let prefix = from_cow_str(value);
let result = parser.namespace_for_prefix(&prefix);
let url = result.ok_or(())?;
- explicit_namespace(input, NamespaceConstraint::Specific(Namespace {
- prefix: Some(prefix),
- url: url
- }))
+ explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
},
_ => {
input.reset(position);
if in_attr_selector {
- Ok(Some((NamespaceConstraint::Specific(Default::default()), Some(value))))
+ Ok(Some((QNamePrefix::ImplicitNoNamespace, Some(value))))
} else {
default_namespace(Some(value))
}
@@ -1074,7 +1128,9 @@ fn parse_qualified_name<'i, 't, P, Impl>
Ok(Token::Delim('*')) => {
let position = input.position();
match input.next_including_whitespace() {
- Ok(Token::Delim('|')) => explicit_namespace(input, NamespaceConstraint::Any),
+ Ok(Token::Delim('|')) => {
+ explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
+ }
_ => {
input.reset(position);
if in_attr_selector {
@@ -1086,7 +1142,7 @@ fn parse_qualified_name<'i, 't, P, Impl>
}
},
Ok(Token::Delim('|')) => {
- explicit_namespace(input, NamespaceConstraint::Specific(Default::default()))
+ explicit_namespace(input, QNamePrefix::ExplicitNoNamespace)
}
_ => {
input.reset(position);
@@ -1104,7 +1160,28 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
None => return Err(()),
Some((_, None)) => unreachable!(),
Some((namespace, Some(local_name))) => AttrSelector {
- namespace: namespace,
+ namespace: match namespace {
+ QNamePrefix::ImplicitNoNamespace |
+ QNamePrefix::ExplicitNoNamespace => {
+ NamespaceConstraint::Specific(Namespace {
+ prefix: None,
+ url: Impl::NamespaceUrl::default(),
+ })
+ }
+ QNamePrefix::ExplicitNamespace(prefix, url) => {
+ NamespaceConstraint::Specific(Namespace {
+ prefix: Some(prefix),
+ url: url,
+ })
+ }
+ QNamePrefix::ExplicitAnyNamespace => {
+ NamespaceConstraint::Any
+ }
+ QNamePrefix::ImplicitAnyNamespace |
+ QNamePrefix::ImplicitDefaultNamespace(_) => {
+ unreachable!() // Not returned with in_attr_selector = true
+ }
+ },
lower_name: from_ascii_lowercase(&local_name),
name: from_cow_str(local_name),
},
@@ -1187,17 +1264,33 @@ fn parse_negation<P, Impl>(parser: &P,
let mut v = ParseVec::new();
parse_compound_selector(parser, input, &mut v, /* inside_negation = */ true)?;
- let allow = v.len() <= 1 ||
- (v.len() == 2 && matches!(v[0], Component::Namespace(_)) &&
- matches!(v[1], Component::LocalName(_)));
-
- if allow {
+ if single_simple_selector(&v) {
Ok(Component::Negation(v.into_vec().into_boxed_slice()))
} else {
Err(())
}
}
+// A single type selector can be represented as two components
+fn single_simple_selector<Impl: SelectorImpl>(v: &[Component<Impl>]) -> bool {
+ v.len() == 1 || (
+ v.len() == 2 &&
+ match v[1] {
+ Component::LocalName(_) | Component::ExplicitUniversalType => {
+ debug_assert!(matches!(v[0],
+ Component::ExplicitAnyNamespace |
+ Component::ExplicitNoNamespace |
+ Component::DefaultNamespace(_) |
+ Component::Namespace(..)
+ ));
+ true
+ }
+ _ => false,
+ }
+ )
+
+}
+
/// simple_selector_sequence
/// : [ type_selector | universal ] [ HASH | class | attrib | pseudo | negation ]*
/// | [ HASH | class | attrib | pseudo | negation ]+
@@ -1228,10 +1321,7 @@ fn parse_compound_selector<P, Impl>(
//
// Note that this doesn't apply to :not() and :matches() per spec.
if !inside_negation {
- sequence.push(Component::Namespace(Namespace {
- prefix: None,
- url: url
- }));
+ sequence.push(Component::DefaultNamespace(url))
}
}
} else {
@@ -1554,13 +1644,61 @@ pub mod tests {
assert_eq!(parse(":lang(4)"), Err(())) ;
assert_eq!(parse(":lang(en US)"), Err(())) ;
assert_eq!(parse("EeÉ"), Ok(SelectorList(vec!(Selector {
- inner: SelectorInner::from_vec(vec!(Component::LocalName(LocalName {
+ inner: SelectorInner::from_vec(vec!(
+ Component::LocalName(LocalName {
name: DummyAtom::from("EeÉ"),
- lower_name: DummyAtom::from("eeÉ") })),
- ),
+ lower_name: DummyAtom::from("eeÉ")
+ }),
+ )),
pseudo_element: None,
specificity: specificity(0, 0, 1),
}))));
+ assert_eq!(parse("|e"), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::ExplicitNoNamespace,
+ Component::LocalName(LocalName {
+ name: DummyAtom::from("e"),
+ lower_name: DummyAtom::from("e")
+ }),
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 1),
+ }))));
+ // https://github.com/servo/servo/issues/16020
+ assert_eq!(parse("*|e"), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::ExplicitAnyNamespace,
+ Component::LocalName(LocalName {
+ name: DummyAtom::from("e"),
+ lower_name: DummyAtom::from("e")
+ }),
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 1),
+ }))));
+ assert_eq!(parse("*"), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::ExplicitUniversalType,
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse("|*"), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::ExplicitNoNamespace,
+ Component::ExplicitUniversalType,
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse("*|*"), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::ExplicitAnyNamespace,
+ Component::ExplicitUniversalType,
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
assert_eq!(parse(".foo:lang(en-US)"), Ok(SelectorList(vec!(Selector {
inner: SelectorInner::from_vec(vec![
Component::Class(DummyAtom::from("foo")),
@@ -1616,10 +1754,7 @@ pub mod tests {
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList(vec![Selector {
inner: SelectorInner::from_vec(
vec![
- Component::Namespace(Namespace {
- prefix: Some(DummyAtom("svg".into())),
- url: SVG.into(),
- }),
+ Component::Namespace(DummyAtom("svg".into()), SVG.into()),
Component::LocalName(LocalName {
name: DummyAtom::from("circle"),
lower_name: DummyAtom::from("circle"),
@@ -1628,6 +1763,15 @@ pub mod tests {
pseudo_element: None,
specificity: specificity(0, 0, 1),
}])));
+ assert_eq!(parse_ns("svg|*", &parser), Ok(SelectorList(vec![Selector {
+ inner: SelectorInner::from_vec(
+ vec![
+ Component::Namespace(DummyAtom("svg".into()), SVG.into()),
+ Component::ExplicitUniversalType,
+ ]),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }])));
// Default namespace does not apply to attribute selectors
// https://github.com/mozilla/servo/pull/1652
// but it does apply to implicit type selectors
@@ -1636,10 +1780,7 @@ pub mod tests {
assert_eq!(parse_ns("[Foo]", &parser), Ok(SelectorList(vec!(Selector {
inner: SelectorInner::from_vec(
vec![
- Component::Namespace(Namespace {
- prefix: None,
- url: MATHML.into(),
- }),
+ Component::DefaultNamespace(MATHML.into()),
Component::AttrExists(AttrSelector {
name: DummyAtom::from("Foo"),
lower_name: DummyAtom::from("foo"),
@@ -1656,10 +1797,7 @@ pub mod tests {
assert_eq!(parse_ns("e", &parser), Ok(SelectorList(vec!(Selector {
inner: SelectorInner::from_vec(
vec!(
- Component::Namespace(Namespace {
- prefix: None,
- url: MATHML.into(),
- }),
+ Component::DefaultNamespace(MATHML.into()),
Component::LocalName(LocalName {
name: DummyAtom::from("e"),
lower_name: DummyAtom::from("e") }),
@@ -1667,6 +1805,61 @@ pub mod tests {
pseudo_element: None,
specificity: specificity(0, 0, 1),
}))));
+ assert_eq!(parse_ns("*", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(
+ vec!(
+ Component::DefaultNamespace(MATHML.into()),
+ Component::ExplicitUniversalType,
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse_ns("*|*", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(
+ vec!(
+ Component::ExplicitAnyNamespace,
+ Component::ExplicitUniversalType,
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ // Default namespace applies to universal and type selectors inside :not and :matches,
+ // but not otherwise.
+ assert_eq!(parse_ns(":not(.cl)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::DefaultNamespace(MATHML.into()),
+ Component::Negation(vec![
+ Component::Class(DummyAtom::from("cl"))
+ ].into_boxed_slice()),
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 1, 0),
+ }))));
+ assert_eq!(parse_ns(":not(*)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::DefaultNamespace(MATHML.into()),
+ Component::Negation(vec![
+ Component::DefaultNamespace(MATHML.into()),
+ Component::ExplicitUniversalType,
+ ].into_boxed_slice()),
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse_ns(":not(e)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(
+ Component::DefaultNamespace(MATHML.into()),
+ Component::Negation(vec![
+ Component::DefaultNamespace(MATHML.into()),
+ Component::LocalName(LocalName {
+ name: DummyAtom::from("e"),
+ lower_name: DummyAtom::from("e")
+ }),
+ ].into_boxed_slice())
+ )),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 1),
+ }))));
assert_eq!(parse("[attr |= \"foo\"]"), Ok(SelectorList(vec![Selector {
inner: SelectorInner::from_vec(
vec![
@@ -1727,10 +1920,7 @@ pub mod tests {
assert_eq!(parse_ns(":not(svg|circle)", &parser), Ok(SelectorList(vec!(Selector {
inner: SelectorInner::from_vec(vec!(Component::Negation(
vec![
- Component::Namespace(Namespace {
- prefix: Some(DummyAtom("svg".into())),
- url: SVG.into(),
- }),
+ Component::Namespace(DummyAtom("svg".into()), SVG.into()),
Component::LocalName(LocalName {
name: DummyAtom::from("circle"),
lower_name: DummyAtom::from("circle")
@@ -1740,6 +1930,46 @@ pub mod tests {
pseudo_element: None,
specificity: specificity(0, 0, 1),
}))));
+ // https://github.com/servo/servo/issues/16017
+ assert_eq!(parse_ns(":not(*)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(Component::Negation(
+ vec![
+ Component::ExplicitUniversalType,
+ ].into_boxed_slice()
+ ))),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse_ns(":not(|*)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(Component::Negation(
+ vec![
+ Component::ExplicitNoNamespace,
+ Component::ExplicitUniversalType,
+ ].into_boxed_slice()
+ ))),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse_ns(":not(*|*)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(Component::Negation(
+ vec![
+ Component::ExplicitAnyNamespace,
+ Component::ExplicitUniversalType,
+ ].into_boxed_slice()
+ ))),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
+ assert_eq!(parse_ns(":not(svg|*)", &parser), Ok(SelectorList(vec!(Selector {
+ inner: SelectorInner::from_vec(vec!(Component::Negation(
+ vec![
+ Component::Namespace(DummyAtom("svg".into()), SVG.into()),
+ Component::ExplicitUniversalType,
+ ].into_boxed_slice()
+ ))),
+ pseudo_element: None,
+ specificity: specificity(0, 0, 0),
+ }))));
}
struct TestVisitor {
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index 74221045b11..acef07d054e 100644
--- a/components/style/stylist.rs
+++ b/components/style/stylist.rs
@@ -1359,8 +1359,8 @@ impl SelectorMap<Rule> {
let mut rules_list = vec![];
for rule in self.other.iter() {
- if rule.selector.inner.complex.iter_raw().next().is_none() {
- rules_list.push(rule.to_applicable_declaration_block(cascade_level));
+ if rule.selector.is_universal() {
+ rules_list.push(rule.to_applicable_declaration_block(cascade_level))
}
}
diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs
index 1cef0f377be..81d8a6fffd4 100644
--- a/tests/unit/style/stylesheets.rs
+++ b/tests/unit/style/stylesheets.rs
@@ -92,10 +92,7 @@ fn test_parse_stylesheet() {
selectors: SelectorList(vec![
Selector {
inner: SelectorInner::from_vec(vec![
- Component::Namespace(Namespace {
- prefix: None,
- url: NsAtom::from("http://www.w3.org/1999/xhtml")
- }),
+ Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("input"),
lower_name: local_name!("input"),
@@ -129,10 +126,7 @@ fn test_parse_stylesheet() {
selectors: SelectorList(vec![
Selector {
inner: SelectorInner::from_vec(vec![
- Component::Namespace(Namespace {
- prefix: None,
- url: NsAtom::from("http://www.w3.org/1999/xhtml")
- }),
+ Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("html"),
lower_name: local_name!("html"),
@@ -143,10 +137,7 @@ fn test_parse_stylesheet() {
},
Selector {
inner: SelectorInner::from_vec(vec![
- Component::Namespace(Namespace {
- prefix: None,
- url: NsAtom::from("http://www.w3.org/1999/xhtml")
- }),
+ Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("body"),
lower_name: local_name!("body"),
@@ -169,16 +160,10 @@ fn test_parse_stylesheet() {
selectors: SelectorList(vec![
Selector {
inner: SelectorInner::from_vec(vec![
- Component::Namespace(Namespace {
- prefix: None,
- url: NsAtom::from("http://www.w3.org/1999/xhtml")
- }),
+ Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::ID(Atom::from("d1")),
Component::Combinator(Combinator::Child),
- Component::Namespace(Namespace {
- prefix: None,
- url: NsAtom::from("http://www.w3.org/1999/xhtml")
- }),
+ Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::Class(Atom::from("ok")),
]),
pseudo_element: None,
diff --git a/tests/unit/style/stylist.rs b/tests/unit/style/stylist.rs
index 073c003b0bb..3c136edcef3 100644
--- a/tests/unit/style/stylist.rs
+++ b/tests/unit/style/stylist.rs
@@ -212,9 +212,9 @@ fn test_insert() {
#[test]
fn test_get_universal_rules() {
thread_state::initialize(thread_state::LAYOUT);
- let (map, shared_lock) = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
+ let (map, shared_lock) = get_mock_map(&["*|*", "#foo > *|*", "*|* > *|*", ".klass", "#id"]);
let decls = map.get_universal_rules(CascadeLevel::UserNormal);
- assert_eq!(decls.len(), 1);
+ assert_eq!(decls.len(), 1, "{:?}", decls);
}