aboutsummaryrefslogtreecommitdiffstats
path: root/components/selectors/parser.rs
diff options
context:
space:
mode:
authorCameron McCormack <cam@mcc.id.au>2018-07-16 12:15:47 +1000
committerEmilio Cobos Álvarez <emilio@crisal.io>2018-08-08 01:36:53 +0200
commit62419adaaaeefd9da21c32899af2a5e1555fe8de (patch)
tree700cce4a3dc3e19d19ab45930a30aab3054043b7 /components/selectors/parser.rs
parentb05ace3e4a9df4af8973d5067dc32859c5ae5803 (diff)
downloadservo-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.rs76
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),