diff options
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r-- | components/script/script_task.rs | 94 |
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(); |