Only pass nodes to layout for restyling that are actually in the document.

This commit is contained in:
Josh Matthews 2017-01-04 12:36:11 -05:00
parent 1e927ca88b
commit 9a264c8173
5 changed files with 49 additions and 3 deletions

View file

@ -67,7 +67,7 @@ use dom::keyboardevent::KeyboardEvent;
use dom::location::Location;
use dom::messageevent::MessageEvent;
use dom::mouseevent::MouseEvent;
use dom::node::{self, CloneChildrenFlag, Node, NodeDamage, window_from_node};
use dom::node::{self, CloneChildrenFlag, Node, NodeDamage, window_from_node, IS_IN_DOC, LayoutNodeHelpers};
use dom::nodeiterator::NodeIterator;
use dom::nodelist::NodeList;
use dom::pagetransitionevent::PageTransitionEvent;
@ -1790,7 +1790,12 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
#[allow(unrooted_must_root)]
unsafe fn drain_pending_restyles(&self) -> Vec<(LayoutJS<Element>, PendingRestyle)> {
let mut elements = (*self.unsafe_get()).pending_restyles.borrow_mut_for_layout();
let result = elements.drain().map(|(k, v)| (k.to_layout(), v)).collect();
// Elements were in a document when they were adding to this list, but that
// may no longer be true when the next layout occurs.
let result = elements.drain()
.map(|(k, v)| (k.to_layout(), v))
.filter(|&(ref k, _)| k.upcast::<Node>().get_flag(IS_IN_DOC))
.collect();
result
}

View file

@ -37,7 +37,7 @@ use dom::bindings::js::LayoutJS;
use dom::characterdata::LayoutCharacterDataHelpers;
use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
use dom::node::{CAN_BE_FRAGMENTED, DIRTY_ON_VIEWPORT_SIZE_CHANGE, HAS_DIRTY_DESCENDANTS};
use dom::node::{CAN_BE_FRAGMENTED, DIRTY_ON_VIEWPORT_SIZE_CHANGE, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
use dom::node::{LayoutNodeHelpers, Node};
use dom::text::Text;
use gfx_traits::ByteIndex;
@ -404,6 +404,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
unsafe fn set_dirty_descendants(&self) {
debug_assert!(self.as_node().node.get_flag(IS_IN_DOC));
self.as_node().node.set_flag(HAS_DIRTY_DESCENDANTS, true)
}

View file

@ -6438,6 +6438,18 @@
"url": "/_mozilla/mozilla/iframe/resize_after_load.html"
}
],
"mozilla/restyle-out-of-document.html": [
{
"path": "mozilla/restyle-out-of-document.html",
"references": [
[
"/_mozilla/mozilla/restyle-out-of-document-ref.html",
"=="
]
],
"url": "/_mozilla/mozilla/restyle-out-of-document.html"
}
],
"mozilla/scrolling_div_background_borders.html": [
{
"path": "mozilla/scrolling_div_background_borders.html",
@ -21720,6 +21732,18 @@
"url": "/_mozilla/mozilla/iframe/resize_after_load.html"
}
],
"mozilla/restyle-out-of-document.html": [
{
"path": "mozilla/restyle-out-of-document.html",
"references": [
[
"/_mozilla/mozilla/restyle-out-of-document-ref.html",
"=="
]
],
"url": "/_mozilla/mozilla/restyle-out-of-document.html"
}
],
"mozilla/scrolling_div_background_borders.html": [
{
"path": "mozilla/scrolling_div_background_borders.html",

View file

@ -0,0 +1,3 @@
<!doctype html>
<meta charset="utf-8">
<span>Visible content.</span>

View file

@ -0,0 +1,13 @@
<!doctype html>
<meta charset="utf-8">
<title>Verify that dirtying an element and removing it from the document before it's restyled doesn't mess up layout</title>
<link rel='match' href='restyle-out-of-document-ref.html'>
<div><strong>Removed content.</strong></div>
<span>Visible content.</span>
<script>
addEventListener('load', function() {
var d = document.querySelector('div');
d.firstChild.style.display = "none";
d.remove();
}, true);
</script>