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
This commit is contained in:
Emilio Cobos Álvarez 2020-11-22 01:02:22 +00:00
parent 4ea378a6ae
commit 9f40b9ba38
19 changed files with 220 additions and 114 deletions

View file

@ -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),

View file

@ -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);

View file

@ -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())
}
})
}