From 1ae9cdbb23da14bc5ecf597ed31789a01ac768f0 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Tue, 7 Jul 2020 14:30:35 -0400 Subject: [PATCH] box `selector` field of pseudo selectors gives a ~3% improvement to bootstrap by decreasing size of `SimpleSelector` to 88 bytes --- src/selector/compound.rs | 5 +++-- src/selector/extend/mod.rs | 15 ++++++++------- src/selector/parse.rs | 8 ++++---- src/selector/simple.rs | 6 +++--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/selector/compound.rs b/src/selector/compound.rs index cd1b47e..6ba1e0d 100644 --- a/src/selector/compound.rs +++ b/src/selector/compound.rs @@ -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)) diff --git a/src/selector/extend/mod.rs b/src/selector/extend/mod.rs index 205022f..73327c1 100644 --- a/src/selector/extend/mod.rs +++ b/src/selector/extend/mod.rs @@ -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::>(); 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); } } } diff --git a/src/selector/parse.rs b/src/selector/parse.rs index a5af6c8..cab9324 100644 --- a/src/selector/parse.rs +++ b/src/selector/parse.rs @@ -312,19 +312,19 @@ impl<'a, 'b> SelectorParser<'a, 'b> { let unvendored = unvendor(&name); let mut argument: Option> = None; - let mut selector: Option = None; + let mut selector: Option> = 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()?)); } _ => {} } diff --git a/src/selector/simple.rs b/src/selector/simple.rs index 6fbd40b..26f8c45 100644 --- a/src/selector/simple.rs +++ b/src/selector/simple.rs @@ -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, + pub selector: Option>, pub span: Span, } @@ -601,7 +601,7 @@ impl Pseudo { } #[allow(clippy::missing_const_for_fn)] - pub fn with_selector(self, selector: Option) -> Self { + pub fn with_selector(self, selector: Option>) -> Self { Self { selector, ..self } }