style: Add an extra flag to flag ::part() to selectors.

This grows the selector struct, but only in 32-bit, since in 64-bit we take
space from the alignment padding that we're paying due to having the size of the
slice as a word.

Differential Revision: https://phabricator.services.mozilla.com/D32645
This commit is contained in:
Emilio Cobos Álvarez 2019-06-11 17:42:23 +00:00
parent 96594be65d
commit fac050325c
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
2 changed files with 92 additions and 28 deletions

View file

@ -6,7 +6,7 @@ use crate::attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace};
use crate::attr::{NamespaceConstraint, ParsedAttrSelectorOperation};
use crate::attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE};
use crate::bloom::BLOOM_HASH_MASK;
use crate::builder::{SelectorBuilder, SpecificityAndFlags};
use crate::builder::{SelectorBuilder, SelectorFlags, SpecificityAndFlags};
use crate::context::QuirksMode;
use crate::sink::Push;
pub use crate::visitor::{SelectorVisitor, Visit};
@ -601,6 +601,11 @@ impl<Impl: SelectorImpl> Selector<Impl> {
self.0.header.header.is_slotted()
}
#[inline]
pub fn is_part(&self) -> bool {
self.0.header.header.is_part()
}
#[inline]
pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
if !self.has_pseudo_element() {
@ -720,7 +725,8 @@ impl<Impl: SelectorImpl> Selector<Impl> {
}
/// Creates a Selector from a vec of Components, specified in parse order. Used in tests.
pub fn from_vec(vec: Vec<Component<Impl>>, specificity_and_flags: u32) -> Self {
#[allow(unused)]
pub (crate) fn from_vec(vec: Vec<Component<Impl>>, specificity: u32, flags: SelectorFlags) -> Self {
let mut builder = SelectorBuilder::default();
for component in vec.into_iter() {
if let Some(combinator) = component.as_combinator() {
@ -729,7 +735,10 @@ impl<Impl: SelectorImpl> Selector<Impl> {
builder.push_simple_selector(component);
}
}
let spec = SpecificityAndFlags(specificity_and_flags);
let spec = SpecificityAndFlags {
specificity,
flags,
};
Selector(builder.build_with_specificity_and_flags(spec))
}
@ -1445,6 +1454,7 @@ where
let mut has_pseudo_element = false;
let mut slotted = false;
let mut part = false;
'outer_loop: loop {
// Parse a sequence of simple selectors.
let state = match parse_compound_selector(parser, input, &mut builder)? {
@ -1461,7 +1471,7 @@ where
if state.intersects(SelectorParsingState::AFTER_PSEUDO) {
has_pseudo_element = state.intersects(SelectorParsingState::AFTER_PSEUDO_ELEMENT);
slotted = state.intersects(SelectorParsingState::AFTER_SLOTTED);
let part = state.intersects(SelectorParsingState::AFTER_PART);
part = state.intersects(SelectorParsingState::AFTER_PART);
debug_assert!(has_pseudo_element || slotted || part);
break;
}
@ -1500,9 +1510,7 @@ where
builder.push_combinator(combinator);
}
// TODO(emilio): We'll have to flag part() somehow as well, but we need more
// bits!
Ok(Selector(builder.build(has_pseudo_element, slotted)))
Ok(Selector(builder.build(has_pseudo_element, slotted, part)))
}
impl<Impl: SelectorImpl> Selector<Impl> {
@ -2249,7 +2257,7 @@ where
#[cfg(test)]
pub mod tests {
use super::*;
use crate::builder::HAS_PSEUDO_BIT;
use crate::builder::SelectorFlags;
use crate::parser;
use cssparser::{serialize_identifier, Parser as CssParser, ParserInput, ToCss};
use std::collections::HashMap;
@ -2532,6 +2540,7 @@ pub mod tests {
lower_name: DummyAtom::from("eeÉ"),
})],
specificity(0, 0, 1),
Default::default(),
)]))
);
assert_eq!(
@ -2545,6 +2554,7 @@ pub mod tests {
}),
],
specificity(0, 0, 1),
Default::default(),
)]))
);
// When the default namespace is not set, *| should be elided.
@ -2557,6 +2567,7 @@ pub mod tests {
lower_name: DummyAtom::from("e"),
})],
specificity(0, 0, 1),
Default::default(),
)]))
);
// When the default namespace is set, *| should _not_ be elided (as foo
@ -2577,13 +2588,15 @@ pub mod tests {
}),
],
specificity(0, 0, 1),
Default::default(),
)]))
);
assert_eq!(
parse("*"),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
vec![Component::ExplicitUniversalType],
specificity(0, 0, 0)
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2594,13 +2607,15 @@ pub mod tests {
Component::ExplicitUniversalType,
],
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
parse_expected("*|*", Some("*")),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
vec![Component::ExplicitUniversalType],
specificity(0, 0, 0)
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2614,6 +2629,7 @@ pub mod tests {
Component::ExplicitUniversalType,
],
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2624,6 +2640,7 @@ pub mod tests {
Component::NonTSPseudoClass(PseudoClass::Lang("en-US".to_owned())),
],
specificity(0, 2, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2631,6 +2648,7 @@ pub mod tests {
Ok(SelectorList::from_vec(vec![Selector::from_vec(
vec![Component::ID(DummyAtom::from("bar"))],
specificity(1, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2645,6 +2663,7 @@ pub mod tests {
Component::ID(DummyAtom::from("bar")),
],
specificity(1, 1, 1),
Default::default(),
)]))
);
assert_eq!(
@ -2660,6 +2679,7 @@ pub mod tests {
Component::ID(DummyAtom::from("bar")),
],
specificity(1, 1, 1),
Default::default(),
)]))
);
// Default namespace does not apply to attribute selectors
@ -2673,6 +2693,7 @@ pub mod tests {
local_name_lower: DummyAtom::from("foo"),
}],
specificity(0, 1, 0),
Default::default(),
)]))
);
assert!(parse_ns("svg|circle", &parser).is_err());
@ -2690,6 +2711,7 @@ pub mod tests {
}),
],
specificity(0, 0, 1),
Default::default(),
)]))
);
assert_eq!(
@ -2700,6 +2722,7 @@ pub mod tests {
Component::ExplicitUniversalType,
],
specificity(0, 0, 0),
Default::default(),
)]))
);
// Default namespace does not apply to attribute selectors
@ -2718,6 +2741,7 @@ pub mod tests {
},
],
specificity(0, 1, 0),
Default::default(),
)]))
);
// Default namespace does apply to type selectors
@ -2732,6 +2756,7 @@ pub mod tests {
}),
],
specificity(0, 0, 1),
Default::default(),
)]))
);
assert_eq!(
@ -2742,6 +2767,7 @@ pub mod tests {
Component::ExplicitUniversalType,
],
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2752,6 +2778,7 @@ pub mod tests {
Component::ExplicitUniversalType,
],
specificity(0, 0, 0),
Default::default(),
)]))
);
// Default namespace applies to universal and type selectors inside :not and :matches,
@ -2768,6 +2795,7 @@ pub mod tests {
),
],
specificity(0, 1, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2785,6 +2813,7 @@ pub mod tests {
),
],
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2805,6 +2834,7 @@ pub mod tests {
),
],
specificity(0, 0, 1),
Default::default(),
)]))
);
assert_eq!(
@ -2818,6 +2848,7 @@ pub mod tests {
case_sensitivity: ParsedCaseSensitivity::CaseSensitive,
}],
specificity(0, 1, 0),
Default::default(),
)]))
);
// https://github.com/mozilla/servo/issues/1723
@ -2828,7 +2859,8 @@ pub mod tests {
Component::Combinator(Combinator::PseudoElement),
Component::PseudoElement(PseudoElement::Before),
],
specificity(0, 0, 1) | HAS_PSEUDO_BIT,
specificity(0, 0, 1),
SelectorFlags::HAS_PSEUDO,
)]))
);
assert_eq!(
@ -2839,7 +2871,8 @@ pub mod tests {
Component::PseudoElement(PseudoElement::Before),
Component::NonTSPseudoClass(PseudoClass::Hover),
],
specificity(0, 1, 1) | HAS_PSEUDO_BIT,
specificity(0, 1, 1),
SelectorFlags::HAS_PSEUDO,
)]))
);
assert_eq!(
@ -2851,7 +2884,8 @@ pub mod tests {
Component::NonTSPseudoClass(PseudoClass::Hover),
Component::NonTSPseudoClass(PseudoClass::Hover),
],
specificity(0, 2, 1) | HAS_PSEUDO_BIT,
specificity(0, 2, 1),
SelectorFlags::HAS_PSEUDO,
)]))
);
assert!(parse("::before:hover:lang(foo)").is_err());
@ -2874,7 +2908,8 @@ pub mod tests {
Component::Combinator(Combinator::PseudoElement),
Component::PseudoElement(PseudoElement::After),
],
specificity(0, 0, 2) | HAS_PSEUDO_BIT,
specificity(0, 0, 2),
SelectorFlags::HAS_PSEUDO,
)]))
);
assert_eq!(
@ -2886,6 +2921,7 @@ pub mod tests {
Component::Class(DummyAtom::from("ok")),
],
(1 << 20) + (1 << 10) + (0 << 0),
Default::default(),
)]))
);
parser.default_ns = None;
@ -2901,6 +2937,7 @@ pub mod tests {
.into(),
)],
specificity(1, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2918,6 +2955,7 @@ pub mod tests {
.into(),
)],
specificity(0, 0, 1),
Default::default(),
)]))
);
// https://github.com/servo/servo/issues/16017
@ -2930,6 +2968,7 @@ pub mod tests {
.into(),
)],
specificity(0, 0, 0),
Default::default(),
)]))
);
assert_eq!(
@ -2944,6 +2983,7 @@ pub mod tests {
.into(),
)],
specificity(0, 0, 0),
Default::default(),
)]))
);
// *| should be elided if there is no default namespace.
@ -2957,6 +2997,7 @@ pub mod tests {
.into(),
)],
specificity(0, 0, 0),
Default::default(),
)]))
);
@ -2972,6 +3013,7 @@ pub mod tests {
.into(),
)],
specificity(0, 0, 0),
Default::default(),
)]))
);