Reap layout data whenever a node is removed from the tree.

Also introduce a clear() function to layout data which will be used to clear items such as compositor layouts.

Clear the layout data when a node becomes display:none.
This commit is contained in:
Glenn Watson 2015-02-27 16:29:02 +10:00
parent 8ad3c5aeb6
commit 611fd7a846
5 changed files with 35 additions and 40 deletions

View file

@ -177,9 +177,7 @@ impl NodeFlags {
impl Drop for Node {
#[allow(unsafe_blocks)]
fn drop(&mut self) {
unsafe {
self.reap_layout_data();
}
self.layout_data.dispose();
}
}
@ -205,6 +203,8 @@ pub struct LayoutData {
_data: NonZero<*const ()>,
}
unsafe impl Send for LayoutData {}
pub struct LayoutDataRef {
pub data_cell: RefCell<Option<LayoutData>>,
}
@ -218,18 +218,17 @@ impl LayoutDataRef {
}
}
/// Returns true if there is layout data present.
#[inline]
pub fn is_present(&self) -> bool {
self.data_cell.borrow().is_some()
}
/// Take the chan out of the layout data if it is present.
pub fn take_chan(&self) -> Option<LayoutChan> {
let mut layout_data = self.data_cell.borrow_mut();
match &mut *layout_data {
&mut None => None,
&mut Some(ref mut layout_data) => Some(layout_data.chan.take().unwrap()),
/// Sends layout data, if any, back to the layout task to be destroyed.
pub fn dispose(&self) {
if let Some(mut layout_data) = mem::replace(&mut *self.borrow_mut(), None) {
let layout_chan = layout_data.chan.take();
match layout_chan {
None => {}
Some(chan) => {
let LayoutChan(chan) = chan;
chan.send(Msg::ReapLayoutData(layout_data)).unwrap()
}
}
}
}
@ -258,8 +257,6 @@ impl LayoutDataRef {
}
}
unsafe impl Send for LayoutDataRef {}
/// The different types of nodes.
#[derive(Copy, PartialEq, Debug)]
#[jstraceable]
@ -302,6 +299,7 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
for node in self.traverse_preorder() {
vtable_for(&node).unbind_from_tree(parent_in_doc);
}
self.layout_data.dispose();
}
//
@ -1648,21 +1646,6 @@ impl Node {
Temporary::from_rooted(copy.r())
}
/// Sends layout data, if any, back to the layout task to be destroyed.
unsafe fn reap_layout_data(&mut self) {
if self.layout_data.is_present() {
let layout_data = mem::replace(&mut self.layout_data, LayoutDataRef::new());
let layout_chan = layout_data.take_chan();
match layout_chan {
None => {}
Some(chan) => {
let LayoutChan(chan) = chan;
chan.send(Msg::ReapLayoutData(layout_data)).unwrap()
},
}
}
}
pub fn collect_text_contents<'a, T: Iterator<Item=JSRef<'a, Node>>>(iterator: T) -> String {
let mut content = String::new();
for node in iterator {

View file

@ -6,7 +6,7 @@
//! interface helps reduce coupling between these two components, and enables
//! the DOM to be placed in a separate crate from layout.
use dom::node::LayoutDataRef;
use dom::node::LayoutData;
use geom::point::Point2D;
use geom::rect::Rect;
@ -41,7 +41,7 @@ pub enum Msg {
/// Destroys layout data associated with a DOM node.
///
/// TODO(pcwalton): Maybe think about batching to avoid message traffic.
ReapLayoutData(LayoutDataRef),
ReapLayoutData(LayoutData),
/// Requests that the layout task enter a quiescent state in which no more messages are
/// accepted except `ExitMsg`. A response message will be sent on the supplied channel when