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.rs136
1 files changed, 87 insertions, 49 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 2d64f53b396..0f3f5c1b564 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -12,11 +12,11 @@ use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, Documen
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, NodeCast, EventCast};
+use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::global::GlobalRef;
-use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
+use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, RootedReference};
use dom::bindings::js::{RootCollection, RootCollectionPtr};
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference};
use dom::bindings::structuredclone::StructuredCloneData;
@@ -28,10 +28,12 @@ use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
use dom::uievent::UIEvent;
use dom::eventtarget::{EventTarget, EventTargetHelpers};
use dom::htmlelement::HTMLElementTypeId;
+use dom::htmliframeelement::HTMLIFrameElement;
use dom::keyboardevent::KeyboardEvent;
use dom::mouseevent::MouseEvent;
use dom::node::{self, Node, NodeHelpers, NodeDamage, NodeTypeId};
use dom::window::{Window, WindowHelpers, ScriptHelpers};
+use dom::worker::{Worker, TrustedWorkerAddress};
use parse::html::{HTMLInput, parse_html};
use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowGoal, ReflowQueryType};
use layout_interface;
@@ -41,7 +43,7 @@ use devtools;
use devtools_traits::{DevtoolsControlChan, DevtoolsControlPort, NewGlobal, GetRootNode, DevtoolsPageInfo};
use devtools_traits::{DevtoolScriptControlMsg, EvaluateJS, GetDocumentElement};
-use devtools_traits::{GetChildren, GetLayout, ModifyAttribute};
+use devtools_traits::{GetChildren, GetLayout, ModifyAttribute, WantsLiveNotifications};
use script_traits::CompositorEvent;
use script_traits::CompositorEvent::{ResizeEvent, ReflowEvent, ClickEvent};
use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
@@ -52,7 +54,7 @@ use script_traits::ScriptTaskFactory;
use servo_msg::compositor_msg::ReadyState::{FinishedLoading, Loading, PerformingLayout};
use servo_msg::compositor_msg::{LayerId, ScriptListener};
use servo_msg::constellation_msg::{ConstellationChan};
-use servo_msg::constellation_msg::{LoadData, NavigationDirection, PipelineId};
+use servo_msg::constellation_msg::{LoadData, NavigationDirection, PipelineId, SubpageId};
use servo_msg::constellation_msg::{Failure, Msg, WindowSizeData, Key, KeyState};
use servo_msg::constellation_msg::{KeyModifiers, SUPER, SHIFT, CONTROL, ALT};
use servo_msg::constellation_msg::{PipelineExitType};
@@ -63,6 +65,7 @@ use servo_net::resource_task::LoadData as NetLoadData;
use servo_net::storage_task::StorageTask;
use util::geometry::to_frac_px;
use util::smallvec::SmallVec;
+use util::str::DOMString;
use util::task::spawn_named_with_send_on_failure;
use util::task_state;
@@ -123,6 +126,8 @@ pub enum ScriptMsg {
/// Message sent through Worker.postMessage (only dispatched to
/// DedicatedWorkerGlobalScope).
DOMMessage(StructuredCloneData),
+ /// Sends a message to the Worker object (dispatched to all tasks) regarding error.
+ WorkerDispatchErrorEvent(TrustedWorkerAddress, DOMString, DOMString, u32, u32),
/// Generic message that encapsulates event handling.
RunnableMsg(Box<Runnable+Send>),
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
@@ -379,7 +384,8 @@ impl ScriptTask {
resource_task.clone(),
storage_task,
constellation_chan.clone(),
- js_context.clone());
+ js_context.clone(),
+ devtools_chan.clone());
let (devtools_sender, devtools_receiver) = channel();
ScriptTask {
@@ -581,8 +587,8 @@ impl ScriptTask {
match msg {
ConstellationControlMsg::AttachLayout(_) =>
panic!("should have handled AttachLayout already"),
- ConstellationControlMsg::Load(id, load_data) =>
- self.load(id, load_data),
+ ConstellationControlMsg::Load(id, parent, load_data) =>
+ self.load(id, parent, load_data),
ConstellationControlMsg::SendEvent(id, event) =>
self.handle_event(id, event),
ConstellationControlMsg::ReflowComplete(id, reflow_id) =>
@@ -616,6 +622,8 @@ impl ScriptTask {
self.handle_exit_window_msg(id),
ScriptMsg::DOMMessage(..) =>
panic!("unexpected message"),
+ ScriptMsg::WorkerDispatchErrorEvent(addr, msg, file_name,line_num, col_num) =>
+ Worker::handle_error_message(addr, msg, file_name, line_num, col_num),
ScriptMsg::RunnableMsg(runnable) =>
runnable.handler(),
ScriptMsg::RefcountCleanup(addr) =>
@@ -637,6 +645,8 @@ impl ScriptTask {
devtools::handle_get_layout(&*self.page.borrow(), id, node_id, reply),
ModifyAttribute(id, node_id, modifications) =>
devtools::handle_modify_attribute(&*self.page.borrow(), id, node_id, modifications),
+ WantsLiveNotifications(pipeline_id, to_send) =>
+ devtools::handle_wants_live_notifications(&*self.page.borrow(), pipeline_id, to_send),
}
}
@@ -660,7 +670,8 @@ impl ScriptTask {
parent_page.resource_task.clone(),
parent_page.storage_task.clone(),
self.constellation_chan.clone(),
- self.js_context.borrow().as_ref().unwrap().clone())
+ self.js_context.borrow().as_ref().unwrap().clone(),
+ self.devtools_chan.clone())
};
parent_page.children.borrow_mut().push(Rc::new(new_page));
}
@@ -742,9 +753,10 @@ impl ScriptTask {
}
// otherwise find just the matching page and exit all sub-pages
- match page.remove(id) {
+ match page.find(id) {
Some(ref mut page) => {
shut_down_layout(&*page, (*self.js_runtime).ptr, exit_type);
+ page.remove(id);
false
}
// TODO(tkuehn): pipeline closing is currently duplicated across
@@ -757,12 +769,37 @@ impl ScriptTask {
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
- fn load(&self, pipeline_id: PipelineId, load_data: LoadData) {
+ fn load(&self, pipeline_id: PipelineId,
+ parent: Option<(PipelineId, SubpageId)>, load_data: LoadData) {
let url = load_data.url.clone();
debug!("ScriptTask: loading {:?} on page {:?}", url, pipeline_id);
- let page = self.page.borrow_mut();
- let page = page.find(pipeline_id).expect("ScriptTask: received a load
+ let borrowed_page = self.page.borrow_mut();
+
+ let frame_element = parent.and_then(|(parent_id, subpage_id)| {
+ // In the case a parent id exists but the matching page
+ // cannot be found, this means the page exists in a different
+ // script task (due to origin) so it shouldn't be returned.
+ // TODO: window.parent will continue to return self in that
+ // case, which is wrong. We should be returning an object that
+ // denies access to most properties (per
+ // https://github.com/servo/servo/issues/3939#issuecomment-62287025).
+ borrowed_page.find(parent_id).and_then(|page| {
+ let match_iframe = |&:&node: &JSRef<HTMLIFrameElement>| {
+ node.subpage_id().map_or(false, |id| id == subpage_id)
+ };
+
+ let doc = page.frame().as_ref().unwrap().document.root();
+ let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
+
+ doc.traverse_preorder()
+ .filter_map(|node| HTMLIFrameElementCast::to_ref(node))
+ .find(match_iframe)
+ .map(|node| Temporary::from_rooted(ElementCast::from_ref(node)))
+ })
+ }).root();
+
+ let page = borrowed_page.find(pipeline_id).expect("ScriptTask: received a load
message for a layout channel that is not associated with this script task. This
is a bug.");
@@ -839,9 +876,9 @@ impl ScriptTask {
IsHTMLDocument::HTMLDocument, None,
DocumentSource::FromParser).root();
if let Some(tm) = last_modified {
- document.set_last_modified(dom_last_modified(&tm));
+ document.r().set_last_modified(dom_last_modified(&tm));
}
- window.r().init_browser_context(document.r());
+ window.r().init_browser_context(document.r(), frame_element.r());
{
@@ -943,7 +980,7 @@ impl ScriptTask {
fn handle_event(&self, pipeline_id: PipelineId, event: CompositorEvent) {
match event {
ResizeEvent(new_size) => {
- self.handle_resize_event(pipeline_id, new_size);
+ self.handle_resize_event(pipeline_id, new_size);
}
ReflowEvent(nodes) => {
@@ -971,13 +1008,13 @@ impl ScriptTask {
}
ClickEvent(_button, point) => {
- self.handle_click_event(pipeline_id, _button, point);
+ self.handle_click_event(pipeline_id, _button, point);
}
MouseDownEvent(..) => {}
MouseUpEvent(..) => {}
MouseMoveEvent(point) => {
- self.handle_mouse_move_event(pipeline_id, point);
+ self.handle_mouse_move_event(pipeline_id, point);
}
KeyEvent(key, state, modifiers) => {
@@ -1145,8 +1182,8 @@ impl ScriptTask {
debug!("node address is {:?}", node_address.0);
let temp_node =
- node::from_untrusted_node_address(
- self.js_runtime.ptr, node_address).root();
+ node::from_untrusted_node_address(
+ self.js_runtime.ptr, node_address).root();
let maybe_elem: Option<JSRef<Element>> = ElementCast::to_ref(temp_node.r());
let maybe_node = match maybe_elem {
@@ -1210,37 +1247,37 @@ impl ScriptTask {
}
if node_address.len() > 0 {
- let top_most_node =
- node::from_untrusted_node_address(self.js_runtime.ptr, node_address[0]).root();
-
- if let Some(ref frame) = *page.frame() {
- let window = frame.window.root();
-
- let x = point.x.to_i32().unwrap_or(0);
- let y = point.y.to_i32().unwrap_or(0);
-
- let mouse_event = MouseEvent::new(window.r(),
- "mousemove".to_owned(),
- true,
- true,
- Some(window.r()),
- 0i32,
- x, y, x, y,
- false, false, false, false,
- 0i16,
- None).root();
-
- let event: JSRef<Event> = EventCast::from_ref(mouse_event.r());
- let target: JSRef<EventTarget> = EventTargetCast::from_ref(top_most_node.r());
- event.fire(target);
- }
+ let top_most_node =
+ node::from_untrusted_node_address(self.js_runtime.ptr, node_address[0]).root();
+
+ if let Some(ref frame) = *page.frame() {
+ let window = frame.window.root();
+
+ let x = point.x.to_i32().unwrap_or(0);
+ let y = point.y.to_i32().unwrap_or(0);
+
+ let mouse_event = MouseEvent::new(window.r(),
+ "mousemove".to_owned(),
+ true,
+ true,
+ Some(window.r()),
+ 0i32,
+ x, y, x, y,
+ false, false, false, false,
+ 0i16,
+ None).root();
+
+ let event: JSRef<Event> = EventCast::from_ref(mouse_event.r());
+ let target: JSRef<EventTarget> = EventTargetCast::from_ref(top_most_node.r());
+ event.fire(target);
+ }
}
for node_address in node_address.iter() {
let temp_node =
- node::from_untrusted_node_address(self.js_runtime.ptr, *node_address);
+ node::from_untrusted_node_address(self.js_runtime.ptr, *node_address).root();
- let maybe_node = temp_node.root().ancestors().find(|node| node.is_element());
+ let maybe_node = temp_node.r().ancestors().find(|node| node.is_element());
match maybe_node {
Some(node) => {
node.set_hover_state(true);
@@ -1285,8 +1322,9 @@ fn shut_down_layout(page_tree: &Rc<Page>, rt: *mut JSRuntime, exit_type: Pipelin
// processed this message.
let (response_chan, response_port) = channel();
let LayoutChan(ref chan) = page.layout_chan;
- chan.send(layout_interface::Msg::PrepareToExit(response_chan)).unwrap();
- response_port.recv().unwrap();
+ if chan.send(layout_interface::Msg::PrepareToExit(response_chan)).is_ok() {
+ response_port.recv().unwrap();
+ }
}
// Remove our references to the DOM objects in this page tree.
@@ -1308,7 +1346,7 @@ fn shut_down_layout(page_tree: &Rc<Page>, rt: *mut JSRuntime, exit_type: Pipelin
// Destroy the layout task. If there were node leaks, layout will now crash safely.
for page in page_tree.iter() {
let LayoutChan(ref chan) = page.layout_chan;
- chan.send(layout_interface::Msg::ExitNow(exit_type)).unwrap();
+ chan.send(layout_interface::Msg::ExitNow(exit_type)).ok();
}
}
@@ -1392,7 +1430,7 @@ impl DocumentProgressHandler {
EventCancelable::NotCancelable).root();
let wintarget: JSRef<EventTarget> = EventTargetCast::from_ref(window.r());
let doctarget: JSRef<EventTarget> = EventTargetCast::from_ref(document.r());
- event.set_trusted(true);
+ event.r().set_trusted(true);
let _ = wintarget.dispatch_event_with_target(doctarget, event.r());
}
}