script: Split Pipeline::create into chrome process and content

process parts.

This will make it easier to adapt to IPC.

The trickiest part here was to make script tasks spawn new layout tasks
directly instead of having the pipeline do it for them. The latter
approach will not work in multiprocess mode, because layout and script
must run in the same address space and the pipeline cannot inject tasks
into another process.
This commit is contained in:
Patrick Walton 2015-07-13 19:59:13 -07:00
parent 64751b8eef
commit e5b1ec4078
12 changed files with 316 additions and 149 deletions

View file

@ -30,6 +30,9 @@ path = "../profile_traits"
[dependencies.script_traits]
path = "../script_traits"
[dependencies.layout_traits]
path = "../layout_traits"
[dependencies.devtools_traits]
path = "../devtools_traits"

View file

@ -10,15 +10,17 @@ use dom::node::LayoutData;
use euclid::point::Point2D;
use euclid::rect::Rect;
use ipc_channel::ipc::IpcSender;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use libc::uintptr_t;
use msg::compositor_msg::LayerId;
use msg::constellation_msg::{PipelineExitType, WindowSizeData};
use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId};
use msg::constellation_msg::{WindowSizeData};
use msg::compositor_msg::Epoch;
use net_traits::image_cache_task::ImageCacheTask;
use net_traits::PendingAsyncLoad;
use profile_traits::mem::{Reporter, ReportsChan};
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress};
use script_traits::StylesheetLoadResponder;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan};
use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress};
use std::any::Any;
use std::sync::mpsc::{channel, Receiver, Sender};
use style::animation::PropertyAnimation;
@ -72,7 +74,12 @@ pub enum Msg {
ExitNow(PipelineExitType),
/// Get the last epoch counter for this layout task.
GetCurrentEpoch(IpcSender<Epoch>)
GetCurrentEpoch(IpcSender<Epoch>),
/// Creates a new layout task.
///
/// This basically exists to keep the script-layout dependency one-way.
CreateLayoutTask(NewLayoutTaskInfo),
}
/// Synchronous messages that script can send to layout.
@ -209,3 +216,17 @@ impl Animation {
}
}
pub struct NewLayoutTaskInfo {
pub id: PipelineId,
pub url: Url,
pub is_parent: bool,
pub layout_pair: OpaqueScriptLayoutChannel,
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
pub constellation_chan: ConstellationChan,
pub failure: Failure,
pub script_chan: Sender<ConstellationControlMsg>,
pub image_cache_task: ImageCacheTask,
pub paint_chan: Box<Any + Send>,
pub layout_shutdown_chan: Sender<()>,
}

View file

@ -46,6 +46,7 @@ extern crate fnv;
extern crate hyper;
extern crate ipc_channel;
extern crate js;
extern crate layout_traits;
extern crate libc;
extern crate msg;
extern crate net_traits;

View file

@ -42,8 +42,8 @@ use dom::servohtmlparser::{ServoHTMLParser, ParserContext};
use dom::window::{Window, WindowHelpers, ScriptHelpers, ReflowReason};
use dom::worker::TrustedWorkerAddress;
use parse::html::{ParseContext, parse_html};
use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowGoal, ReflowQueryType};
use layout_interface;
use layout_interface::{self, NewLayoutTaskInfo, ScriptLayoutChan, LayoutChan, ReflowGoal};
use layout_interface::{ReflowQueryType};
use network_listener::NetworkListener;
use page::{Page, IterablePage, Frame};
use timers::TimerId;
@ -925,18 +925,44 @@ impl ScriptTask {
containing_pipeline_id,
new_pipeline_id,
subpage_id,
layout_chan,
load_data,
paint_chan,
failure,
pipeline_port,
layout_shutdown_chan,
} = new_layout_info;
let layout_pair = ScriptTask::create_layout_channel(None::<&mut ScriptTask>);
let layout_chan = LayoutChan(*ScriptTask::clone_layout_channel(
None::<&mut ScriptTask>,
&layout_pair).downcast::<Sender<layout_interface::Msg>>().unwrap());
let layout_creation_info = NewLayoutTaskInfo {
id: new_pipeline_id,
url: load_data.url.clone(),
is_parent: false,
layout_pair: layout_pair,
pipeline_port: pipeline_port,
constellation_chan: self.constellation_chan.clone(),
failure: failure,
paint_chan: paint_chan,
script_chan: self.control_chan.0.clone(),
image_cache_task: self.image_cache_task.clone(),
layout_shutdown_chan: layout_shutdown_chan,
};
let page = self.root_page();
let parent_page = page.find(containing_pipeline_id).expect("ScriptTask: received a layout
whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug.");
let parent_window = parent_page.window();
let chan = layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap();
let layout_chan = LayoutChan(chan.clone());
// Tell layout to actually spawn the task.
parent_window.layout_chan()
.0
.send(layout_interface::Msg::CreateLayoutTask(layout_creation_info))
.unwrap();
// Kick off the fetch for the new resource.
let new_load = InProgressLoad::new(new_pipeline_id, Some((containing_pipeline_id, subpage_id)),
layout_chan, parent_window.r().window_size(),