aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs61
1 files changed, 45 insertions, 16 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 7ae23dba2a2..e01a8caff39 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -29,9 +29,7 @@ use dom::worker::{Worker, TrustedWorkerAddress};
use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress};
use html::hubbub_html_parser::{InputString, InputUrl, HtmlParserResult, HtmlDiscoveredScript};
use html::hubbub_html_parser;
-use layout_interface::{ScriptLayoutChan, LayoutChan, MatchSelectorsDocumentDamage};
-use layout_interface::{ReflowDocumentDamage, ReflowForDisplay};
-use layout_interface::ContentChangedDocumentDamage;
+use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowForDisplay};
use layout_interface;
use page::{Page, IterablePage, Frame};
@@ -52,6 +50,7 @@ use servo_msg::constellation_msg;
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::geometry::to_frac_px;
+use servo_util::smallvec::{SmallVec1, SmallVec};
use servo_util::task::spawn_named_with_send_on_failure;
use geom::point::Point2D;
@@ -66,6 +65,7 @@ use url::Url;
use libc::size_t;
use std::any::{Any, AnyRefExt};
use std::cell::RefCell;
+use std::collections::HashSet;
use std::comm::{channel, Sender, Receiver, Select};
use std::mem::replace;
use std::rc::Rc;
@@ -445,7 +445,9 @@ impl ScriptTask {
}
};
- // Squash any pending resize events in the queue.
+ let mut needs_reflow = HashSet::new();
+
+ // Squash any pending resize and reflow events in the queue.
loop {
match event {
// This has to be handled before the ResizeMsg below,
@@ -459,6 +461,13 @@ impl ScriptTask {
let page = page.find(id).expect("resize sent to nonexistent pipeline");
page.resize_event.set(Some(size));
}
+ FromConstellation(SendEventMsg(id, ReflowEvent(node_addresses))) => {
+ let mut page = self.page.borrow_mut();
+ let inner_page = page.find(id).expect("Reflow sent to nonexistent pipeline");
+ let mut pending = inner_page.pending_dirty_nodes.borrow_mut();
+ pending.push_all_move(node_addresses);
+ needs_reflow.insert(id);
+ }
_ => {
sequential.push(event);
}
@@ -507,6 +516,11 @@ impl ScriptTask {
}
}
+ // Now process any pending reflows.
+ for id in needs_reflow.into_iter() {
+ self.handle_event(id, ReflowEvent(SmallVec1::new()));
+ }
+
true
}
@@ -632,8 +646,7 @@ impl ScriptTask {
if page.pending_reflows.get() > 0 {
page.pending_reflows.set(0);
- page.damage(MatchSelectorsDocumentDamage);
- page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor);
+ self.force_reflow(&*page);
}
}
@@ -711,8 +724,7 @@ impl ScriptTask {
Some((ref loaded, needs_reflow)) if *loaded == url => {
*page.mut_url() = Some((loaded.clone(), false));
if needs_reflow {
- page.damage(ContentChangedDocumentDamage);
- page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor);
+ self.force_reflow(&*page);
}
return;
},
@@ -796,7 +808,11 @@ impl ScriptTask {
// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {}", url);
- document.content_changed();
+ {
+ let document_js_ref = (&*document).clone();
+ let document_as_node = NodeCast::from_ref(document_js_ref);
+ document.content_changed(document_as_node);
+ }
window.flush_layout(ReflowForDisplay);
{
@@ -856,6 +872,21 @@ impl ScriptTask {
self.compositor.scroll_fragment_point(pipeline_id, LayerId::null(), point);
}
+ fn force_reflow(&self, page: &Page) {
+ {
+ let mut pending = page.pending_dirty_nodes.borrow_mut();
+ let js_runtime = self.js_runtime.deref().ptr;
+
+ for untrusted_node in pending.into_iter() {
+ let node = node::from_untrusted_node_address(js_runtime, untrusted_node).root();
+ node.dirty();
+ }
+ }
+
+ page.damage();
+ page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor);
+ }
+
/// This is the main entry point for receiving and dispatching DOM events.
///
/// TODO: Actually perform DOM event dispatch.
@@ -870,8 +901,7 @@ impl ScriptTask {
let frame = page.frame();
if frame.is_some() {
- page.damage(ReflowDocumentDamage);
- page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor)
+ self.force_reflow(&*page);
}
let fragment_node =
@@ -906,8 +936,9 @@ impl ScriptTask {
}
// FIXME(pcwalton): This reflows the entire document and is not incremental-y.
- ReflowEvent => {
+ ReflowEvent(to_dirty) => {
debug!("script got reflow event");
+ assert_eq!(to_dirty.len(), 0);
let page = get_page(&*self.page.borrow(), pipeline_id);
let frame = page.frame();
if frame.is_some() {
@@ -915,8 +946,7 @@ impl ScriptTask {
if in_layout {
page.pending_reflows.set(page.pending_reflows.get() + 1);
} else {
- page.damage(MatchSelectorsDocumentDamage);
- page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor)
+ self.force_reflow(&*page);
}
}
}
@@ -1021,8 +1051,7 @@ impl ScriptTask {
if target_compare {
if mouse_over_targets.is_some() {
- page.damage(MatchSelectorsDocumentDamage);
- page.reflow(ReflowForDisplay, self.control_chan.clone(), &*self.compositor);
+ self.force_reflow(&*page);
}
*mouse_over_targets = Some(target_list);
}