diff options
author | Josh Matthews <josh@joshmatthews.net> | 2019-12-19 18:15:30 -0500 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2020-02-24 16:27:40 -0500 |
commit | 1449bac0e19bfafbb14a71c3bb246ad28ddbf8e8 (patch) | |
tree | 738882ff53ca00c251c939917ce73a65605f4b05 /components/script/dom/node.rs | |
parent | 3e95efdea62266c756b04f7557cf1bd3f36f3b87 (diff) | |
download | servo-1449bac0e19bfafbb14a71c3bb246ad28ddbf8e8.tar.gz servo-1449bac0e19bfafbb14a71c3bb246ad28ddbf8e8.zip |
Avoid accessing node global during Node's destructor.
Diffstat (limited to 'components/script/dom/node.rs')
-rw-r--r-- | components/script/dom/node.rs | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 457c1f0d55c..c1da57eae88 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -67,6 +67,7 @@ use crate::dom::window::Window; use crate::script_runtime::JSContext; use crate::script_thread::ScriptThread; use app_units::Au; +use crossbeam_channel::Sender; use devtools_traits::NodeInfo; use dom_struct::dom_struct; use euclid::default::{Point2D, Rect, Size2D, Vector2D}; @@ -209,7 +210,9 @@ impl NodeFlags { impl Drop for Node { #[allow(unsafe_code)] fn drop(&mut self) { - self.style_and_layout_data.get().map(|d| self.dispose(d)); + if let Some(data) = self.style_and_layout_data.get() { + self.dispose(data, ScriptThread::get_any_layout_chan().as_ref()); + } } } @@ -224,15 +227,16 @@ enum SuppressObserver { impl Node { /// Sends the style and layout data, if any, back to the layout thread to be destroyed. - pub fn dispose(&self, data: OpaqueStyleAndLayoutData) { + pub(crate) fn dispose( + &self, + data: OpaqueStyleAndLayoutData, + layout_chan: Option<&Sender<Msg>>, + ) { debug_assert!(thread_state::get().is_script()); - let win = window_from_node(self); self.style_and_layout_data.set(None); - if win - .layout_chan() - .send(Msg::ReapStyleAndLayoutData(data)) - .is_err() - { + if layout_chan.map_or(false, |chan| { + chan.send(Msg::ReapStyleAndLayoutData(data)).is_err() + }) { warn!("layout thread unreachable - leaking layout data"); } } @@ -315,12 +319,16 @@ impl Node { false, ); } + let window = window_from_node(root); + let layout_chan = window.layout_chan(); for node in root.traverse_preorder(ShadowIncluding::Yes) { // This needs to be in its own loop, because unbind_from_tree may // rely on the state of IS_IN_DOC of the context node's descendants, // e.g. when removing a <form>. vtable_for(&&*node).unbind_from_tree(&context); - node.style_and_layout_data.get().map(|d| node.dispose(d)); + if let Some(data) = node.style_and_layout_data.get() { + node.dispose(data, Some(layout_chan)); + } // https://dom.spec.whatwg.org/#concept-node-remove step 14 if let Some(element) = node.as_custom_element() { ScriptThread::enqueue_callback_reaction( @@ -481,10 +489,12 @@ impl<'a> Iterator for QuerySelectorIterator { impl Node { impl_rare_data!(NodeRareData); - pub fn teardown(&self) { - self.style_and_layout_data.get().map(|d| self.dispose(d)); + pub(crate) fn teardown(&self, layout_chan: &Sender<Msg>) { + if let Some(data) = self.style_and_layout_data.get() { + self.dispose(data, Some(layout_chan)); + } for kid in self.children() { - kid.teardown(); + kid.teardown(layout_chan); } } |