diff options
author | Cameron McCormack <cam@mcc.id.au> | 2018-07-16 12:15:47 +1000 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-08-08 01:36:53 +0200 |
commit | 62419adaaaeefd9da21c32899af2a5e1555fe8de (patch) | |
tree | 700cce4a3dc3e19d19ab45930a30aab3054043b7 /components/selectors/parser.rs | |
parent | b05ace3e4a9df4af8973d5067dc32859c5ae5803 (diff) | |
download | servo-62419adaaaeefd9da21c32899af2a5e1555fe8de.tar.gz servo-62419adaaaeefd9da21c32899af2a5e1555fe8de.zip |
style: Shrink selectors::Component to 24 bytes.
This saves about 37 KiB of memory across the UA style sheets.
Bug: 1475197
Reviewed-by: emilio
Diffstat (limited to 'components/selectors/parser.rs')
-rw-r--r-- | components/selectors/parser.rs | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 399f21e6361..d0f98cde57b 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -2,8 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use attr::{AttrSelectorOperator, AttrSelectorWithNamespace, ParsedAttrSelectorOperation}; -use attr::{NamespaceConstraint, ParsedCaseSensitivity, SELECTOR_WHITESPACE}; +use attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace}; +use attr::{NamespaceConstraint, ParsedAttrSelectorOperation}; +use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE}; use bloom::BLOOM_HASH_MASK; use builder::{SelectorBuilder, SpecificityAndFlags}; use context::QuirksMode; @@ -19,6 +20,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt::{self, Debug, Display, Write}; use std::iter::Rev; use std::slice; +use thin_slice::ThinBoxedSlice; pub use visitor::{SelectorVisitor, Visit}; /// A trait that represents a pseudo-element. @@ -45,6 +47,8 @@ pub trait NonTSPseudoClass: Sized + ToCss { fn is_active_or_hover(&self) -> bool; } +/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a +/// Cow::Owned if `s` had to be converted into ASCII lowercase. fn to_ascii_lowercase(s: &str) -> Cow<str> { if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') { let mut string = s.to_owned(); @@ -428,7 +432,6 @@ where }, AttributeInNoNamespace { ref local_name, - ref local_name_lower, never_matches, .. } if !never_matches => @@ -436,14 +439,22 @@ where if !visitor.visit_attribute_selector( &NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()), local_name, - local_name_lower, + local_name, ) { return false; } }, AttributeOther(ref attr_selector) if !attr_selector.never_matches => { + let empty_string; + let namespace = match attr_selector.namespace() { + Some(ns) => ns, + None => { + empty_string = ::parser::namespace_empty_string::<Impl>(); + NamespaceConstraint::Specific(&empty_string) + } + }; if !visitor.visit_attribute_selector( - &attr_selector.namespace(), + &namespace, &attr_selector.local_name, &attr_selector.local_name_lower, ) { @@ -815,16 +826,16 @@ pub enum Component<Impl: SelectorImpl> { local_name: Impl::LocalName, local_name_lower: Impl::LocalName, }, + // Used only when local_name is already lowercase. AttributeInNoNamespace { local_name: Impl::LocalName, - local_name_lower: Impl::LocalName, operator: AttrSelectorOperator, value: Impl::AttrValue, case_sensitivity: ParsedCaseSensitivity, never_matches: bool, }, // Use a Box in the less common cases with more data to keep size_of::<Component>() small. - AttributeOther(Box<AttrSelectorWithNamespace<Impl>>), + AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>), /// Pseudo-classes /// @@ -836,7 +847,7 @@ pub enum Component<Impl: SelectorImpl> { /// need to think about how this should interact with /// visit_complex_selector, and what the consumers of those APIs should do /// about the presence of combinators in negation. - Negation(Box<[Component<Impl>]>), + Negation(ThinBoxedSlice<Component<Impl>>), FirstChild, LastChild, OnlyChild, @@ -948,7 +959,7 @@ impl<Impl: SelectorImpl> Debug for Component<Impl> { self.to_css(f) } } -impl<Impl: SelectorImpl> Debug for AttrSelectorWithNamespace<Impl> { +impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_css(f) } @@ -1238,18 +1249,19 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> { } } -impl<Impl: SelectorImpl> ToCss for AttrSelectorWithNamespace<Impl> { +impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write, { dest.write_char('[')?; match self.namespace { - NamespaceConstraint::Specific((ref prefix, _)) => { + Some(NamespaceConstraint::Specific((ref prefix, _))) => { display_to_css_identifier(prefix, dest)?; dest.write_char('|')? }, - NamespaceConstraint::Any => dest.write_str("*|")?, + Some(NamespaceConstraint::Any) => dest.write_str("*|")?, + None => {} } display_to_css_identifier(&self.local_name, dest)?; match self.operation { @@ -1628,8 +1640,8 @@ where let local_name = local_name.as_ref().into(); if let Some(namespace) = namespace { return Ok(Component::AttributeOther(Box::new( - AttrSelectorWithNamespace { - namespace: namespace, + AttrSelectorWithOptionalNamespace { + namespace: Some(namespace), local_name: local_name, local_name_lower: local_name_lower, operation: ParsedAttrSelectorOperation::Exists, @@ -1685,6 +1697,7 @@ where let value = value.as_ref().into(); let local_name_lower; + let local_name_is_ascii_lowercase; { let local_name_lower_cow = to_ascii_lowercase(&local_name); if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity { @@ -1699,15 +1712,16 @@ where } } local_name_lower = local_name_lower_cow.as_ref().into(); + local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..)); } let local_name = local_name.as_ref().into(); - if let Some(namespace) = namespace { + if namespace.is_some() || !local_name_is_ascii_lowercase { Ok(Component::AttributeOther(Box::new( - AttrSelectorWithNamespace { - namespace: namespace, - local_name: local_name, - local_name_lower: local_name_lower, - never_matches: never_matches, + AttrSelectorWithOptionalNamespace { + namespace, + local_name, + local_name_lower, + never_matches, operation: ParsedAttrSelectorOperation::WithValue { operator: operator, case_sensitivity: case_sensitivity, @@ -1718,7 +1732,6 @@ where } else { Ok(Component::AttributeInNoNamespace { local_name: local_name, - local_name_lower: local_name_lower, operator: operator, value: value, case_sensitivity: case_sensitivity, @@ -1785,7 +1798,7 @@ where } // Success. - Ok(Component::Negation(sequence.into_vec().into_boxed_slice())) + Ok(Component::Negation(sequence.into_vec().into_boxed_slice().into())) } /// simple_selector_sequence @@ -2625,7 +2638,7 @@ pub mod tests { vec![ Component::DefaultNamespace(MATHML.into()), Component::Negation( - vec![Component::Class(DummyAtom::from("cl"))].into_boxed_slice(), + vec![Component::Class(DummyAtom::from("cl"))].into_boxed_slice().into(), ), ], specificity(0, 1, 0), @@ -2642,7 +2655,7 @@ pub mod tests { vec![ Component::DefaultNamespace(MATHML.into()), Component::ExplicitUniversalType, - ].into_boxed_slice(), + ].into_boxed_slice().into(), ), ], specificity(0, 0, 0), @@ -2662,7 +2675,7 @@ pub mod tests { name: DummyAtom::from("e"), lower_name: DummyAtom::from("e"), }), - ].into_boxed_slice(), + ].into_boxed_slice().into(), ), ], specificity(0, 0, 1), @@ -2676,7 +2689,6 @@ pub mod tests { vec![ Component::AttributeInNoNamespace { local_name: DummyAtom::from("attr"), - local_name_lower: DummyAtom::from("attr"), operator: AttrSelectorOperator::DashMatch, value: DummyAtom::from("foo"), never_matches: false, @@ -2770,7 +2782,7 @@ pub mod tests { Selector::from_vec( vec![ Component::Negation( - vec![Component::ID(DummyAtom::from("provel"))].into_boxed_slice(), + vec![Component::ID(DummyAtom::from("provel"))].into_boxed_slice().into(), ), ], specificity(1, 0, 0), @@ -2789,7 +2801,7 @@ pub mod tests { name: DummyAtom::from("circle"), lower_name: DummyAtom::from("circle"), }), - ].into_boxed_slice(), + ].into_boxed_slice().into(), ), ], specificity(0, 0, 1), @@ -2803,7 +2815,7 @@ pub mod tests { Selector::from_vec( vec![ Component::Negation( - vec![Component::ExplicitUniversalType].into_boxed_slice(), + vec![Component::ExplicitUniversalType].into_boxed_slice().into(), ), ], specificity(0, 0, 0), @@ -2819,7 +2831,7 @@ pub mod tests { vec![ Component::ExplicitNoNamespace, Component::ExplicitUniversalType, - ].into_boxed_slice(), + ].into_boxed_slice().into(), ), ], specificity(0, 0, 0), @@ -2834,7 +2846,7 @@ pub mod tests { Selector::from_vec( vec![ Component::Negation( - vec![Component::ExplicitUniversalType].into_boxed_slice(), + vec![Component::ExplicitUniversalType].into_boxed_slice().into(), ), ], specificity(0, 0, 0), @@ -2850,7 +2862,7 @@ pub mod tests { vec![ Component::Namespace(DummyAtom("svg".into()), SVG.into()), Component::ExplicitUniversalType, - ].into_boxed_slice(), + ].into_boxed_slice().into(), ), ], specificity(0, 0, 0), |