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() { if !sel.contains_parent_selector() {
return Ok(SimpleSelector::Pseudo(pseudo)); return Ok(SimpleSelector::Pseudo(pseudo));
} }
pseudo.selector = pseudo.selector = Some(Box::new(
Some(sel.resolve_parent_selectors(Some(parent.clone()), false)?); sel.resolve_parent_selectors(Some(parent.clone()), false)?,
));
Ok(SimpleSelector::Pseudo(pseudo)) Ok(SimpleSelector::Pseudo(pseudo))
} else { } else {
Ok(SimpleSelector::Pseudo(pseudo)) Ok(SimpleSelector::Pseudo(pseudo))

View File

@ -582,13 +582,14 @@ impl Extender {
let extended = self.extend_list( let extended = self.extend_list(
pseudo pseudo
.selector .selector
.clone() .as_deref()
.cloned()
.unwrap_or_else(|| SelectorList::new(self.span)), .unwrap_or_else(|| SelectorList::new(self.span)),
extensions, extensions,
media_query_context, media_query_context,
); );
/*todo: identical(extended, pseudo.selector)*/ /*todo: identical(extended, pseudo.selector)*/
if Some(&extended) == pseudo.selector.as_ref() { if Some(&extended) == pseudo.selector.as_deref() {
return None; return None;
} }
@ -689,10 +690,10 @@ impl Extender {
let result = complexes let result = complexes
.into_iter() .into_iter()
.map(|complex| { .map(|complex| {
pseudo.clone().with_selector(Some(SelectorList { pseudo.clone().with_selector(Some(Box::new(SelectorList {
components: vec![complex], components: vec![complex],
span: self.span, span: self.span,
})) })))
}) })
.collect::<Vec<Pseudo>>(); .collect::<Vec<Pseudo>>();
if result.is_empty() { if result.is_empty() {
@ -701,10 +702,10 @@ impl Extender {
Some(result) Some(result)
} }
} else { } else {
Some(vec![pseudo.with_selector(Some(SelectorList { Some(vec![pseudo.with_selector(Some(Box::new(SelectorList {
components: complexes, components: complexes,
span: self.span, span: self.span,
}))]) })))])
} }
} }
@ -925,7 +926,7 @@ impl Extender {
.. ..
}) = simple }) = 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 unvendored = unvendor(&name);
let mut argument: Option<Box<str>> = None; let mut argument: Option<Box<str>> = None;
let mut selector: Option<SelectorList> = None; let mut selector: Option<Box<SelectorList>> = None;
if element { if element {
// todo: lowercase? // todo: lowercase?
if SELECTOR_PSEUDO_ELEMENTS.contains(&unvendored) { if SELECTOR_PSEUDO_ELEMENTS.contains(&unvendored) {
selector = Some(self.parse_selector_list()?); selector = Some(Box::new(self.parse_selector_list()?));
self.parser.whitespace(); self.parser.whitespace();
self.expect_closing_paren()?; self.expect_closing_paren()?;
} else { } else {
argument = Some(self.declaration_value()?.into_boxed_str()); argument = Some(self.declaration_value()?.into_boxed_str());
} }
} else if SELECTOR_PSEUDO_CLASSES.contains(&unvendored) { } 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.parser.whitespace();
self.expect_closing_paren()?; self.expect_closing_paren()?;
} else if unvendored == "nth-child" || unvendored == "nth-last-child" { } else if unvendored == "nth-child" || unvendored == "nth-last-child" {
@ -337,7 +337,7 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
self.expect_identifier("of")?; self.expect_identifier("of")?;
this_arg.push_str(" of"); this_arg.push_str(" of");
self.parser.whitespace(); 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::Class(..)
| Self::Attribute(..) => false, | Self::Attribute(..) => false,
Self::Pseudo(Pseudo { name, selector, .. }) => { 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::Placeholder(..) => true,
Self::Parent(..) => todo!(), Self::Parent(..) => todo!(),
@ -411,7 +411,7 @@ pub(crate) struct Pseudo {
/// ///
/// This is `None` if there's no selector. If `argument` and `selector` are /// This is `None` if there's no selector. If `argument` and `selector` are
/// both non-`None`, the selector follows the argument. /// both non-`None`, the selector follows the argument.
pub selector: Option<SelectorList>, pub selector: Option<Box<SelectorList>>,
pub span: Span, pub span: Span,
} }
@ -601,7 +601,7 @@ impl Pseudo {
} }
#[allow(clippy::missing_const_for_fn)] #[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 } Self { selector, ..self }
} }