Don't persist styles on elements not in the document.

This commit is contained in:
Cameron McCormack 2016-12-29 15:04:45 +08:00
parent b5f3d7dd41
commit be1a73dac5
5 changed files with 24 additions and 4 deletions

View file

@ -199,6 +199,10 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
}
}
fn is_in_doc(&self) -> bool {
unsafe { (*self.node.unsafe_get()).is_in_doc() }
}
}
pub struct ServoChildrenIterator<'a> {

View file

@ -99,6 +99,8 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
unsafe fn set_can_be_fragmented(&self, value: bool);
fn parent_node(&self) -> Option<Self>;
fn is_in_doc(&self) -> bool;
}
/// Wrapper to output the ElementData along with the node when formatting for

View file

@ -157,6 +157,10 @@ impl<'ln> TNode for GeckoNode<'ln> {
unsafe { bindings::Gecko_GetParentNode(self.0).map(GeckoNode) }
}
fn is_in_doc(&self) -> bool {
unsafe { bindings::Gecko_IsInDocument(self.0) }
}
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
// Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag,
// so we force them to be dirtied on viewport size change, regardless if

View file

@ -267,6 +267,9 @@ extern "C" {
extern "C" {
pub fn Gecko_NodeIsElement(node: RawGeckoNodeBorrowed) -> bool;
}
extern "C" {
pub fn Gecko_IsInDocument(node: RawGeckoNodeBorrowed) -> bool;
}
extern "C" {
pub fn Gecko_GetParentNode(node: RawGeckoNodeBorrowed)
-> RawGeckoNodeBorrowedOrNull;

View file

@ -324,16 +324,23 @@ pub fn resolve_style<E, F, G, H>(context: &StyleContext<E>, element: E,
// on the Element.
callback(element.borrow_data().unwrap().styles());
// Clear any styles in display:none subtrees to leave the tree in a valid state.
if let Some(root) = display_none_root {
// Clear any styles in display:none subtrees or subtrees not in the document,
// to leave the tree in a valid state. For display:none subtrees, we leave
// the styles on the display:none root, but for subtrees not in the document,
// we clear styles all the way up to the root of the disconnected subtree.
let in_doc = element.as_node().is_in_doc();
if !in_doc || display_none_root.is_some() {
let mut curr = element;
loop {
unsafe { curr.unset_dirty_descendants(); }
if curr == root {
if in_doc && curr == display_none_root.unwrap() {
break;
}
clear_data(curr);
curr = curr.parent_element().unwrap();
curr = match curr.parent_element() {
Some(parent) => parent,
None => break,
};
}
}
}