style: Make Element::id not clone the attribute.

This commit is contained in:
Emilio Cobos Álvarez 2018-02-24 21:49:43 +01:00
parent 98c9292ecb
commit f2efd04a5d
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
10 changed files with 46 additions and 37 deletions

View file

@ -341,7 +341,7 @@ pub struct ServoLayoutElement<'le> {
impl<'le> fmt::Debug for ServoLayoutElement<'le> { impl<'le> fmt::Debug for ServoLayoutElement<'le> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<{}", self.element.local_name())?; write!(f, "<{}", self.element.local_name())?;
if let &Some(ref id) = unsafe { &*self.element.id_attribute() } { if let Some(id) = self.id() {
write!(f, " id={}", id)?; write!(f, " id={}", id)?;
} }
write!(f, "> ({:#x})", self.as_node().opaque().0) write!(f, "> ({:#x})", self.as_node().opaque().0)
@ -382,9 +382,9 @@ impl<'le> TElement for ServoLayoutElement<'le> {
} }
#[inline] #[inline]
fn id(&self) -> Option<Atom> { fn id(&self) -> Option<&Atom> {
unsafe { unsafe {
(*self.element.id_attribute()).clone() (*self.element.id_attribute()).as_ref()
} }
} }

View file

@ -7,7 +7,7 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
use {Atom, Namespace, LocalName}; use {Atom, Namespace, LocalName, WeakAtom};
use applicable_declarations::ApplicableDeclarationBlock; use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
#[cfg(feature = "gecko")] use context::PostAnimationTasks; #[cfg(feature = "gecko")] use context::PostAnimationTasks;
@ -467,7 +467,7 @@ pub trait TElement
fn has_attr(&self, namespace: &Namespace, attr: &LocalName) -> bool; fn has_attr(&self, namespace: &Namespace, attr: &LocalName) -> bool;
/// The ID for this element. /// The ID for this element.
fn id(&self) -> Option<Atom>; fn id(&self) -> Option<&WeakAtom>;
/// Internal iterator for the classes of this element. /// Internal iterator for the classes of this element.
fn each_class<F>(&self, callback: F) where F: FnMut(&Atom); fn each_class<F>(&self, callback: F) where F: FnMut(&Atom);

View file

@ -5,6 +5,7 @@
//! A gecko snapshot, that stores the element attributes and state before they //! A gecko snapshot, that stores the element attributes and state before they
//! change in order to properly calculate restyle hints. //! change in order to properly calculate restyle hints.
use WeakAtom;
use dom::TElement; use dom::TElement;
use element_state::ElementState; use element_state::ElementState;
use gecko::snapshot_helpers; use gecko::snapshot_helpers;
@ -80,17 +81,20 @@ impl GeckoElementSnapshot {
} }
/// selectors::Element::attr_matches /// selectors::Element::attr_matches
pub fn attr_matches(&self, pub fn attr_matches(
ns: &NamespaceConstraint<&Namespace>, &self,
local_name: &Atom, ns: &NamespaceConstraint<&Namespace>,
operation: &AttrSelectorOperation<&Atom>) local_name: &Atom,
-> bool { operation: &AttrSelectorOperation<&Atom>,
) -> bool {
unsafe { unsafe {
match *operation { match *operation {
AttrSelectorOperation::Exists => { AttrSelectorOperation::Exists => {
bindings:: Gecko_SnapshotHasAttr(self, bindings:: Gecko_SnapshotHasAttr(
ns.atom_or_null(), self,
local_name.as_ptr()) ns.atom_or_null(),
local_name.as_ptr(),
)
} }
AttrSelectorOperation::WithValue { operator, case_sensitivity, expected_value } => { AttrSelectorOperation::WithValue { operator, case_sensitivity, expected_value } => {
let ignore_case = match case_sensitivity { let ignore_case = match case_sensitivity {
@ -163,7 +167,7 @@ impl ElementSnapshot for GeckoElementSnapshot {
} }
#[inline] #[inline]
fn id_attr(&self) -> Option<Atom> { fn id_attr(&self) -> Option<&WeakAtom> {
if !self.has_any(Flags::Id) { if !self.has_any(Flags::Id) {
return None return None
} }
@ -172,10 +176,11 @@ impl ElementSnapshot for GeckoElementSnapshot {
bindings::Gecko_SnapshotAtomAttrValue(self, atom!("id").as_ptr()) bindings::Gecko_SnapshotAtomAttrValue(self, atom!("id").as_ptr())
}; };
// FIXME(emilio): This should assert, since this flag is exact.
if ptr.is_null() { if ptr.is_null() {
None None
} else { } else {
Some(Atom::from(ptr)) Some(unsafe { WeakAtom::new(ptr) })
} }
} }

View file

@ -1176,7 +1176,7 @@ impl<'le> TElement for GeckoElement<'le> {
// FIXME(emilio): we should probably just return a reference to the Atom. // FIXME(emilio): we should probably just return a reference to the Atom.
#[inline] #[inline]
fn id(&self) -> Option<Atom> { fn id(&self) -> Option<&WeakAtom> {
if !self.has_id() { if !self.has_id() {
return None; return None;
} }
@ -1185,10 +1185,12 @@ impl<'le> TElement for GeckoElement<'le> {
bindings::Gecko_AtomAttrValue(self.0, atom!("id").as_ptr()) bindings::Gecko_AtomAttrValue(self.0, atom!("id").as_ptr())
}; };
// FIXME(emilio): Pretty sure the has_id flag is exact and we could
// assert here.
if ptr.is_null() { if ptr.is_null() {
None None
} else { } else {
Some(Atom::from(ptr)) Some(unsafe { WeakAtom::new(ptr) })
} }
} }

View file

@ -5,7 +5,7 @@
//! A wrapper over an element and a snapshot, that allows us to selector-match //! A wrapper over an element and a snapshot, that allows us to selector-match
//! against a past state of the element. //! against a past state of the element.
use {Atom, CaseSensitivityExt, LocalName, Namespace}; use {Atom, CaseSensitivityExt, LocalName, Namespace, WeakAtom};
use dom::TElement; use dom::TElement;
use element_state::ElementState; use element_state::ElementState;
use selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl, Snapshot, SnapshotMap, AttrValue}; use selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl, Snapshot, SnapshotMap, AttrValue};
@ -44,7 +44,7 @@ pub trait ElementSnapshot : Sized {
/// The ID attribute per this snapshot. Should only be called if /// The ID attribute per this snapshot. Should only be called if
/// `has_attrs()` returns true. /// `has_attrs()` returns true.
fn id_attr(&self) -> Option<Atom>; fn id_attr(&self) -> Option<&WeakAtom>;
/// Whether this snapshot contains the class `name`. Should only be called /// Whether this snapshot contains the class `name`. Should only be called
/// if `has_attrs()` returns true. /// if `has_attrs()` returns true.
@ -53,7 +53,8 @@ pub trait ElementSnapshot : Sized {
/// A callback that should be called for each class of the snapshot. Should /// A callback that should be called for each class of the snapshot. Should
/// only be called if `has_attrs()` returns true. /// only be called if `has_attrs()` returns true.
fn each_class<F>(&self, F) fn each_class<F>(&self, F)
where F: FnMut(&Atom); where
F: FnMut(&Atom);
/// The `xml:lang=""` or `lang=""` attribute value per this snapshot. /// The `xml:lang=""` or `lang=""` attribute value per this snapshot.
fn lang_attr(&self) -> Option<AttrValue>; fn lang_attr(&self) -> Option<AttrValue>;
@ -63,7 +64,8 @@ pub trait ElementSnapshot : Sized {
/// selector-match against a past state of the element. /// selector-match against a past state of the element.
#[derive(Clone)] #[derive(Clone)]
pub struct ElementWrapper<'a, E> pub struct ElementWrapper<'a, E>
where E: TElement, where
E: TElement,
{ {
element: E, element: E,
cached_snapshot: Cell<Option<&'a Snapshot>>, cached_snapshot: Cell<Option<&'a Snapshot>>,

View file

@ -5,7 +5,7 @@
//! An invalidation processor for style changes due to state and attribute //! An invalidation processor for style changes due to state and attribute
//! changes. //! changes.
use Atom; use {Atom, WeakAtom};
use context::{QuirksMode, SharedStyleContext}; use context::{QuirksMode, SharedStyleContext};
use data::ElementData; use data::ElementData;
use dom::TElement; use dom::TElement;
@ -42,8 +42,8 @@ where
snapshot: &'a Snapshot, snapshot: &'a Snapshot,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
lookup_element: E, lookup_element: E,
removed_id: Option<&'a Atom>, removed_id: Option<&'a WeakAtom>,
added_id: Option<&'a Atom>, added_id: Option<&'a WeakAtom>,
classes_removed: &'a SmallVec<[Atom; 8]>, classes_removed: &'a SmallVec<[Atom; 8]>,
classes_added: &'a SmallVec<[Atom; 8]>, classes_added: &'a SmallVec<[Atom; 8]>,
state_changes: ElementState, state_changes: ElementState,
@ -239,8 +239,8 @@ where
snapshot: &snapshot, snapshot: &snapshot,
quirks_mode: self.shared_context.quirks_mode(), quirks_mode: self.shared_context.quirks_mode(),
nth_index_cache: self.matching_context.nth_index_cache.as_mut().map(|c| &mut **c), nth_index_cache: self.matching_context.nth_index_cache.as_mut().map(|c| &mut **c),
removed_id: id_removed.as_ref(), removed_id: id_removed,
added_id: id_added.as_ref(), added_id: id_added,
classes_removed: &classes_removed, classes_removed: &classes_removed,
classes_added: &classes_added, classes_added: &classes_added,
descendant_invalidations, descendant_invalidations,

View file

@ -5,7 +5,7 @@
//! A data structure to efficiently index structs containing selectors by local //! A data structure to efficiently index structs containing selectors by local
//! name, ids and hash. //! name, ids and hash.
use {Atom, LocalName}; use {Atom, LocalName, WeakAtom};
use applicable_declarations::ApplicableDeclarationList; use applicable_declarations::ApplicableDeclarationList;
use context::QuirksMode; use context::QuirksMode;
use dom::TElement; use dom::TElement;
@ -176,7 +176,7 @@ impl SelectorMap<Rule> {
// where we began. // where we began.
let init_len = matching_rules_list.len(); let init_len = matching_rules_list.len();
if let Some(id) = rule_hash_target.id() { if let Some(id) = rule_hash_target.id() {
if let Some(rules) = self.id_hash.get(&id, quirks_mode) { if let Some(rules) = self.id_hash.get(id, quirks_mode) {
SelectorMap::get_matching_rules( SelectorMap::get_matching_rules(
element, element,
rules, rules,
@ -316,7 +316,7 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
{ {
// Id. // Id.
if let Some(id) = element.id() { if let Some(id) = element.id() {
if let Some(v) = self.id_hash.get(&id, quirks_mode) { if let Some(v) = self.id_hash.get(id, quirks_mode) {
for entry in v.iter() { for entry in v.iter() {
if !f(&entry) { if !f(&entry) {
return false; return false;
@ -374,7 +374,7 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
&'a self, &'a self,
element: E, element: E,
quirks_mode: QuirksMode, quirks_mode: QuirksMode,
additional_id: Option<&Atom>, additional_id: Option<&WeakAtom>,
additional_classes: &[Atom], additional_classes: &[Atom],
mut f: F, mut f: F,
) -> bool ) -> bool
@ -535,7 +535,7 @@ impl<V: 'static> MaybeCaseInsensitiveHashMap<Atom, V> {
} }
/// HashMap::get /// HashMap::get
pub fn get(&self, key: &Atom, quirks_mode: QuirksMode) -> Option<&V> { pub fn get(&self, key: &WeakAtom, quirks_mode: QuirksMode) -> Option<&V> {
if quirks_mode == QuirksMode::Quirks { if quirks_mode == QuirksMode::Quirks {
self.0.get(&key.to_ascii_lowercase()) self.0.get(&key.to_ascii_lowercase())
} else { } else {

View file

@ -696,8 +696,8 @@ impl ElementSnapshot for ServoElementSnapshot {
self.attrs.is_some() self.attrs.is_some()
} }
fn id_attr(&self) -> Option<Atom> { fn id_attr(&self) -> Option<&Atom> {
self.get_attr(&ns!(), &local_name!("id")).map(|v| v.as_atom().clone()) self.get_attr(&ns!(), &local_name!("id")).map(|v| v.as_atom())
} }
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {

View file

@ -155,7 +155,7 @@ where
let stylist = &shared_context.stylist; let stylist = &shared_context.stylist;
let may_have_rules_for_element = match element_id { let may_have_rules_for_element = match element_id {
Some(ref id) => stylist.may_have_rules_for_id(id, element), Some(id) => stylist.may_have_rules_for_id(id, element),
None => false None => false
}; };
@ -164,7 +164,7 @@ where
} }
match candidate_id { match candidate_id {
Some(ref id) => stylist.may_have_rules_for_id(id, candidate), Some(id) => stylist.may_have_rules_for_id(id, candidate),
None => false None => false
} }
} }

View file

@ -4,7 +4,7 @@
//! Selector matching. //! Selector matching.
use {Atom, LocalName, Namespace}; use {Atom, LocalName, Namespace, WeakAtom};
use applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList}; use applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
use context::{CascadeInputs, QuirksMode}; use context::{CascadeInputs, QuirksMode};
use dom::TElement; use dom::TElement;
@ -1385,7 +1385,7 @@ impl Stylist {
#[inline] #[inline]
pub fn may_have_rules_for_id<E>( pub fn may_have_rules_for_id<E>(
&self, &self,
id: &Atom, id: &WeakAtom,
element: E, element: E,
) -> bool ) -> bool
where where