aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2020-11-22 01:02:22 +0000
committerEmilio Cobos Álvarez <emilio@crisal.io>2021-02-26 16:44:05 +0100
commit9f40b9ba38a531088c2117b955f40af6ea0d09c8 (patch)
treee221662df58ec16b2c2027d71fd5df015fe3f526
parent4ea378a6ae232af09135b2037c527466ef5454de (diff)
downloadservo-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.rs15
-rw-r--r--components/style/dom_apis.rs8
-rw-r--r--components/style/gecko/selector_parser.rs20
-rw-r--r--components/style/gecko/snapshot.rs23
-rw-r--r--components/style/gecko/snapshot_helpers.rs24
-rw-r--r--components/style/gecko/wrapper.rs38
-rw-r--r--components/style/gecko_string_cache/mod.rs6
-rw-r--r--components/style/gecko_string_cache/namespace.rs11
-rw-r--r--components/style/invalidation/element/element_wrapper.rs19
-rw-r--r--components/style/invalidation/element/invalidation_map.rs2
-rw-r--r--components/style/invalidation/element/state_and_attributes.rs4
-rw-r--r--components/style/invalidation/stylesheets.rs9
-rw-r--r--components/style/lib.rs4
-rw-r--r--components/style/macros.rs7
-rw-r--r--components/style/rule_collector.rs9
-rw-r--r--components/style/sharing/mod.rs22
-rw-r--r--components/style/style_adjuster.rs2
-rw-r--r--components/style/stylist.rs4
-rw-r--r--components/style/values/mod.rs107
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