diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-11-22 01:02:22 +0000 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2021-02-26 16:44:05 +0100 |
commit | 9f40b9ba38a531088c2117b955f40af6ea0d09c8 (patch) | |
tree | e221662df58ec16b2c2027d71fd5df015fe3f526 | |
parent | 4ea378a6ae232af09135b2037c527466ef5454de (diff) | |
download | servo-9f40b9ba38a531088c2117b955f40af6ea0d09c8.tar.gz servo-9f40b9ba38a531088c2117b955f40af6ea0d09c8.zip |
style: Avoid some allocations in selector serialization.
The allocations in display_to_css_identifier show up in the profiles of
bug 1675628.
Differential Revision: https://phabricator.services.mozilla.com/D97856
-rw-r--r-- | components/style/dom.rs | 15 | ||||
-rw-r--r-- | components/style/dom_apis.rs | 8 | ||||
-rw-r--r-- | components/style/gecko/selector_parser.rs | 20 | ||||
-rw-r--r-- | components/style/gecko/snapshot.rs | 23 | ||||
-rw-r--r-- | components/style/gecko/snapshot_helpers.rs | 24 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 38 | ||||
-rw-r--r-- | components/style/gecko_string_cache/mod.rs | 6 | ||||
-rw-r--r-- | components/style/gecko_string_cache/namespace.rs | 11 | ||||
-rw-r--r-- | components/style/invalidation/element/element_wrapper.rs | 19 | ||||
-rw-r--r-- | components/style/invalidation/element/invalidation_map.rs | 2 | ||||
-rw-r--r-- | components/style/invalidation/element/state_and_attributes.rs | 4 | ||||
-rw-r--r-- | components/style/invalidation/stylesheets.rs | 9 | ||||
-rw-r--r-- | components/style/lib.rs | 4 | ||||
-rw-r--r-- | components/style/macros.rs | 7 | ||||
-rw-r--r-- | components/style/rule_collector.rs | 9 | ||||
-rw-r--r-- | components/style/sharing/mod.rs | 22 | ||||
-rw-r--r-- | components/style/style_adjuster.rs | 2 | ||||
-rw-r--r-- | components/style/stylist.rs | 4 | ||||
-rw-r--r-- | components/style/values/mod.rs | 107 |
19 files changed, 220 insertions, 114 deletions
diff --git a/components/style/dom.rs b/components/style/dom.rs index 351f54af6e3..2edf5ae7dab 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -20,7 +20,8 @@ use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl}; use crate::shared_lock::{Locked, SharedRwLock}; use crate::stylist::CascadeData; use crate::traversal_flags::TraversalFlags; -use crate::{Atom, LocalName, Namespace, WeakAtom}; +use crate::values::AtomIdent; +use crate::{LocalName, Namespace, WeakAtom}; use atomic_refcell::{AtomicRef, AtomicRefMut}; use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode}; use selectors::sink::Push; @@ -121,7 +122,7 @@ pub trait TDocument: Sized + Copy + Clone { /// return an empty slice. fn elements_with_id<'a>( &self, - _id: &Atom, + _id: &AtomIdent, ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()> where Self: 'a, @@ -344,7 +345,7 @@ pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq { /// return an empty slice. fn elements_with_id<'a>( &self, - _id: &Atom, + _id: &AtomIdent, ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()> where Self: 'a, @@ -520,20 +521,20 @@ pub trait TElement: /// Internal iterator for the classes of this element. fn each_class<F>(&self, callback: F) where - F: FnMut(&Atom); + F: FnMut(&AtomIdent); /// Internal iterator for the part names of this element. fn each_part<F>(&self, _callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { } /// Internal iterator for the part names that this element exports for a /// given part name. - fn each_exported_part<F>(&self, _name: &Atom, _callback: F) + fn each_exported_part<F>(&self, _name: &AtomIdent, _callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { } diff --git a/components/style/dom_apis.rs b/components/style/dom_apis.rs index f4e814acd11..a6c50805cbb 100644 --- a/components/style/dom_apis.rs +++ b/components/style/dom_apis.rs @@ -10,7 +10,7 @@ use crate::dom::{TDocument, TElement, TNode, TShadowRoot}; use crate::invalidation::element::invalidation_map::Dependency; use crate::invalidation::element::invalidator::{DescendantInvalidationLists, Invalidation}; use crate::invalidation::element::invalidator::{InvalidationProcessor, InvalidationVector}; -use crate::Atom; +use crate::values::AtomIdent; use selectors::attr::CaseSensitivity; use selectors::matching::{self, MatchingContext, MatchingMode}; use selectors::parser::{Combinator, Component, LocalName, SelectorImpl}; @@ -276,7 +276,7 @@ where /// or shadow root that `root` is connected to. fn fast_connected_elements_with_id<'a, N>( root: N, - id: &Atom, + id: &AtomIdent, quirks_mode: QuirksMode, ) -> Result<&'a [N::ConcreteElement], ()> where @@ -305,7 +305,7 @@ where /// Collects elements with a given id under `root`, that pass `filter`. fn collect_elements_with_id<E, Q, F>( root: E::ConcreteNode, - id: &Atom, + id: &AtomIdent, results: &mut Q::Output, quirks_mode: QuirksMode, mut filter: F, @@ -398,7 +398,7 @@ where } enum SimpleFilter<'a, Impl: SelectorImpl> { - Class(&'a Atom), + Class(&'a AtomIdent), LocalName(&'a LocalName<Impl>), } diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 6f8ac010e11..c63bc81c95b 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -11,7 +11,7 @@ use crate::invalidation::element::document_state::InvalidationMatchingData; use crate::selector_parser::{Direction, SelectorParser}; use crate::str::starts_with_ignore_ascii_case; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; -use crate::values::serialize_atom_identifier; +use crate::values::{AtomIdent, AtomString}; use cssparser::{BasicParseError, BasicParseErrorKind, Parser}; use cssparser::{CowRcStr, SourceLocation, ToCss, Token}; use selectors::parser::{SelectorParseErrorKind, ParseErrorRecovery}; @@ -39,7 +39,7 @@ bitflags! { } /// The type used to store the language argument to the `:lang` pseudo-class. -pub type Lang = Atom; +pub type Lang = AtomIdent; macro_rules! pseudo_class_name { ([$(($css:expr, $name:ident, $state:tt, $flags:tt),)*]) => { @@ -77,7 +77,7 @@ impl ToCss for NonTSPseudoClass { $(NonTSPseudoClass::$name => concat!(":", $css),)* NonTSPseudoClass::Lang(ref s) => { dest.write_str(":lang(")?; - serialize_atom_identifier(s, dest)?; + s.to_css(dest)?; return dest.write_char(')'); }, NonTSPseudoClass::MozLocaleDir(ref dir) => { @@ -270,12 +270,10 @@ pub struct SelectorImpl; impl ::selectors::SelectorImpl for SelectorImpl { type ExtraMatchingData = InvalidationMatchingData; - type AttrValue = Atom; - type Identifier = Atom; - type ClassName = Atom; - type PartName = Atom; - type LocalName = Atom; - type NamespacePrefix = Atom; + type AttrValue = AtomString; + type Identifier = AtomIdent; + type LocalName = AtomIdent; + type NamespacePrefix = AtomIdent; type NamespaceUrl = Namespace; type BorrowedNamespaceUrl = WeakNamespace; type BorrowedLocalName = WeakAtom; @@ -386,7 +384,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { let pseudo_class = match_ignore_ascii_case! { &name, "lang" => { let name = parser.expect_ident_or_string()?; - NonTSPseudoClass::Lang(Atom::from(name.as_ref())) + NonTSPseudoClass::Lang(Lang::from(name.as_ref())) }, "-moz-locale-dir" => { NonTSPseudoClass::MozLocaleDir(Direction::parse(parser)?) @@ -475,7 +473,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { self.namespaces.default.clone() } - fn namespace_for_prefix(&self, prefix: &Atom) -> Option<Namespace> { + fn namespace_for_prefix(&self, prefix: &AtomIdent) -> Option<Namespace> { self.namespaces.prefixes.get(prefix).cloned() } } diff --git a/components/style/gecko/snapshot.rs b/components/style/gecko/snapshot.rs index 26b3e1393dd..8ff794a4d8c 100644 --- a/components/style/gecko/snapshot.rs +++ b/components/style/gecko/snapshot.rs @@ -14,7 +14,10 @@ use crate::gecko_bindings::structs::ServoElementSnapshot; use crate::gecko_bindings::structs::ServoElementSnapshotFlags as Flags; use crate::gecko_bindings::structs::ServoElementSnapshotTable; use crate::invalidation::element::element_wrapper::ElementSnapshot; +use crate::selector_parser::AttrValue; use crate::string_cache::{Atom, Namespace}; +use crate::values::{AtomIdent, AtomString}; +use crate::LocalName; use crate::WeakAtom; use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator}; use selectors::attr::{CaseSensitivity, NamespaceConstraint}; @@ -74,10 +77,10 @@ impl GeckoElementSnapshot { #[inline] pub fn each_attr_changed<F>(&self, mut callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { for attr in self.mChangedAttrNames.iter() { - unsafe { Atom::with(attr.mRawPtr, &mut callback) } + unsafe { AtomIdent::with(attr.mRawPtr, &mut callback) } } } @@ -85,8 +88,8 @@ impl GeckoElementSnapshot { pub fn attr_matches( &self, ns: &NamespaceConstraint<&Namespace>, - local_name: &Atom, - operation: &AttrSelectorOperation<&Atom>, + local_name: &LocalName, + operation: &AttrSelectorOperation<&AttrValue>, ) -> bool { unsafe { match *operation { @@ -188,7 +191,7 @@ impl ElementSnapshot for GeckoElementSnapshot { } #[inline] - fn is_part(&self, name: &Atom) -> bool { + fn is_part(&self, name: &AtomIdent) -> bool { let attr = match snapshot_helpers::find_attr(&*self.mAttrs, &atom!("part")) { Some(attr) => attr, None => return false, @@ -198,12 +201,12 @@ impl ElementSnapshot for GeckoElementSnapshot { } #[inline] - fn imported_part(&self, name: &Atom) -> Option<Atom> { + fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> { snapshot_helpers::imported_part(&*self.mAttrs, name) } #[inline] - fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { + fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool { if !self.has_any(Flags::MaybeClass) { return false; } @@ -214,7 +217,7 @@ impl ElementSnapshot for GeckoElementSnapshot { #[inline] fn each_class<F>(&self, callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { if !self.has_any(Flags::MaybeClass) { return; @@ -224,12 +227,12 @@ impl ElementSnapshot for GeckoElementSnapshot { } #[inline] - fn lang_attr(&self) -> Option<Atom> { + fn lang_attr(&self) -> Option<AtomString> { let ptr = unsafe { bindings::Gecko_SnapshotLangValue(self) }; if ptr.is_null() { None } else { - Some(unsafe { Atom::from_addrefed(ptr) }) + Some(AtomString(unsafe { Atom::from_addrefed(ptr) })) } } } diff --git a/components/style/gecko/snapshot_helpers.rs b/components/style/gecko/snapshot_helpers.rs index bd905870353..ee8d7dfd704 100644 --- a/components/style/gecko/snapshot_helpers.rs +++ b/components/style/gecko/snapshot_helpers.rs @@ -6,7 +6,9 @@ use crate::gecko_bindings::bindings; use crate::gecko_bindings::structs::{self, nsAtom}; -use crate::string_cache::{Atom, WeakAtom}; +use crate::string_cache::WeakAtom; +use crate::values::AtomIdent; +use crate::Atom; use crate::CaseSensitivityExt; use selectors::attr::CaseSensitivity; @@ -85,8 +87,8 @@ pub fn get_id(attrs: &[structs::AttrArray_InternalAttr]) -> Option<&WeakAtom> { #[inline(always)] pub(super) fn each_exported_part( attrs: &[structs::AttrArray_InternalAttr], - name: &Atom, - mut callback: impl FnMut(&Atom), + name: &AtomIdent, + mut callback: impl FnMut(&AtomIdent), ) { let attr = match find_attr(attrs, &atom!("exportparts")) { Some(attr) => attr, @@ -100,7 +102,7 @@ pub(super) fn each_exported_part( unsafe { for atom in std::slice::from_raw_parts(atoms, length) { - Atom::with(*atom, &mut callback) + AtomIdent::with(*atom, &mut callback) } } } @@ -108,21 +110,21 @@ pub(super) fn each_exported_part( #[inline(always)] pub(super) fn imported_part( attrs: &[structs::AttrArray_InternalAttr], - name: &Atom, -) -> Option<Atom> { + name: &AtomIdent, +) -> Option<AtomIdent> { let attr = find_attr(attrs, &atom!("exportparts"))?; let atom = unsafe { bindings::Gecko_Element_ImportedPart(attr, name.as_ptr()) }; if atom.is_null() { return None; } - Some(unsafe { Atom::from_raw(atom) }) + Some(AtomIdent(unsafe { Atom::from_raw(atom) })) } /// Given a class or part name, a case sensitivity, and an array of attributes, /// returns whether the attribute has that name. #[inline(always)] pub fn has_class_or_part( - name: &Atom, + name: &AtomIdent, case_sensitivity: CaseSensitivity, attr: &structs::nsAttrValue, ) -> bool { @@ -147,15 +149,15 @@ pub fn has_class_or_part( #[inline(always)] pub fn each_class_or_part<F>(attr: &structs::nsAttrValue, mut callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { unsafe { match get_class_or_part_from_attr(attr) { Class::None => {}, - Class::One(atom) => Atom::with(atom, callback), + Class::One(atom) => AtomIdent::with(atom, callback), Class::More(atoms) => { for atom in atoms { - Atom::with(atom.mRawPtr, &mut callback) + AtomIdent::with(atom.mRawPtr, &mut callback) } }, } diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 847b822b28d..4773bd89997 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -70,7 +70,9 @@ use crate::stylist::CascadeData; use crate::values::computed::font::GenericFontFamily; use crate::values::computed::Length; use crate::values::specified::length::FontBaseSize; +use crate::values::{AtomIdent, AtomString}; use crate::CaseSensitivityExt; +use crate::LocalName; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator}; use selectors::attr::{CaseSensitivity, NamespaceConstraint}; @@ -130,7 +132,7 @@ impl<'ld> TDocument for GeckoDocument<'ld> { } #[inline] - fn elements_with_id<'a>(&self, id: &Atom) -> Result<&'a [GeckoElement<'ld>], ()> + fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoElement<'ld>], ()> where Self: 'a, { @@ -186,7 +188,7 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> { } #[inline] - fn elements_with_id<'a>(&self, id: &Atom) -> Result<&'a [GeckoElement<'lr>], ()> + fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoElement<'lr>], ()> where Self: 'a, { @@ -801,7 +803,7 @@ impl<'le> GeckoElement<'le> { return false; } let host = self.containing_shadow_host().unwrap(); - host.is_svg_element() && host.local_name() == &*local_name!("use") + host.is_svg_element() && host.local_name() == &**local_name!("use") } fn css_transitions_info(&self) -> FxHashMap<LonghandId, Arc<AnimationValue>> { @@ -1270,7 +1272,7 @@ impl<'le> TElement for GeckoElement<'le> { } #[inline] - fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool { + fn has_attr(&self, namespace: &Namespace, attr: &AtomIdent) -> bool { unsafe { bindings::Gecko_HasAttr(self.0, namespace.0.as_ptr(), attr.as_ptr()) } } @@ -1297,7 +1299,7 @@ impl<'le> TElement for GeckoElement<'le> { fn each_class<F>(&self, callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { let attr = match self.get_class_attr() { Some(c) => c, @@ -1308,16 +1310,16 @@ impl<'le> TElement for GeckoElement<'le> { } #[inline] - fn each_exported_part<F>(&self, name: &Atom, callback: F) + fn each_exported_part<F>(&self, name: &AtomIdent, callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { snapshot_helpers::each_exported_part(self.attrs(), name, callback) } fn each_part<F>(&self, callback: F) where - F: FnMut(&Atom), + F: FnMut(&AtomIdent), { let attr = match self.get_part_attr() { Some(c) => c, @@ -1615,7 +1617,7 @@ impl<'le> TElement for GeckoElement<'le> { if ptr.is_null() { None } else { - Some(unsafe { Atom::from_addrefed(ptr) }) + Some(AtomString(unsafe { Atom::from_addrefed(ptr) })) } } @@ -1623,8 +1625,8 @@ impl<'le> TElement for GeckoElement<'le> { // Gecko supports :lang() from CSS Selectors 3, which only accepts a // single language tag, and which performs simple dash-prefix matching // on it. - let override_lang_ptr = match &override_lang { - &Some(Some(ref atom)) => atom.as_ptr(), + let override_lang_ptr = match override_lang { + Some(Some(ref atom)) => atom.as_ptr(), _ => ptr::null_mut(), }; unsafe { @@ -1638,7 +1640,7 @@ impl<'le> TElement for GeckoElement<'le> { } fn is_html_document_body_element(&self) -> bool { - if self.local_name() != &*local_name!("body") { + if self.local_name() != &**local_name!("body") { return false; } @@ -1895,8 +1897,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { fn attr_matches( &self, ns: &NamespaceConstraint<&Namespace>, - local_name: &Atom, - operation: &AttrSelectorOperation<&Atom>, + local_name: &LocalName, + operation: &AttrSelectorOperation<&AttrValue>, ) -> bool { unsafe { match *operation { @@ -2180,7 +2182,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } #[inline] - fn has_id(&self, id: &Atom, case_sensitivity: CaseSensitivity) -> bool { + fn has_id(&self, id: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool { if !self.has_id() { return false; } @@ -2194,7 +2196,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } #[inline] - fn is_part(&self, name: &Atom) -> bool { + fn is_part(&self, name: &AtomIdent) -> bool { let attr = match self.get_part_attr() { Some(c) => c, None => return false, @@ -2204,12 +2206,12 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } #[inline] - fn imported_part(&self, name: &Atom) -> Option<Atom> { + fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> { snapshot_helpers::imported_part(self.attrs(), name) } #[inline(always)] - fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { + fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool { let attr = match self.get_class_attr() { Some(c) => c, None => return false, diff --git a/components/style/gecko_string_cache/mod.rs b/components/style/gecko_string_cache/mod.rs index e9208a5e32e..a6cf017877d 100644 --- a/components/style/gecko_string_cache/mod.rs +++ b/components/style/gecko_string_cache/mod.rs @@ -42,12 +42,6 @@ pub mod namespace; pub use self::namespace::{Namespace, WeakNamespace}; -macro_rules! local_name { - ($s:tt) => { - atom!($s) - }; -} - /// A handle to a Gecko atom. This is a type that can represent either: /// /// * A strong reference to a dynamic atom (an `nsAtom` pointer), in which case diff --git a/components/style/gecko_string_cache/namespace.rs b/components/style/gecko_string_cache/namespace.rs index 72de229f1d7..1acf04c93ff 100644 --- a/components/style/gecko_string_cache/namespace.rs +++ b/components/style/gecko_string_cache/namespace.rs @@ -47,18 +47,9 @@ impl PrecomputedHash for Namespace { } /// A Gecko WeakNamespace is a wrapped WeakAtom. -#[derive(Hash)] +#[derive(Hash, Deref)] pub struct WeakNamespace(WeakAtom); -impl Deref for WeakNamespace { - type Target = WeakAtom; - - #[inline] - fn deref(&self) -> &WeakAtom { - &self.0 - } -} - impl Deref for Namespace { type Target = WeakNamespace; diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index 2b6f934c8b7..953c07f46c7 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -9,7 +9,8 @@ use crate::dom::TElement; use crate::element_state::ElementState; use crate::selector_parser::{AttrValue, NonTSPseudoClass, PseudoElement, SelectorImpl}; use crate::selector_parser::{Snapshot, SnapshotMap}; -use crate::{Atom, CaseSensitivityExt, LocalName, Namespace, WeakAtom}; +use crate::values::AtomIdent; +use crate::{CaseSensitivityExt, LocalName, Namespace, WeakAtom}; use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint}; use selectors::matching::{ElementSelectorFlags, MatchingContext}; use selectors::{Element, OpaqueElement}; @@ -56,20 +57,20 @@ pub trait ElementSnapshot: Sized { /// Whether this snapshot contains the class `name`. Should only be called /// if `has_attrs()` returns true. - fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool; + fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool; /// Whether this snapshot represents the part named `name`. Should only be /// called if `has_attrs()` returns true. - fn is_part(&self, name: &Atom) -> bool; + fn is_part(&self, name: &AtomIdent) -> bool; /// See Element::imported_part. - fn imported_part(&self, name: &Atom) -> Option<Atom>; + fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent>; /// A callback that should be called for each class of the snapshot. Should /// only be called if `has_attrs()` returns true. fn each_class<F>(&self, _: F) where - F: FnMut(&Atom); + F: FnMut(&AtomIdent); /// The `xml:lang=""` or `lang=""` attribute value per this snapshot. fn lang_attr(&self) -> Option<AttrValue>; @@ -361,7 +362,7 @@ where } } - fn has_id(&self, id: &Atom, case_sensitivity: CaseSensitivity) -> bool { + fn has_id(&self, id: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool { match self.snapshot() { Some(snapshot) if snapshot.has_attrs() => snapshot .id_attr() @@ -370,21 +371,21 @@ where } } - fn is_part(&self, name: &Atom) -> bool { + fn is_part(&self, name: &AtomIdent) -> bool { match self.snapshot() { Some(snapshot) if snapshot.has_attrs() => snapshot.is_part(name), _ => self.element.is_part(name), } } - fn imported_part(&self, name: &Atom) -> Option<Atom> { + fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> { match self.snapshot() { Some(snapshot) if snapshot.has_attrs() => snapshot.imported_part(name), _ => self.element.imported_part(name), } } - fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { + fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool { match self.snapshot() { Some(snapshot) if snapshot.has_attrs() => snapshot.has_class(name, case_sensitivity), _ => self.element.has_class(name, case_sensitivity), diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index ea08bb4f4fb..29e0962a897 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -478,7 +478,7 @@ impl<'a> SelectorVisitor for SelectorDependencyCollector<'a> { Component::Class(..) => &mut self.map.class_to_selector, _ => unreachable!(), }; - let entry = match map.try_entry(atom.clone(), self.quirks_mode) { + let entry = match map.try_entry(atom.0.clone(), self.quirks_mode) { Ok(entry) => entry, Err(err) => { *self.alloc_error = Some(err); diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index 79f1b53ada7..128feae76be 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -216,13 +216,13 @@ where // TODO(emilio): Do this more efficiently! snapshot.each_class(|c| { if !element.has_class(c, CaseSensitivity::CaseSensitive) { - classes_removed.push(c.clone()) + classes_removed.push(c.0.clone()) } }); element.each_class(|c| { if !snapshot.has_class(c, CaseSensitivity::CaseSensitive) { - classes_added.push(c.clone()) + classes_added.push(c.0.clone()) } }) } diff --git a/components/style/invalidation/stylesheets.rs b/components/style/invalidation/stylesheets.rs index 8ac2b57b34e..9854387ccad 100644 --- a/components/style/invalidation/stylesheets.rs +++ b/components/style/invalidation/stylesheets.rs @@ -17,6 +17,7 @@ use crate::selector_parser::{SelectorImpl, Snapshot, SnapshotMap}; use crate::shared_lock::SharedRwLockReadGuard; use crate::stylesheets::{CssRule, StylesheetInDocument}; use crate::stylesheets::{EffectiveRules, EffectiveRulesIterator}; +use crate::values::AtomIdent; use crate::Atom; use crate::LocalName as SelectorLocalName; use selectors::parser::{Component, LocalName, Selector}; @@ -43,9 +44,9 @@ pub enum RuleChangeKind { #[derive(Debug, Eq, Hash, MallocSizeOf, PartialEq)] enum Invalidation { /// An element with a given id. - ID(Atom), + ID(AtomIdent), /// An element with a given class name. - Class(Atom), + Class(AtomIdent), /// An element with a given local name. LocalName { name: SelectorLocalName, @@ -468,14 +469,14 @@ impl StylesheetInvalidationSet { ) -> bool { match invalidation { Invalidation::Class(c) => { - let entry = match self.classes.try_entry(c, quirks_mode) { + let entry = match self.classes.try_entry(c.0, quirks_mode) { Ok(e) => e, Err(..) => return false, }; *entry.or_insert(InvalidationKind::None) |= kind; }, Invalidation::ID(i) => { - let entry = match self.ids.try_entry(i, quirks_mode) { + let entry = match self.ids.try_entry(i.0, quirks_mode) { Ok(e) => e, Err(..) => return false, }; diff --git a/components/style/lib.rs b/components/style/lib.rs index 8b8af1073ae..f1d36b2722c 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -131,10 +131,10 @@ pub use crate::gecko_string_cache as string_cache; pub use crate::gecko_string_cache::Atom; /// The namespace prefix type for Gecko, which is just an atom. #[cfg(feature = "gecko")] -pub type Prefix = crate::gecko_string_cache::Atom; +pub type Prefix = crate::values::AtomIdent; /// The local name of an element for Gecko, which is just an atom. #[cfg(feature = "gecko")] -pub type LocalName = crate::gecko_string_cache::Atom; +pub type LocalName = crate::values::AtomIdent; #[cfg(feature = "gecko")] pub use crate::gecko_string_cache::Namespace; diff --git a/components/style/macros.rs b/components/style/macros.rs index b4f4f1f7caf..e60be8efc5f 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -133,3 +133,10 @@ macro_rules! profiler_label { macro_rules! profiler_label { ($label_type:ident) => {}; } + +#[cfg(feature = "gecko")] +macro_rules! local_name { + ($s:tt) => { + $crate::values::AtomIdent(atom!($s)) + }; +} diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs index 884abc07c63..86293e5c785 100644 --- a/components/style/rule_collector.rs +++ b/components/style/rule_collector.rs @@ -13,7 +13,6 @@ use crate::selector_parser::PseudoElement; use crate::shared_lock::Locked; use crate::stylesheets::Origin; use crate::stylist::{AuthorStylesEnabled, Rule, RuleInclusion, Stylist}; -use crate::Atom; use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode}; use servo_arc::ArcBorrow; use smallvec::SmallVec; @@ -43,7 +42,7 @@ pub fn containing_shadow_ignoring_svg_use<E: TElement>( loop { let host = shadow.host(); let host_is_svg_use_element = - host.is_svg_element() && host.local_name() == &*local_name!("use"); + host.is_svg_element() && host.local_name() == &**local_name!("use"); if !host_is_svg_use_element { return Some(shadow); } @@ -319,7 +318,7 @@ where }; hash_target.each_part(|part| { - if let Some(part_rules) = part_rules.get(part) { + if let Some(part_rules) = part_rules.get(&part.0) { collector.collect_rules_in_list(part_rules, cascade_level); } }); @@ -377,7 +376,7 @@ where let mut shadow_cascade_order = ShadowCascadeOrder::for_innermost_containing_tree(); - let mut parts = SmallVec::<[Atom; 3]>::new(); + let mut parts = SmallVec::<[_; 3]>::new(); self.rule_hash_target.each_part(|p| parts.push(p.clone())); loop { @@ -405,7 +404,7 @@ where }; self.in_tree(containing_host, |collector| { for p in &parts { - if let Some(part_rules) = part_rules.get(p) { + if let Some(part_rules) = part_rules.get(&p.0) { collector.collect_rules_in_list(part_rules, cascade_level); } } diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index fab21901bd9..9adb7afb8cd 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -73,7 +73,7 @@ use crate::properties::ComputedValues; use crate::rule_tree::StrongRuleNode; use crate::style_resolver::{PrimaryStyle, ResolvedElementStyles}; use crate::stylist::Stylist; -use crate::Atom; +use crate::values::AtomIdent; use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use owning_ref::OwningHandle; use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode}; @@ -126,13 +126,13 @@ pub struct ValidationData { /// /// TODO(emilio): Maybe check whether rules for these classes apply to the /// element? - class_list: Option<SmallVec<[Atom; 5]>>, + class_list: Option<SmallVec<[AtomIdent; 5]>>, /// The part list of this element. /// /// TODO(emilio): Maybe check whether rules with these part names apply to /// the element? - part_list: Option<SmallVec<[Atom; 5]>>, + part_list: Option<SmallVec<[AtomIdent; 5]>>, /// The list of presentational attributes of the element. pres_hints: Option<SmallVec<[ApplicableDeclarationBlock; 5]>>, @@ -168,7 +168,7 @@ impl ValidationData { } /// Get or compute the part-list associated with this element. - pub fn part_list<E>(&mut self, element: E) -> &[Atom] + pub fn part_list<E>(&mut self, element: E) -> &[AtomIdent] where E: TElement, { @@ -176,7 +176,7 @@ impl ValidationData { return &[]; } self.part_list.get_or_insert_with(|| { - let mut list = SmallVec::<[Atom; 5]>::new(); + let mut list = SmallVec::<[_; 5]>::new(); element.each_part(|p| list.push(p.clone())); // See below for the reasoning. if !list.spilled() { @@ -187,12 +187,12 @@ impl ValidationData { } /// Get or compute the class-list associated with this element. - pub fn class_list<E>(&mut self, element: E) -> &[Atom] + pub fn class_list<E>(&mut self, element: E) -> &[AtomIdent] where E: TElement, { self.class_list.get_or_insert_with(|| { - let mut list = SmallVec::<[Atom; 5]>::new(); + let mut list = SmallVec::<[_; 5]>::new(); element.each_class(|c| list.push(c.clone())); // Assuming there are a reasonable number of classes (we use the // inline capacity as "reasonable number"), sort them to so that @@ -294,12 +294,12 @@ impl<E: TElement> Deref for StyleSharingCandidate<E> { impl<E: TElement> StyleSharingCandidate<E> { /// Get the classlist of this candidate. - fn class_list(&mut self) -> &[Atom] { + fn class_list(&mut self) -> &[AtomIdent] { self.validation_data.class_list(self.element) } /// Get the part list of this candidate. - fn part_list(&mut self) -> &[Atom] { + fn part_list(&mut self) -> &[AtomIdent] { self.validation_data.part_list(self.element) } @@ -361,11 +361,11 @@ impl<E: TElement> StyleSharingTarget<E> { } } - fn class_list(&mut self) -> &[Atom] { + fn class_list(&mut self) -> &[AtomIdent] { self.validation_data.class_list(self.element) } - fn part_list(&mut self) -> &[Atom] { + fn part_list(&mut self) -> &[AtomIdent] { self.validation_data.part_list(self.element) } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index db950397c37..cc0c4a21d72 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -806,7 +806,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { return; } let is_html_select_element = element.map_or(false, |e| { - e.is_html_element() && e.local_name() == &*local_name!("select") + e.is_html_element() && e.local_name() == &*atom!("select") }); if !is_html_select_element { return; diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 8cf9efb3927..418a86bc5e0 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -1651,7 +1651,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> { // // NOTE(emilio): See the comment regarding on when this may // break in visit_complex_selector. - self.mapped_ids.insert(id.clone()); + self.mapped_ids.insert(id.0.clone()); }, _ => {}, } @@ -2078,7 +2078,7 @@ impl CascadeData { self.part_rules .get_or_insert_with(|| Box::new(Default::default())) .for_insertion(pseudo_element) - .try_entry(parts.last().unwrap().clone())? + .try_entry(parts.last().unwrap().clone().0)? .or_insert_with(SmallVec::new) .try_push(rule)?; } else { diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 36ea909ab87..6c088535d7f 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -13,6 +13,7 @@ use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::Atom; pub use cssparser::{serialize_identifier, serialize_name, CowRcStr, Parser}; pub use cssparser::{SourceLocation, Token, RGBA}; +use precomputed_hash::PrecomputedHash; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Debug, Write}; use std::hash; @@ -84,6 +85,112 @@ where serialize_name(&ident, dest) } +/// A CSS string stored as an `Atom`. +#[repr(transparent)] +#[derive( + Clone, + Debug, + Default, + Deref, + Eq, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct AtomString(pub Atom); + +impl cssparser::ToCss for AtomString { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result + where + W: Write, + { + self.0 + .with_str(|s| cssparser::CssStringWriter::new(dest).write_str(s)) + } +} + +impl PrecomputedHash for AtomString { + #[inline] + fn precomputed_hash(&self) -> u32 { + self.0.precomputed_hash() + } +} + +impl<'a> From<&'a str> for AtomString { + #[inline] + fn from(string: &str) -> Self { + Self(Atom::from(string)) + } +} + +/// A CSS `<ident>` stored as an `Atom`. +#[repr(transparent)] +#[derive( + Clone, + Debug, + Default, + Deref, + Eq, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct AtomIdent(pub Atom); + +impl cssparser::ToCss for AtomIdent { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result + where + W: Write, + { + serialize_atom_identifier(&self.0, dest) + } +} + +impl PrecomputedHash for AtomIdent { + #[inline] + fn precomputed_hash(&self) -> u32 { + self.0.precomputed_hash() + } +} + +impl<'a> From<&'a str> for AtomIdent { + #[inline] + fn from(string: &str) -> Self { + Self(Atom::from(string)) + } +} + +impl AtomIdent { + /// Like `Atom::with` but for `AtomIdent`. + #[cfg(feature = "gecko")] + pub unsafe fn with<F, R>(ptr: *const crate::gecko_bindings::structs::nsAtom, callback: F) -> R + where + F: FnOnce(&Self) -> R, + { + Atom::with(ptr, |atom: &Atom| { + // safety: repr(transparent) + let atom = atom as *const Atom as *const AtomIdent; + callback(&*atom) + }) + } +} + +#[cfg(feature = "gecko")] +impl std::borrow::Borrow<crate::gecko_string_cache::WeakAtom> for AtomIdent { + #[inline] + fn borrow(&self) -> &crate::gecko_string_cache::WeakAtom { + self.0.borrow() + } +} + /// Serialize a normalized value into percentage. pub fn serialize_percentage<W>(value: CSSFloat, dest: &mut CssWriter<W>) -> fmt::Result where |