diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 6983b8be2c1..034c57abad8 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -332,75 +332,60 @@ impl Element { } pub fn set_custom_element_state(&self, state: CustomElementState) { - self.rare_data_mut().as_mut().unwrap().custom_element_state = state; + self.ensure_rare_data().custom_element_state = state; } pub fn get_custom_element_state(&self) -> CustomElementState { - self.rare_data().as_ref().unwrap().custom_element_state + if let Some(rare_data) = self.rare_data().as_ref() { + return rare_data.custom_element_state; + } + CustomElementState::Undefined } pub fn set_custom_element_definition(&self, definition: Rc) { - self.rare_data_mut() - .as_mut() - .unwrap() - .custom_element_definition = Some(definition); + self.ensure_rare_data().custom_element_definition = Some(definition); } pub fn get_custom_element_definition(&self) -> Option> { - self.rare_data() - .as_ref() - .unwrap() - .custom_element_definition - .clone() + if let Some(rare_data) = self.rare_data().as_ref() { + return rare_data.custom_element_definition.clone(); + } + None } pub fn push_callback_reaction(&self, function: Rc, args: Box<[Heap]>) { - self.rare_data_mut() - .as_mut() - .unwrap() + self.ensure_rare_data() .custom_element_reaction_queue .push(CustomElementReaction::Callback(function, args)); } pub fn push_upgrade_reaction(&self, definition: Rc) { - self.rare_data_mut() - .as_mut() - .unwrap() + self.ensure_rare_data() .custom_element_reaction_queue .push(CustomElementReaction::Upgrade(definition)); } pub fn clear_reaction_queue(&self) { - self.rare_data_mut() - .as_mut() - .unwrap() + self.ensure_rare_data() .custom_element_reaction_queue .clear(); } pub fn invoke_reactions(&self) { - // TODO: This is not spec compliant, as this will allow some reactions to be processed - // after clear_reaction_queue has been called. - rooted_vec!(let mut reactions); - while !self - .rare_data() - .as_ref() - .unwrap() - .custom_element_reaction_queue - .is_empty() - { - mem::swap( - &mut *reactions, - &mut self - .rare_data_mut() - .as_mut() - .unwrap() - .custom_element_reaction_queue, - ); - for reaction in reactions.iter() { - reaction.invoke(self); + if let Some(rare_data) = self.rare_data().as_ref() { + // TODO: This is not spec compliant, as this will allow some reactions to be processed + // after clear_reaction_queue has been called. + rooted_vec!(let mut reactions); + while !rare_data.custom_element_reaction_queue.is_empty() { + mem::swap( + &mut *reactions, + &mut self.ensure_rare_data().custom_element_reaction_queue, + ); + for reaction in reactions.iter() { + reaction.invoke(self); + } + reactions.clear(); } - reactions.clear(); } } @@ -458,7 +443,10 @@ impl Element { } pub fn is_shadow_host(&self) -> bool { - self.rare_data().as_ref().unwrap().shadow_root.is_some() + if let Some(rare_data) = self.rare_data().as_ref() { + return rare_data.shadow_root.is_some(); + } + false } /// https://dom.spec.whatwg.org/#dom-element-attachshadow @@ -502,7 +490,7 @@ impl Element { // Steps 4, 5 and 6. let shadow_root = ShadowRoot::new(self, &*self.node.owner_doc()); - self.rare_data_mut().as_mut().unwrap().shadow_root = Some(Dom::from_ref(&*shadow_root)); + self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root)); if self.is_connected() { self.node.owner_doc().register_shadow_root(&*shadow_root); @@ -1077,13 +1065,10 @@ impl LayoutElementHelpers for LayoutDom { #[inline] #[allow(unsafe_code)] unsafe fn get_shadow_root_for_layout(&self) -> Option> { - (*self.unsafe_get()) - .rare_data_for_layout() - .as_ref() - .unwrap() - .shadow_root - .as_ref() - .map(|sr| sr.to_layout()) + if let Some(rare_data) = (*self.unsafe_get()).rare_data_for_layout().as_ref() { + return rare_data.shadow_root.as_ref().map(|sr| sr.to_layout()); + } + None } } @@ -2827,13 +2812,15 @@ impl VirtualMethods for Element { let doc = document_from_node(self); - if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().shadow_root { - doc.register_shadow_root(&shadow_root); - let shadow_root = shadow_root.upcast::(); - shadow_root.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected); - for node in shadow_root.children() { - node.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected); - node.bind_to_tree(context); + if let Some(rare_data) = self.rare_data().as_ref() { + if let Some(ref shadow_root) = rare_data.shadow_root { + doc.register_shadow_root(&shadow_root); + let shadow_root = shadow_root.upcast::(); + shadow_root.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected); + for node in shadow_root.children() { + node.set_flag(NodeFlags::IS_CONNECTED, context.tree_connected); + node.bind_to_tree(context); + } } } @@ -2865,13 +2852,15 @@ impl VirtualMethods for Element { let doc = document_from_node(self); - if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().shadow_root { - doc.unregister_shadow_root(&shadow_root); - let shadow_root = shadow_root.upcast::(); - shadow_root.set_flag(NodeFlags::IS_CONNECTED, false); - for node in shadow_root.children() { - node.set_flag(NodeFlags::IS_CONNECTED, false); - node.unbind_from_tree(context); + if let Some(rare_data) = self.rare_data().as_ref() { + if let Some(ref shadow_root) = rare_data.shadow_root { + doc.unregister_shadow_root(&shadow_root); + let shadow_root = shadow_root.upcast::(); + shadow_root.set_flag(NodeFlags::IS_CONNECTED, false); + for node in shadow_root.children() { + node.set_flag(NodeFlags::IS_CONNECTED, false); + node.unbind_from_tree(context); + } } } diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 0fb51c7d8fd..de531f0c53f 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -635,29 +635,22 @@ macro_rules! handle_potential_webgl_error { macro_rules! impl_rare_data ( ($type:ty) => ( - fn init_rare_data(&self) { + fn rare_data(&self) -> Ref>> { + self.rare_data.borrow() + } + + fn ensure_rare_data(&self) -> RefMut> { let mut rare_data = self.rare_data.borrow_mut(); if rare_data.is_none() { *rare_data = Some(Default::default()); } - } - - fn rare_data(&self) -> Ref>> { - self.init_rare_data(); - self.rare_data.borrow() - } - - fn rare_data_mut(&self) -> RefMut>> { - self.init_rare_data(); - self.rare_data.borrow_mut() + RefMut::map(rare_data, |rare_data| { + rare_data.as_mut().unwrap() + }) } #[allow(unsafe_code)] fn rare_data_for_layout(&self) -> &Option> { - 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() } } ); diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index f58f1af652b..c95e90e303c 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -452,26 +452,25 @@ impl Node { } /// Return all registered mutation observers for this node. + /// XXX(ferjm) This should probably be split into two functions, + /// `registered_mutation_observers`, which returns an Option or + /// an empty slice or something, and doesn't create the rare data, + /// and `registered_mutation_observers_mut`, which does lazily + /// initialize the raredata. pub fn registered_mutation_observers(&self) -> RefMut> { - RefMut::map(self.rare_data_mut(), |rare_data| { - &mut rare_data.as_mut().unwrap().mutation_observers + RefMut::map(self.ensure_rare_data(), |rare_data| { + &mut rare_data.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); + self.ensure_rare_data().mutation_observers.push(observer); } /// Removes the mutation observer for a given node. pub fn remove_mutation_observer(&self, observer: &MutationObserver) { - self.rare_data_mut() - .as_mut() - .unwrap() + self.ensure_rare_data() .mutation_observers .retain(|reg_obs| &*reg_obs.observer != observer) } @@ -951,16 +950,17 @@ impl Node { if let Some(ref shadow_root) = self.downcast::() { return Some(DomRoot::from_ref(shadow_root)); } - self.rare_data() - .as_ref() - .unwrap() - .owner_shadow_root - .as_ref() - .map(|sr| DomRoot::from_ref(&**sr)) + if let Some(rare_data) = self.rare_data().as_ref() { + return rare_data + .owner_shadow_root + .as_ref() + .map(|sr| DomRoot::from_ref(&**sr)); + } + None } pub fn set_owner_shadow_root(&self, shadow_root: &ShadowRoot) { - self.rare_data_mut().as_mut().unwrap().owner_shadow_root = Some(Dom::from_ref(shadow_root)); + self.ensure_rare_data().owner_shadow_root = Some(Dom::from_ref(shadow_root)); } pub fn is_in_html_doc(&self) -> bool { @@ -1281,13 +1281,13 @@ impl LayoutNodeHelpers for LayoutDom { #[inline] #[allow(unsafe_code)] unsafe fn owner_shadow_root_for_layout(&self) -> Option> { - (*self.unsafe_get()) - .rare_data_for_layout() - .as_ref() - .unwrap() - .owner_shadow_root - .as_ref() - .map(|sr| sr.to_layout()) + if let Some(rare_data) = (*self.unsafe_get()).rare_data_for_layout().as_ref() { + return rare_data + .owner_shadow_root + .as_ref() + .map(|sr| sr.to_layout()); + } + None } #[inline] @@ -2293,14 +2293,21 @@ impl NodeMethods for Node { // https://dom.spec.whatwg.org/#dom-node-getrootnode fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot { if options.composed { - if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().owner_shadow_root { - // shadow-including root. - return shadow_root.Host().upcast::().GetRootNode(options); + if let Some(rare_data) = self.rare_data().as_ref() { + if let Some(ref shadow_root) = rare_data.owner_shadow_root { + // shadow-including root. + return shadow_root.Host().upcast::().GetRootNode(options); + } } } - if let Some(ref shadow_root) = self.rare_data().as_ref().unwrap().owner_shadow_root { - DomRoot::from_ref(shadow_root.upcast::()) - } else if self.is_in_doc() { + + if let Some(rare_data) = self.rare_data().as_ref() { + if let Some(ref shadow_root) = rare_data.owner_shadow_root { + return DomRoot::from_ref(shadow_root.upcast::()); + } + } + + if self.is_in_doc() { DomRoot::from_ref(self.owner_doc().upcast::()) } else { self.inclusive_ancestors(ShadowIncluding::No) diff --git a/components/script/dom/raredata.rs b/components/script/dom/raredata.rs index 874db7b48ad..30929d2a247 100644 --- a/components/script/dom/raredata.rs +++ b/components/script/dom/raredata.rs @@ -10,6 +10,9 @@ use crate::dom::mutationobserver::RegisteredObserver; use crate::dom::shadowroot::ShadowRoot; use std::rc::Rc; +//XXX(ferjm) Ideally merge NodeRareData and ElementRareData so they share +// storage. + #[derive(Default, JSTraceable, MallocSizeOf)] #[must_root] pub struct NodeRareData {