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.rs94
1 files changed, 39 insertions, 55 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index d44bec8e268..9a20afe4a7b 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -23,8 +23,7 @@ use dom::event::{Event, EventHelpers, Bubbles, DoesNotBubble, Cancelable, NotCan
use dom::uievent::UIEvent;
use dom::eventtarget::{EventTarget, EventTargetHelpers};
use dom::keyboardevent::KeyboardEvent;
-use dom::node;
-use dom::node::{ElementNodeTypeId, Node, NodeHelpers};
+use dom::node::{mod, ElementNodeTypeId, Node, NodeHelpers, OtherNodeDamage};
use dom::window::{Window, WindowHelpers};
use dom::worker::{Worker, TrustedWorkerAddress};
use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress};
@@ -40,10 +39,9 @@ use devtools_traits::{DevtoolScriptControlMsg, EvaluateJS, GetDocumentElement};
use devtools_traits::{GetChildren, GetLayout, ModifyAttribute};
use script_traits::{CompositorEvent, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent};
use script_traits::{MouseMoveEvent, MouseUpEvent, ConstellationControlMsg, ScriptTaskFactory};
-use script_traits::{ResizeMsg, AttachLayoutMsg, LoadMsg, ViewportMsg, SendEventMsg};
+use script_traits::{ResizeMsg, AttachLayoutMsg, GetTitleMsg, KeyEvent, LoadMsg, ViewportMsg};
use script_traits::{ResizeInactiveMsg, ExitPipelineMsg, NewLayoutInfo, OpaqueScriptLayoutChannel};
-use script_traits::{ScriptControlChan, ReflowCompleteMsg, UntrustedNodeAddress, KeyEvent};
-use script_traits::{GetTitleMsg};
+use script_traits::{ScriptControlChan, ReflowCompleteMsg, SendEventMsg};
use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading, PerformingLayout};
use servo_msg::compositor_msg::{ScriptListener};
use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg};
@@ -57,7 +55,7 @@ use servo_net::resource_task::{ResourceTask, Load};
use servo_net::resource_task::LoadData as NetLoadData;
use servo_net::storage_task::StorageTask;
use servo_util::geometry::to_frac_px;
-use servo_util::smallvec::{SmallVec1, SmallVec};
+use servo_util::smallvec::SmallVec;
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::task_state;
@@ -74,7 +72,6 @@ use url::Url;
use libc::size_t;
use std::any::{Any, AnyRefExt};
-use std::collections::HashSet;
use std::comm::{channel, Sender, Receiver, Select};
use std::fmt::{mod, Show};
use std::mem::replace;
@@ -480,8 +477,6 @@ impl ScriptTask {
}
};
- let mut needs_reflow = HashSet::new();
-
// Squash any pending resize and reflow events in the queue.
loop {
match event {
@@ -496,18 +491,12 @@ 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 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);
- }
FromConstellation(ViewportMsg(id, rect)) => {
let page = self.page.borrow_mut();
let inner_page = page.find(id).expect("Page rect message sent to nonexistent pipeline");
if inner_page.set_page_clip_rect_with_new_viewport(rect) {
- needs_reflow.insert(id);
+ let page = get_page(&*self.page.borrow(), id);
+ self.force_reflow(&*page);
}
}
_ => {
@@ -541,11 +530,6 @@ impl ScriptTask {
}
}
- // Now process any pending reflows.
- for id in needs_reflow.into_iter() {
- self.handle_event(id, ReflowEvent(SmallVec1::new()));
- }
-
true
}
@@ -666,11 +650,6 @@ impl ScriptTask {
}
self.compositor.borrow_mut().set_ready_state(pipeline_id, FinishedLoading);
-
- if page.pending_reflows.get() > 0 {
- page.pending_reflows.set(0);
- self.force_reflow(&*page);
- }
}
/// Handles a navigate forward or backward message.
@@ -838,8 +817,12 @@ impl ScriptTask {
// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {}", final_url);
- document.content_changed(NodeCast::from_ref(*document));
- window.flush_layout();
+ {
+ let document_js_ref = (&*document).clone();
+ let document_as_node = NodeCast::from_ref(document_js_ref);
+ document.content_changed(document_as_node, OtherNodeDamage);
+ }
+ window.flush_layout(ReflowForDisplay, NoQuery);
{
// No more reflow required
@@ -895,18 +878,9 @@ impl ScriptTask {
self.compositor.borrow_mut().scroll_fragment_point(pipeline_id, LayerId::null(), point);
}
+ /// Reflows non-incrementally.
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.dirty_all_nodes();
page.reflow(ReflowForDisplay,
self.control_chan.clone(),
&mut **self.compositor.borrow_mut(),
@@ -922,9 +896,27 @@ impl ScriptTask {
self.handle_resize_event(pipeline_id, new_size);
}
- // FIXME(pcwalton): This reflows the entire document and is not incremental-y.
- ReflowEvent(to_dirty) => {
- self.handle_reflow_event(pipeline_id, to_dirty);
+ ReflowEvent(nodes) => {
+ // FIXME(pcwalton): This event seems to only be used by the image cache task, and
+ // the interaction between it and the image holder is really racy. I think that, in
+ // order to fix this race, we need to rewrite the image cache task to make the
+ // image holder responsible for the lifecycle of image loading instead of having
+ // the image holder and layout task both be observers. Then we can have the DOM
+ // image element observe the state of the image holder and have it send reflows
+ // via the normal dirtying mechanism, and ultimately remove this event.
+ //
+ // See the implementation of `Width()` and `Height()` in `HTMLImageElement` for
+ // fallout of this problem.
+ for node in nodes.iter() {
+ let node_to_dirty = node::from_untrusted_node_address(self.js_runtime.ptr,
+ *node).root();
+ let page = get_page(&*self.page.borrow(), pipeline_id);
+ let frame = page.frame();
+ let document = frame.as_ref().unwrap().document.root();
+ document.content_changed(*node_to_dirty, OtherNodeDamage);
+ }
+
+ self.handle_reflow_event(pipeline_id);
}
ClickEvent(_button, point) => {
@@ -1020,7 +1012,7 @@ impl ScriptTask {
_ => ()
}
- window.flush_layout();
+ window.flush_layout(ReflowForDisplay, NoQuery);
}
/// The entry point for content to notify that a new load has been requested
@@ -1084,18 +1076,12 @@ impl ScriptTask {
}
}
- fn handle_reflow_event(&self, pipeline_id: PipelineId, to_dirty: SmallVec1<UntrustedNodeAddress>) {
+ fn handle_reflow_event(&self, pipeline_id: PipelineId) {
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() {
- let in_layout = page.layout_join_port.borrow().is_some();
- if in_layout {
- page.pending_reflows.set(page.pending_reflows.get() + 1);
- } else {
- self.force_reflow(&*page);
- }
+ self.force_reflow(&*page);
}
}
@@ -1138,7 +1124,7 @@ impl ScriptTask {
el.authentic_click_activation(*event);
doc.commit_focus_transaction();
- window.flush_layout();
+ window.flush_layout(ReflowForDisplay, NoQuery);
}
None => {}
}
@@ -1220,8 +1206,6 @@ impl ScriptTask {
/// Shuts down layout for the given page tree.
fn shut_down_layout(page_tree: &Rc<Page>, rt: *mut JSRuntime) {
for page in page_tree.iter() {
- page.join_layout();
-
// Tell the layout task to begin shutting down, and wait until it
// processed this message.
let (response_chan, response_port) = channel();