Make Node and Element rare_data an Option

This commit is contained in:
Fernando Jiménez Moreno 2019-03-08 17:03:34 +01:00
parent f6069630d2
commit 6bf1ca20a2
8 changed files with 181 additions and 120 deletions

View file

@ -106,7 +106,7 @@ use selectors::Element as SelectorsElement;
use servo_arc::Arc; use servo_arc::Arc;
use servo_atoms::Atom; use servo_atoms::Atom;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::{Cell, Ref}; use std::cell::{Cell, Ref, RefMut};
use std::default::Default; use std::default::Default;
use std::fmt; use std::fmt;
use std::mem; use std::mem;
@ -166,7 +166,7 @@ pub struct Element {
/// when it has exclusive access to the element. /// when it has exclusive access to the element.
#[ignore_malloc_size_of = "bitflags defined in rust-selectors"] #[ignore_malloc_size_of = "bitflags defined in rust-selectors"]
selector_flags: Cell<ElementSelectorFlags>, selector_flags: Cell<ElementSelectorFlags>,
rare_data: Box<ElementRareData>, rare_data: DomRefCell<Option<Box<ElementRareData>>>,
} }
impl fmt::Debug for Element { impl fmt::Debug for Element {
@ -308,6 +308,8 @@ impl Element {
) )
} }
impl_rare_data!(ElementRareData);
pub fn restyle(&self, damage: NodeDamage) { pub fn restyle(&self, damage: NodeDamage) {
let doc = self.node.owner_doc(); let doc = self.node.owner_doc();
let mut restyle = doc.ensure_pending_restyle(self); let mut restyle = doc.ensure_pending_restyle(self);
@ -330,39 +332,49 @@ impl Element {
} }
pub fn set_custom_element_state(&self, state: CustomElementState) { pub fn set_custom_element_state(&self, state: CustomElementState) {
self.rare_data.custom_element_state.set(state); self.rare_data_mut().as_mut().unwrap().custom_element_state = state;
} }
pub fn get_custom_element_state(&self) -> CustomElementState { pub fn get_custom_element_state(&self) -> CustomElementState {
self.rare_data.custom_element_state.get() self.rare_data().as_ref().unwrap().custom_element_state
} }
pub fn set_custom_element_definition(&self, definition: Rc<CustomElementDefinition>) { pub fn set_custom_element_definition(&self, definition: Rc<CustomElementDefinition>) {
*self.rare_data.custom_element_definition.borrow_mut() = Some(definition); self.rare_data_mut()
.as_mut()
.unwrap()
.custom_element_definition = Some(definition);
} }
pub fn get_custom_element_definition(&self) -> Option<Rc<CustomElementDefinition>> { pub fn get_custom_element_definition(&self) -> Option<Rc<CustomElementDefinition>> {
(*self.rare_data.custom_element_definition.borrow()).clone() self.rare_data()
.as_ref()
.unwrap()
.custom_element_definition
.clone()
} }
pub fn push_callback_reaction(&self, function: Rc<Function>, args: Box<[Heap<JSVal>]>) { pub fn push_callback_reaction(&self, function: Rc<Function>, args: Box<[Heap<JSVal>]>) {
self.rare_data self.rare_data_mut()
.as_mut()
.unwrap()
.custom_element_reaction_queue .custom_element_reaction_queue
.borrow_mut()
.push(CustomElementReaction::Callback(function, args)); .push(CustomElementReaction::Callback(function, args));
} }
pub fn push_upgrade_reaction(&self, definition: Rc<CustomElementDefinition>) { pub fn push_upgrade_reaction(&self, definition: Rc<CustomElementDefinition>) {
self.rare_data self.rare_data_mut()
.as_mut()
.unwrap()
.custom_element_reaction_queue .custom_element_reaction_queue
.borrow_mut()
.push(CustomElementReaction::Upgrade(definition)); .push(CustomElementReaction::Upgrade(definition));
} }
pub fn clear_reaction_queue(&self) { pub fn clear_reaction_queue(&self) {
self.rare_data self.rare_data_mut()
.as_mut()
.unwrap()
.custom_element_reaction_queue .custom_element_reaction_queue
.borrow_mut()
.clear(); .clear();
} }
@ -371,14 +383,19 @@ impl Element {
// after clear_reaction_queue has been called. // after clear_reaction_queue has been called.
rooted_vec!(let mut reactions); rooted_vec!(let mut reactions);
while !self while !self
.rare_data .rare_data()
.as_ref()
.unwrap()
.custom_element_reaction_queue .custom_element_reaction_queue
.borrow()
.is_empty() .is_empty()
{ {
mem::swap( mem::swap(
&mut *reactions, &mut *reactions,
&mut *self.rare_data.custom_element_reaction_queue.borrow_mut(), &mut self
.rare_data_mut()
.as_mut()
.unwrap()
.custom_element_reaction_queue,
); );
for reaction in reactions.iter() { for reaction in reactions.iter() {
reaction.invoke(self); reaction.invoke(self);
@ -441,7 +458,7 @@ impl Element {
} }
pub fn is_shadow_host(&self) -> bool { pub fn is_shadow_host(&self) -> bool {
self.rare_data.shadow_root.get().is_some() self.rare_data().as_ref().unwrap().shadow_root.is_some()
} }
/// https://dom.spec.whatwg.org/#dom-element-attachshadow /// https://dom.spec.whatwg.org/#dom-element-attachshadow
@ -484,10 +501,8 @@ impl Element {
} }
// Steps 4, 5 and 6. // Steps 4, 5 and 6.
let shadow_root = self let shadow_root = ShadowRoot::new(self, &*self.node.owner_doc());
.rare_data self.rare_data_mut().as_mut().unwrap().shadow_root = Some(Dom::from_ref(&*shadow_root));
.shadow_root
.or_init(|| ShadowRoot::new(self, &*self.node.owner_doc()));
if self.is_connected() { if self.is_connected() {
self.node.owner_doc().register_shadow_root(&*shadow_root); self.node.owner_doc().register_shadow_root(&*shadow_root);
@ -1063,9 +1078,12 @@ impl LayoutElementHelpers for LayoutDom<Element> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> { unsafe fn get_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> {
(*self.unsafe_get()) (*self.unsafe_get())
.rare_data .rare_data_for_layout()
.as_ref()
.unwrap()
.shadow_root .shadow_root
.get_inner_as_layout() .as_ref()
.map(|sr| sr.to_layout())
} }
} }
@ -2809,7 +2827,7 @@ impl VirtualMethods for Element {
let doc = document_from_node(self); let doc = document_from_node(self);
if let Some(shadow_root) = self.rare_data.shadow_root.get() { if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().shadow_root {
doc.register_shadow_root(&shadow_root); doc.register_shadow_root(&shadow_root);
let shadow_root = shadow_root.upcast::<Node>(); let shadow_root = shadow_root.upcast::<Node>();
shadow_root.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected); shadow_root.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected);
@ -2847,7 +2865,7 @@ impl VirtualMethods for Element {
let doc = document_from_node(self); let doc = document_from_node(self);
if let Some(shadow_root) = self.rare_data.shadow_root.get() { if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().shadow_root {
doc.unregister_shadow_root(&shadow_root); doc.unregister_shadow_root(&shadow_root);
let shadow_root = shadow_root.upcast::<Node>(); let shadow_root = shadow_root.upcast::<Node>();
shadow_root.set_flag(NodeFlags::IS_CONNECTED, false); shadow_root.set_flag(NodeFlags::IS_CONNECTED, false);

View file

@ -632,3 +632,33 @@ macro_rules! handle_potential_webgl_error {
handle_potential_webgl_error!($context, $call, ()); handle_potential_webgl_error!($context, $call, ());
}; };
} }
macro_rules! impl_rare_data (
($type:ty) => (
fn init_rare_data(&self) {
let mut rare_data = self.rare_data.borrow_mut();
if rare_data.is_none() {
*rare_data = Some(Default::default());
}
}
fn rare_data(&self) -> Ref<Option<Box<$type>>> {
self.init_rare_data();
self.rare_data.borrow()
}
fn rare_data_mut(&self) -> RefMut<Option<Box<$type>>> {
self.init_rare_data();
self.rare_data.borrow_mut()
}
#[allow(unsafe_code)]
fn rare_data_for_layout(&self) -> &Option<Box<$type>> {
let mut rare_data = self.rare_data.borrow_mut_for_layout();
if rare_data.is_none() {
*rare_data = Some(Default::default());
}
unsafe { self.rare_data.borrow_for_layout() }
}
);
);

View file

@ -318,20 +318,18 @@ impl MutationObserverMethods for MutationObserver {
// Step 8 // Step 8
if add_new_observer { if add_new_observer {
target target.add_mutation_observer(RegisteredObserver {
.registered_mutation_observers() observer: DomRoot::from_ref(self),
.push(RegisteredObserver { options: ObserverOptions {
observer: DomRoot::from_ref(self), attributes,
options: ObserverOptions { attribute_old_value,
attributes, character_data,
attribute_old_value, character_data_old_value,
character_data, subtree,
character_data_old_value, attribute_filter,
subtree, child_list,
attribute_filter, },
child_list, });
},
});
self.node_list.borrow_mut().push(DomRoot::from_ref(target)); self.node_list.borrow_mut().push(DomRoot::from_ref(target));
} }

View file

@ -5,6 +5,7 @@
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
use crate::document_loader::DocumentLoader; use crate::document_loader::DocumentLoader;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
@ -82,7 +83,7 @@ use servo_arc::Arc;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::{Cell, RefMut, UnsafeCell}; use std::cell::{Cell, Ref, RefMut, UnsafeCell};
use std::cmp; use std::cmp;
use std::default::Default; use std::default::Default;
use std::iter; use std::iter;
@ -125,7 +126,7 @@ pub struct Node {
owner_doc: MutNullableDom<Document>, owner_doc: MutNullableDom<Document>,
/// Rare node data. /// Rare node data.
rare_data: Box<NodeRareData>, rare_data: DomRefCell<Option<Box<NodeRareData>>>,
/// The live list of children return by .childNodes. /// The live list of children return by .childNodes.
child_list: MutNullableDom<NodeList>, child_list: MutNullableDom<NodeList>,
@ -430,6 +431,8 @@ impl<'a> Iterator for QuerySelectorIterator {
} }
impl Node { impl Node {
impl_rare_data!(NodeRareData);
pub fn teardown(&self) { pub fn teardown(&self) {
self.style_and_layout_data.get().map(|d| self.dispose(d)); self.style_and_layout_data.get().map(|d| self.dispose(d));
for kid in self.children() { for kid in self.children() {
@ -450,14 +453,26 @@ impl Node {
/// Return all registered mutation observers for this node. /// Return all registered mutation observers for this node.
pub fn registered_mutation_observers(&self) -> RefMut<Vec<RegisteredObserver>> { pub fn registered_mutation_observers(&self) -> RefMut<Vec<RegisteredObserver>> {
self.rare_data.mutation_observers.borrow_mut() RefMut::map(self.rare_data_mut(), |rare_data| {
&mut rare_data.as_mut().unwrap().mutation_observers
})
}
/// Add a new mutation observer for a given node.
pub fn add_mutation_observer(&self, observer: RegisteredObserver) {
self.rare_data_mut()
.as_mut()
.unwrap()
.mutation_observers
.push(observer);
} }
/// Removes the mutation observer for a given node. /// Removes the mutation observer for a given node.
pub fn remove_mutation_observer(&self, observer: &MutationObserver) { pub fn remove_mutation_observer(&self, observer: &MutationObserver) {
self.rare_data self.rare_data_mut()
.as_mut()
.unwrap()
.mutation_observers .mutation_observers
.borrow_mut()
.retain(|reg_obs| &*reg_obs.observer != observer) .retain(|reg_obs| &*reg_obs.observer != observer)
} }
@ -930,11 +945,16 @@ impl Node {
if let Some(ref shadow_root) = self.downcast::<ShadowRoot>() { if let Some(ref shadow_root) = self.downcast::<ShadowRoot>() {
return Some(DomRoot::from_ref(shadow_root)); return Some(DomRoot::from_ref(shadow_root));
} }
self.rare_data.owner_shadow_root.get() self.rare_data()
.as_ref()
.unwrap()
.owner_shadow_root
.as_ref()
.map(|sr| DomRoot::from_ref(&**sr))
} }
pub fn set_owner_shadow_root(&self, shadow_root: &ShadowRoot) { pub fn set_owner_shadow_root(&self, shadow_root: &ShadowRoot) {
self.rare_data.owner_shadow_root.set(Some(shadow_root)); self.rare_data_mut().as_mut().unwrap().owner_shadow_root = Some(Dom::from_ref(shadow_root));
} }
pub fn is_in_html_doc(&self) -> bool { pub fn is_in_html_doc(&self) -> bool {
@ -1266,9 +1286,12 @@ impl LayoutNodeHelpers for LayoutDom<Node> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn owner_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> { unsafe fn owner_shadow_root_for_layout(&self) -> Option<LayoutDom<ShadowRoot>> {
(*self.unsafe_get()) (*self.unsafe_get())
.rare_data .rare_data_for_layout()
.as_ref()
.unwrap()
.owner_shadow_root .owner_shadow_root
.get_inner_as_layout() .as_ref()
.map(|sr| sr.to_layout())
} }
#[inline] #[inline]
@ -2274,12 +2297,12 @@ impl NodeMethods for Node {
// https://dom.spec.whatwg.org/#dom-node-getrootnode // https://dom.spec.whatwg.org/#dom-node-getrootnode
fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> { fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
if options.composed { if options.composed {
if let Some(shadow_root) = self.rare_data.owner_shadow_root.get() { if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().owner_shadow_root {
// shadow-including root. // shadow-including root.
return shadow_root.Host().upcast::<Node>().GetRootNode(options); return shadow_root.Host().upcast::<Node>().GetRootNode(options);
} }
} }
if let Some(shadow_root) = self.rare_data.owner_shadow_root.get() { if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().owner_shadow_root {
DomRoot::from_ref(shadow_root.upcast::<Node>()) DomRoot::from_ref(shadow_root.upcast::<Node>())
} else if self.is_in_doc() { } else if self.is_in_doc() {
DomRoot::from_ref(self.owner_doc().upcast::<Node>()) DomRoot::from_ref(self.owner_doc().upcast::<Node>())

View file

@ -2,14 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::root::Dom;
use crate::dom::bindings::root::MutNullableDom;
use crate::dom::customelementregistry::{ use crate::dom::customelementregistry::{
CustomElementDefinition, CustomElementReaction, CustomElementState, CustomElementDefinition, CustomElementReaction, CustomElementState,
}; };
use crate::dom::mutationobserver::RegisteredObserver; use crate::dom::mutationobserver::RegisteredObserver;
use crate::dom::shadowroot::ShadowRoot; use crate::dom::shadowroot::ShadowRoot;
use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
#[derive(Default, JSTraceable, MallocSizeOf)] #[derive(Default, JSTraceable, MallocSizeOf)]
@ -18,9 +16,9 @@ pub struct NodeRareData {
/// The shadow root the node belongs to. /// The shadow root the node belongs to.
/// This is None if the node is not in a shadow tree or /// This is None if the node is not in a shadow tree or
/// if it is a ShadowRoot. /// if it is a ShadowRoot.
pub owner_shadow_root: MutNullableDom<ShadowRoot>, pub owner_shadow_root: Option<Dom<ShadowRoot>>,
/// Registered observers for this node. /// Registered observers for this node.
pub mutation_observers: DomRefCell<Vec<RegisteredObserver>>, pub mutation_observers: Vec<RegisteredObserver>,
} }
#[derive(Default, JSTraceable, MallocSizeOf)] #[derive(Default, JSTraceable, MallocSizeOf)]
@ -29,12 +27,12 @@ pub struct ElementRareData {
/// https://dom.spec.whatwg.org/#dom-element-shadowroot /// https://dom.spec.whatwg.org/#dom-element-shadowroot
/// XXX This is currently not exposed to web content. Only for /// XXX This is currently not exposed to web content. Only for
/// internal use. /// internal use.
pub shadow_root: MutNullableDom<ShadowRoot>, pub shadow_root: Option<Dom<ShadowRoot>>,
/// <https://html.spec.whatwg.org/multipage/#custom-element-reaction-queue> /// <https://html.spec.whatwg.org/multipage/#custom-element-reaction-queue>
pub custom_element_reaction_queue: DomRefCell<Vec<CustomElementReaction>>, pub custom_element_reaction_queue: Vec<CustomElementReaction>,
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-definition> /// <https://dom.spec.whatwg.org/#concept-element-custom-element-definition>
#[ignore_malloc_size_of = "Rc"] #[ignore_malloc_size_of = "Rc"]
pub custom_element_definition: DomRefCell<Option<Rc<CustomElementDefinition>>>, pub custom_element_definition: Option<Rc<CustomElementDefinition>>,
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-state> /// <https://dom.spec.whatwg.org/#concept-element-custom-element-state>
pub custom_element_state: Cell<CustomElementState>, pub custom_element_state: CustomElementState,
} }

View file

@ -421,11 +421,6 @@ impl<'ln> TNode for GeckoNode<'ln> {
self.get_bool_flag(nsINode_BooleanFlag::IsInDocument) self.get_bool_flag(nsINode_BooleanFlag::IsInDocument)
} }
#[inline]
fn is_connected(&self) -> bool {
self.get_bool_flag(nsINode_BooleanFlag::IsConnected)
}
fn traversal_parent(&self) -> Option<GeckoElement<'ln>> { fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
self.flattened_tree_parent().and_then(|n| n.as_element()) self.flattened_tree_parent().and_then(|n| n.as_element())
} }

View file

@ -443,61 +443,61 @@ where
/// documents, which is slightly annoying. /// documents, which is slightly annoying.
macro_rules! sheet_set_methods { macro_rules! sheet_set_methods {
($set_name:expr) => { ($set_name:expr) => {
fn collect_invalidations_for( fn collect_invalidations_for(
&mut self, &mut self,
device: Option<&Device>, device: Option<&Device>,
sheet: &S, sheet: &S,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
) { ) {
if let Some(device) = device { if let Some(device) = device {
self.invalidations self.invalidations
.collect_invalidations_for(device, sheet, guard); .collect_invalidations_for(device, sheet, guard);
}
} }
}
/// Appends a new stylesheet to the current set. /// Appends a new stylesheet to the current set.
/// ///
/// No device implies not computing invalidations. /// No device implies not computing invalidations.
pub fn append_stylesheet( pub fn append_stylesheet(
&mut self, &mut self,
device: Option<&Device>, device: Option<&Device>,
sheet: S, sheet: S,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
) { ) {
debug!(concat!($set_name, "::append_stylesheet")); debug!(concat!($set_name, "::append_stylesheet"));
self.collect_invalidations_for(device, &sheet, guard); self.collect_invalidations_for(device, &sheet, guard);
let collection = self.collection_for(&sheet, guard); let collection = self.collection_for(&sheet, guard);
collection.append(sheet); collection.append(sheet);
} }
/// Insert a given stylesheet before another stylesheet in the document. /// Insert a given stylesheet before another stylesheet in the document.
pub fn insert_stylesheet_before( pub fn insert_stylesheet_before(
&mut self, &mut self,
device: Option<&Device>, device: Option<&Device>,
sheet: S, sheet: S,
before_sheet: S, before_sheet: S,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
) { ) {
debug!(concat!($set_name, "::insert_stylesheet_before")); debug!(concat!($set_name, "::insert_stylesheet_before"));
self.collect_invalidations_for(device, &sheet, guard); self.collect_invalidations_for(device, &sheet, guard);
let collection = self.collection_for(&sheet, guard); let collection = self.collection_for(&sheet, guard);
collection.insert_before(sheet, &before_sheet); collection.insert_before(sheet, &before_sheet);
} }
/// Remove a given stylesheet from the set. /// Remove a given stylesheet from the set.
pub fn remove_stylesheet( pub fn remove_stylesheet(
&mut self, &mut self,
device: Option<&Device>, device: Option<&Device>,
sheet: S, sheet: S,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
) { ) {
debug!(concat!($set_name, "::remove_stylesheet")); debug!(concat!($set_name, "::remove_stylesheet"));
self.collect_invalidations_for(device, &sheet, guard); self.collect_invalidations_for(device, &sheet, guard);
let collection = self.collection_for(&sheet, guard); let collection = self.collection_for(&sheet, guard);
collection.remove(&sheet) collection.remove(&sheet)
} }
}; };
} }

View file

@ -30,11 +30,10 @@ macro_rules! sizeof_checker (
// Update the sizes here // Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 56); sizeof_checker!(size_event_target, EventTarget, 56);
sizeof_checker!(size_node, Node, 176); sizeof_checker!(size_node, Node, 184);
sizeof_checker!(size_element, Element, 376); sizeof_checker!(size_element, Element, 392);
sizeof_checker!(size_htmlelement, HTMLElement, 392); sizeof_checker!(size_htmlelement, HTMLElement, 408);
sizeof_checker!(size_div, HTMLDivElement, 392); sizeof_checker!(size_div, HTMLDivElement, 408);
sizeof_checker!(size_span, HTMLSpanElement, 392); sizeof_checker!(size_span, HTMLSpanElement, 408);
sizeof_checker!(size_text, Text, 208); sizeof_checker!(size_text, Text, 216);
sizeof_checker!(size_characterdata, CharacterData, 208); sizeof_checker!(size_characterdata, CharacterData, 216);