box selector field of pseudo selectors

gives a ~3% improvement to bootstrap by decreasing size of
`SimpleSelector` to 88 bytes
This commit is contained in:
Connor Skees 2020-07-07 14:30:35 -04:00
parent e915e5cd31
commit 1ae9cdbb23
4 changed files with 18 additions and 16 deletions

View File

@ -134,8 +134,9 @@ impl CompoundSelector {
if !sel.contains_parent_selector() {
return Ok(SimpleSelector::Pseudo(pseudo));
}
pseudo.selector =
Some(sel.resolve_parent_selectors(Some(parent.clone()), false)?);
pseudo.selector = Some(Box::new(
sel.resolve_parent_selectors(Some(parent.clone()), false)?,
));
Ok(SimpleSelector::Pseudo(pseudo))
} else {
Ok(SimpleSelector::Pseudo(pseudo))

View File

@ -582,13 +582,14 @@ impl Extender {
let extended = self.extend_list(
pseudo
.selector
.clone()
.as_deref()
.cloned()
.unwrap_or_else(|| SelectorList::new(self.span)),
extensions,
media_query_context,
);
/*todo: identical(extended, pseudo.selector)*/
if Some(&extended) == pseudo.selector.as_ref() {
if Some(&extended) == pseudo.selector.as_deref() {
return None;
}
@ -689,10 +690,10 @@ impl Extender {
let result = complexes
.into_iter()
.map(|complex| {
pseudo.clone().with_selector(Some(SelectorList {
pseudo.clone().with_selector(Some(Box::new(SelectorList {
components: vec![complex],
span: self.span,
}))
})))
})
.collect::<Vec<Pseudo>>();
if result.is_empty() {
@ -701,10 +702,10 @@ impl Extender {
Some(result)
}
} else {
Some(vec![pseudo.with_selector(Some(SelectorList {
Some(vec![pseudo.with_selector(Some(Box::new(SelectorList {
components: complexes,
span: self.span,
}))])
})))])
}
}
@ -925,7 +926,7 @@ impl Extender {
..
}) = simple
{
self.register_selector(simple_selector, selector);
self.register_selector(*simple_selector, selector);
}
}
}

View File

@ -312,19 +312,19 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
let unvendored = unvendor(&name);
let mut argument: Option<Box<str>> = None;
let mut selector: Option<SelectorList> = None;
let mut selector: Option<Box<SelectorList>> = None;
if element {
// todo: lowercase?
if SELECTOR_PSEUDO_ELEMENTS.contains(&unvendored) {
selector = Some(self.parse_selector_list()?);
selector = Some(Box::new(self.parse_selector_list()?));
self.parser.whitespace();
self.expect_closing_paren()?;
} else {
argument = Some(self.declaration_value()?.into_boxed_str());
}
} else if SELECTOR_PSEUDO_CLASSES.contains(&unvendored) {
selector = Some(self.parse_selector_list()?);
selector = Some(Box::new(self.parse_selector_list()?));
self.parser.whitespace();
self.expect_closing_paren()?;
} else if unvendored == "nth-child" || unvendored == "nth-last-child" {
@ -337,7 +337,7 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
self.expect_identifier("of")?;
this_arg.push_str(" of");
self.parser.whitespace();
selector = Some(self.parse_selector_list()?);
selector = Some(Box::new(self.parse_selector_list()?));
}
_ => {}
}

View File

@ -119,7 +119,7 @@ impl SimpleSelector {
| Self::Class(..)
| Self::Attribute(..) => false,
Self::Pseudo(Pseudo { name, selector, .. }) => {
name != "not" && selector.as_ref().map_or(false, SelectorList::is_invisible)
name != "not" && selector.as_ref().map_or(false, |sel| sel.is_invisible())
}
Self::Placeholder(..) => true,
Self::Parent(..) => todo!(),
@ -411,7 +411,7 @@ pub(crate) struct Pseudo {
///
/// This is `None` if there's no selector. If `argument` and `selector` are
/// both non-`None`, the selector follows the argument.
pub selector: Option<SelectorList>,
pub selector: Option<Box<SelectorList>>,
pub span: Span,
}
@ -601,7 +601,7 @@ impl Pseudo {
}
#[allow(clippy::missing_const_for_fn)]
pub fn with_selector(self, selector: Option<SelectorList>) -> Self {
pub fn with_selector(self, selector: Option<Box<SelectorList>>) -> Self {
Self { selector, ..self }
}