diff options
author | Martin Robinson <mrobinson@igalia.com> | 2024-12-26 04:34:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-26 03:34:54 +0000 |
commit | 5f927a2c285c779b631ba36520904189ebd5cd4c (patch) | |
tree | fd9326f2f730fad0ced85c9f8765aa866fba95e5 /components/script | |
parent | 1e95712772284e434ab8f4c028d6cf78d2f63e1c (diff) | |
download | servo-5f927a2c285c779b631ba36520904189ebd5cd4c.tar.gz servo-5f927a2c285c779b631ba36520904189ebd5cd4c.zip |
script: Refactor channels in `ScriptThread` into receivers and senders (#34776)
Create two new data structures in the `script` crate to hold senders and
receiver:
- `ScriptThreadSenders`: holds all outgoing channels from the
`ScriptThread` including a channel to the `ScriptThread` itself. The
ultimate goal with this is to reduce duplication by giving a boxed
version of this this to `Window`s.
- `ScriptThradReceivers`: holds all incoming channels to the
`ScriptThread`. This isn't cloenable like the senders. This is used to
abstract away `recv()` and `try_recv()` methods used to make the
`ScriptThread` event loop easier to read.
In addition:
- The many duplicated `ScriptThread` self-senders for the `TaskManager`
have been removed and, in general, a lot of boilerplate is removed as
well.
- Visibilty of all methods affected by this change is changed to
`pub(crate)` in order to take advantage of dead code detection. Some
dead code produced from macros is removed.
- Some conversion code is refactord into implementations of the `From`
trait.
- The names of channels uses a standard "sender" and "receiver" naming
as well as trying to be descriptive of where they go in `ScriptThread`
as well as `InitialScriptState`
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'components/script')
28 files changed, 714 insertions, 884 deletions
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs index 869f8083d87..0603a888436 100644 --- a/components/script/dom/abstractworkerglobalscope.rs +++ b/components/script/dom/abstractworkerglobalscope.rs @@ -35,7 +35,7 @@ impl ScriptChan for SendableWorkerScriptChan { self.sender.send(msg).map_err(|_| ()) } - fn clone(&self) -> Box<dyn ScriptChan + Send> { + fn as_boxed(&self) -> Box<dyn ScriptChan + Send> { Box::new(SendableWorkerScriptChan { sender: self.sender.clone(), worker: self.worker.clone(), @@ -62,7 +62,7 @@ impl ScriptChan for WorkerThreadWorkerChan { self.sender.send(msg).map_err(|_| ()) } - fn clone(&self) -> Box<dyn ScriptChan + Send> { + fn as_boxed(&self) -> Box<dyn ScriptChan + Send> { Box::new(WorkerThreadWorkerChan { sender: self.sender.clone(), worker: self.worker.clone(), diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index deb79f4684e..a6d65284cb7 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -418,7 +418,7 @@ impl DedicatedWorkerGlobalScope { worker_url, devtools_mpsc_port, runtime, - parent_sender.clone(), + parent_sender.as_boxed(), own_sender, receiver, closing, diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 577b21d7dc2..ca26f736c5b 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -185,10 +185,11 @@ use crate::dom::windowproxy::WindowProxy; use crate::dom::xpathevaluator::XPathEvaluator; use crate::fetch::FetchCanceller; use crate::iframe_collection::IFrameCollection; +use crate::messaging::MainThreadScriptMsg; use crate::network_listener::{NetworkListener, PreInvoke}; use crate::realms::{enter_realm, AlreadyInRealm, InRealm}; use crate::script_runtime::{CanGc, CommonScriptMsg, ScriptThreadEventCategory}; -use crate::script_thread::{with_script_thread, MainThreadScriptMsg, ScriptThread}; +use crate::script_thread::{with_script_thread, ScriptThread}; use crate::stylesheet_set::StylesheetSetRef; use crate::task::TaskBox; use crate::task_source::{TaskSource, TaskSourceName}; diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index bdb8538ffd9..2779a6be2c8 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -127,6 +127,7 @@ use crate::dom::webgpu::identityhub::IdentityHub; use crate::dom::window::Window; use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workletglobalscope::WorkletGlobalScope; +use crate::messaging::MainThreadScriptChan; use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask}; use crate::network_listener::{NetworkListener, PreInvoke}; use crate::realms::{enter_realm, AlreadyInRealm, InRealm}; @@ -134,7 +135,7 @@ use crate::script_module::{DynamicModuleList, ModuleScript, ModuleTree, ScriptFe use crate::script_runtime::{ CanGc, CommonScriptMsg, JSContext as SafeJSContext, ScriptChan, ScriptPort, ThreadSafeJSContext, }; -use crate::script_thread::{with_script_thread, MainThreadScriptChan, ScriptThread}; +use crate::script_thread::{with_script_thread, ScriptThread}; use crate::security_manager::CSPViolationReporter; use crate::task::TaskCanceller; use crate::task_source::dom_manipulation::DOMManipulationTaskSource; @@ -2581,7 +2582,9 @@ impl GlobalScope { /// `ScriptChan` to send messages to the event loop of this global scope. pub fn script_chan(&self) -> Box<dyn ScriptChan + Send> { if let Some(window) = self.downcast::<Window>() { - return MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(); + return Box::new( + MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(), + ); } if let Some(worker) = self.downcast::<WorkerGlobalScope>() { return worker.script_chan(); diff --git a/components/script/dom/paintworkletglobalscope.rs b/components/script/dom/paintworkletglobalscope.rs index 9f13f0a8337..efcbe332b62 100644 --- a/components/script/dom/paintworkletglobalscope.rs +++ b/components/script/dom/paintworkletglobalscope.rs @@ -86,7 +86,7 @@ pub struct PaintWorkletGlobalScope { impl PaintWorkletGlobalScope { #[allow(unsafe_code)] - pub fn new( + pub(crate) fn new( runtime: &Runtime, pipeline_id: PipelineId, base_url: ServoUrl, diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs index b4ef6d9ade8..1703254b83d 100644 --- a/components/script/dom/serviceworkerglobalscope.rs +++ b/components/script/dom/serviceworkerglobalscope.rs @@ -143,7 +143,7 @@ impl ScriptChan for ServiceWorkerChan { .map_err(|_| ()) } - fn clone(&self) -> Box<dyn ScriptChan + Send> { + fn as_boxed(&self) -> Box<dyn ScriptChan + Send> { Box::new(ServiceWorkerChan { sender: self.sender.clone(), }) diff --git a/components/script/dom/testworkletglobalscope.rs b/components/script/dom/testworkletglobalscope.rs index 8e5597ba10e..4a42d71a292 100644 --- a/components/script/dom/testworkletglobalscope.rs +++ b/components/script/dom/testworkletglobalscope.rs @@ -31,7 +31,7 @@ pub struct TestWorkletGlobalScope { impl TestWorkletGlobalScope { #[allow(unsafe_code)] - pub fn new( + pub(crate) fn new( runtime: &Runtime, pipeline_id: PipelineId, base_url: ServoUrl, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index ac972fb80a8..a6c13ae96f3 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -145,15 +145,15 @@ use crate::dom::windowproxy::{WindowProxy, WindowProxyHandler}; use crate::dom::worklet::Worklet; use crate::dom::workletglobalscope::WorkletGlobalScopeType; use crate::layout_image::fetch_image_for_layout; +use crate::messaging::{ + ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, SendableMainThreadScriptChan, +}; use crate::microtask::MicrotaskQueue; use crate::realms::{enter_realm, InRealm}; use crate::script_runtime::{ CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory, }; -use crate::script_thread::{ - ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, ScriptThread, - SendableMainThreadScriptChan, -}; +use crate::script_thread::ScriptThread; use crate::task_manager::TaskManager; use crate::task_source::{TaskSource, TaskSourceName}; use crate::timers::{IsInterval, TimerCallback}; @@ -453,7 +453,7 @@ impl Window { self.js_runtime.borrow() } - pub fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> { + pub(crate) fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> { &self.script_chan.0 } @@ -2683,7 +2683,7 @@ impl Window { impl Window { #[allow(unsafe_code)] #[allow(clippy::too_many_arguments)] - pub fn new( + pub(crate) fn new( runtime: Rc<Runtime>, script_chan: MainThreadScriptChan, task_manager: TaskManager, diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index 0de60a7812b..63847797e68 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -49,9 +49,10 @@ use crate::dom::workletglobalscope::{ WorkletGlobalScope, WorkletGlobalScopeInit, WorkletGlobalScopeType, WorkletTask, }; use crate::fetch::load_whole_resource; +use crate::messaging::MainThreadScriptMsg; use crate::realms::InRealm; use crate::script_runtime::{CanGc, CommonScriptMsg, Runtime, ScriptThreadEventCategory}; -use crate::script_thread::{MainThreadScriptMsg, ScriptThread}; +use crate::script_thread::ScriptThread; use crate::task::TaskBox; use crate::task_source::TaskSourceName; @@ -277,7 +278,7 @@ impl Drop for WorkletThreadPool { impl WorkletThreadPool { /// Create a new thread pool and spawn the threads. /// When the thread pool is dropped, the threads will be asked to quit. - pub fn spawn(global_init: WorkletGlobalScopeInit) -> WorkletThreadPool { + pub(crate) fn spawn(global_init: WorkletGlobalScopeInit) -> WorkletThreadPool { let primary_role = WorkletThreadRole::new(false, false); let hot_backup_role = WorkletThreadRole::new(true, false); let cold_backup_role = WorkletThreadRole::new(false, true); diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index 3165ad77a9d..7a25f361172 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -27,9 +27,9 @@ use crate::dom::testworkletglobalscope::{TestWorkletGlobalScope, TestWorkletTask #[cfg(feature = "webgpu")] use crate::dom::webgpu::identityhub::IdentityHub; use crate::dom::worklet::WorkletExecutor; +use crate::messaging::MainThreadScriptMsg; use crate::script_module::ScriptFetchOptions; use crate::script_runtime::{CanGc, JSContext}; -use crate::script_thread::MainThreadScriptMsg; #[dom_struct] /// <https://drafts.css-houdini.org/worklets/#workletglobalscope> @@ -49,7 +49,7 @@ pub struct WorkletGlobalScope { impl WorkletGlobalScope { /// Create a new heap-allocated `WorkletGlobalScope`. - pub fn new( + pub(crate) fn new( scope_type: WorkletGlobalScopeType, runtime: &Runtime, pipeline_id: PipelineId, @@ -76,7 +76,7 @@ impl WorkletGlobalScope { } /// Create a new stack-allocated `WorkletGlobalScope`. - pub fn new_inherited( + pub(crate) fn new_inherited( pipeline_id: PipelineId, base_url: ServoUrl, executor: WorkletExecutor, @@ -172,7 +172,7 @@ impl WorkletGlobalScope { /// Resources required by workletglobalscopes #[derive(Clone)] -pub struct WorkletGlobalScopeInit { +pub(crate) struct WorkletGlobalScopeInit { /// Channel to the main script thread pub to_script_thread_sender: Sender<MainThreadScriptMsg>, /// Channel to a resource thread diff --git a/components/script/lib.rs b/components/script/lib.rs index 2e181725d27..6eef876d304 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -61,6 +61,9 @@ pub mod layout_dom; #[warn(deprecated)] mod mem; #[warn(deprecated)] +#[allow(unsafe_code)] +pub mod messaging; +#[warn(deprecated)] mod microtask; #[warn(deprecated)] mod network_listener; diff --git a/components/script/messaging.rs b/components/script/messaging.rs new file mode 100644 index 00000000000..f077f969b19 --- /dev/null +++ b/components/script/messaging.rs @@ -0,0 +1,398 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::cell::RefCell; +use std::option::Option; +use std::result::Result; + +use base::id::PipelineId; +use bluetooth_traits::BluetoothRequest; +use crossbeam_channel::{select, Receiver, Sender}; +use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg}; +use ipc_channel::ipc::IpcSender; +use net_traits::image_cache::PendingImageResponse; +use profile_traits::mem::{self as profile_mem, OpaqueSender}; +use profile_traits::time::{self as profile_time}; +use script_traits::{ConstellationControlMsg, LayoutMsg, Painter, ScriptMsg}; +use servo_atoms::Atom; +use timers::TimerScheduler; +#[cfg(feature = "webgpu")] +use webgpu::WebGPUMsg; + +use crate::dom::serviceworker::TrustedServiceWorkerAddress; +use crate::dom::worker::TrustedWorkerAddress; +use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; +use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue}; +use crate::task_source::TaskSourceName; + +pub(crate) type ImageCacheMsg = (PipelineId, PendingImageResponse); + +#[derive(Debug)] +pub(crate) enum MixedMessage { + FromConstellation(ConstellationControlMsg), + FromScript(MainThreadScriptMsg), + FromDevtools(DevtoolScriptControlMsg), + FromImageCache((PipelineId, PendingImageResponse)), + #[cfg(feature = "webgpu")] + FromWebGPUServer(WebGPUMsg), + TimerFired, +} + +impl MixedMessage { + pub(crate) fn pipeline_id(&self) -> Option<PipelineId> { + match self { + MixedMessage::FromConstellation(ref inner_msg) => match *inner_msg { + ConstellationControlMsg::StopDelayingLoadEventsMode(id) => Some(id), + ConstellationControlMsg::NavigationResponse(id, _) => Some(id), + ConstellationControlMsg::AttachLayout(ref new_layout_info) => new_layout_info + .parent_info + .or(Some(new_layout_info.new_pipeline_id)), + ConstellationControlMsg::Resize(id, ..) => Some(id), + ConstellationControlMsg::ThemeChange(id, ..) => Some(id), + ConstellationControlMsg::ResizeInactive(id, ..) => Some(id), + ConstellationControlMsg::UnloadDocument(id) => Some(id), + ConstellationControlMsg::ExitPipeline(id, ..) => Some(id), + ConstellationControlMsg::ExitScriptThread => None, + ConstellationControlMsg::SendEvent(id, ..) => Some(id), + ConstellationControlMsg::Viewport(id, ..) => Some(id), + ConstellationControlMsg::GetTitle(id) => Some(id), + ConstellationControlMsg::SetDocumentActivity(id, ..) => Some(id), + ConstellationControlMsg::SetThrottled(id, ..) => Some(id), + ConstellationControlMsg::SetThrottledInContainingIframe(id, ..) => Some(id), + ConstellationControlMsg::NavigateIframe(id, ..) => Some(id), + ConstellationControlMsg::PostMessage { target: id, .. } => Some(id), + ConstellationControlMsg::UpdatePipelineId(_, _, _, id, _) => Some(id), + ConstellationControlMsg::UpdateHistoryState(id, ..) => Some(id), + ConstellationControlMsg::RemoveHistoryStates(id, ..) => Some(id), + ConstellationControlMsg::FocusIFrame(id, ..) => Some(id), + ConstellationControlMsg::WebDriverScriptCommand(id, ..) => Some(id), + ConstellationControlMsg::TickAllAnimations(id, ..) => Some(id), + ConstellationControlMsg::WebFontLoaded(id, ..) => Some(id), + ConstellationControlMsg::DispatchIFrameLoadEvent { + target: _, + parent: id, + child: _, + } => Some(id), + ConstellationControlMsg::DispatchStorageEvent(id, ..) => Some(id), + ConstellationControlMsg::ReportCSSError(id, ..) => Some(id), + ConstellationControlMsg::Reload(id, ..) => Some(id), + ConstellationControlMsg::PaintMetric(id, ..) => Some(id), + ConstellationControlMsg::ExitFullScreen(id, ..) => Some(id), + ConstellationControlMsg::MediaSessionAction(..) => None, + #[cfg(feature = "webgpu")] + ConstellationControlMsg::SetWebGPUPort(..) => None, + ConstellationControlMsg::SetScrollStates(id, ..) => Some(id), + ConstellationControlMsg::SetEpochPaintTime(id, ..) => Some(id), + }, + MixedMessage::FromScript(ref inner_msg) => match *inner_msg { + MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, _, pipeline_id, _)) => { + pipeline_id + }, + MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(_)) => None, + MainThreadScriptMsg::WorkletLoaded(pipeline_id) => Some(pipeline_id), + MainThreadScriptMsg::RegisterPaintWorklet { pipeline_id, .. } => Some(pipeline_id), + MainThreadScriptMsg::Inactive => None, + MainThreadScriptMsg::WakeUp => None, + }, + MixedMessage::FromImageCache((pipeline_id, _)) => Some(*pipeline_id), + MixedMessage::FromDevtools(_) | MixedMessage::TimerFired => None, + #[cfg(feature = "webgpu")] + MixedMessage::FromWebGPUServer(..) => None, + } + } +} + +/// Messages used to control the script event loop. +#[derive(Debug)] +pub(crate) enum MainThreadScriptMsg { + /// Common variants associated with the script messages + Common(CommonScriptMsg), + /// Notifies the script thread that a new worklet has been loaded, and thus the page should be + /// reflowed. + WorkletLoaded(PipelineId), + /// Notifies the script thread that a new paint worklet has been registered. + RegisterPaintWorklet { + pipeline_id: PipelineId, + name: Atom, + properties: Vec<Atom>, + painter: Box<dyn Painter>, + }, + /// A task related to a not fully-active document has been throttled. + Inactive, + /// Wake-up call from the task queue. + WakeUp, +} + +impl QueuedTaskConversion for MainThreadScriptMsg { + fn task_source_name(&self) -> Option<&TaskSourceName> { + let script_msg = match self { + MainThreadScriptMsg::Common(script_msg) => script_msg, + _ => return None, + }; + match script_msg { + CommonScriptMsg::Task(_category, _boxed, _pipeline_id, task_source) => { + Some(task_source) + }, + _ => None, + } + } + + fn pipeline_id(&self) -> Option<PipelineId> { + let script_msg = match self { + MainThreadScriptMsg::Common(script_msg) => script_msg, + _ => return None, + }; + match script_msg { + CommonScriptMsg::Task(_category, _boxed, pipeline_id, _task_source) => *pipeline_id, + _ => None, + } + } + + fn into_queued_task(self) -> Option<QueuedTask> { + let script_msg = match self { + MainThreadScriptMsg::Common(script_msg) => script_msg, + _ => return None, + }; + let (category, boxed, pipeline_id, task_source) = match script_msg { + CommonScriptMsg::Task(category, boxed, pipeline_id, task_source) => { + (category, boxed, pipeline_id, task_source) + }, + _ => return None, + }; + Some((None, category, boxed, pipeline_id, task_source)) + } + + fn from_queued_task(queued_task: QueuedTask) -> Self { + let (_worker, category, boxed, pipeline_id, task_source) = queued_task; + let script_msg = CommonScriptMsg::Task(category, boxed, pipeline_id, task_source); + MainThreadScriptMsg::Common(script_msg) + } + + fn inactive_msg() -> Self { + MainThreadScriptMsg::Inactive + } + + fn wake_up_msg() -> Self { + MainThreadScriptMsg::WakeUp + } + + fn is_wake_up(&self) -> bool { + matches!(self, MainThreadScriptMsg::WakeUp) + } +} + +impl OpaqueSender<CommonScriptMsg> for Box<dyn ScriptChan + Send> { + fn send(&self, msg: CommonScriptMsg) { + ScriptChan::send(&**self, msg).unwrap(); + } +} + +impl ScriptPort for Receiver<CommonScriptMsg> { + fn recv(&self) -> Result<CommonScriptMsg, ()> { + self.recv().map_err(|_| ()) + } +} + +impl ScriptPort for Receiver<MainThreadScriptMsg> { + fn recv(&self) -> Result<CommonScriptMsg, ()> { + match self.recv() { + Ok(MainThreadScriptMsg::Common(script_msg)) => Ok(script_msg), + Ok(_) => panic!("unexpected main thread event message!"), + Err(_) => Err(()), + } + } +} + +impl ScriptPort for Receiver<(TrustedWorkerAddress, CommonScriptMsg)> { + fn recv(&self) -> Result<CommonScriptMsg, ()> { + self.recv().map(|(_, msg)| msg).map_err(|_| ()) + } +} + +impl ScriptPort for Receiver<(TrustedWorkerAddress, MainThreadScriptMsg)> { + fn recv(&self) -> Result<CommonScriptMsg, ()> { + match self.recv().map(|(_, msg)| msg) { + Ok(MainThreadScriptMsg::Common(script_msg)) => Ok(script_msg), + Ok(_) => panic!("unexpected main thread event message!"), + Err(_) => Err(()), + } + } +} + +impl ScriptPort for Receiver<(TrustedServiceWorkerAddress, CommonScriptMsg)> { + fn recv(&self) -> Result<CommonScriptMsg, ()> { + self.recv().map(|(_, msg)| msg).map_err(|_| ()) + } +} + +/// Encapsulates internal communication of shared messages within the script thread. +#[derive(Clone, JSTraceable)] +pub(crate) struct SendableMainThreadScriptChan(#[no_trace] pub Sender<CommonScriptMsg>); + +impl ScriptChan for SendableMainThreadScriptChan { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + self.0.send(msg).map_err(|_| ()) + } + + fn as_boxed(&self) -> Box<dyn ScriptChan + Send> { + Box::new(SendableMainThreadScriptChan((self.0).clone())) + } +} + +/// Encapsulates internal communication of main thread messages within the script thread. +#[derive(Clone, JSTraceable)] +pub(crate) struct MainThreadScriptChan(#[no_trace] pub Sender<MainThreadScriptMsg>); + +impl ScriptChan for MainThreadScriptChan { + fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { + self.0 + .send(MainThreadScriptMsg::Common(msg)) + .map_err(|_| ()) + } + + fn as_boxed(&self) -> Box<dyn ScriptChan + Send> { + Box::new(MainThreadScriptChan((self.0).clone())) + } +} + +impl OpaqueSender<CommonScriptMsg> for Sender<MainThreadScriptMsg> { + fn send(&self, msg: CommonScriptMsg) { + self.send(MainThreadScriptMsg::Common(msg)).unwrap() + } +} + +#[derive(Clone, JSTraceable)] +pub(crate) struct ScriptThreadSenders { + /// A channel to hand out to script thread-based entities that need to be able to enqueue + /// events in the event queue. + pub self_sender: MainThreadScriptChan, + + /// A handle to the bluetooth thread. + #[no_trace] + pub bluetooth_sender: IpcSender<BluetoothRequest>, + + /// A [`Sender`] that sends messages to the `Constellation`. + #[no_trace] + pub constellation_sender: IpcSender<ConstellationControlMsg>, + + /// A [`Sender`] that sends messages to the `Constellation` associated with + /// particular pipelines. + #[no_trace] + pub pipeline_to_constellation_sender: IpcSender<(PipelineId, ScriptMsg)>, + + /// A sender for layout to communicate to the constellation. + #[no_trace] + pub layout_to_constellation_ipc_sender: IpcSender<LayoutMsg>, + + /// The [`Sender`] on which messages can be sent to the `ImageCache`. + #[no_trace] + pub image_cache_sender: Sender<ImageCacheMsg>, + + /// For providing contact with the time profiler. + #[no_trace] + pub time_profiler_sender: profile_time::ProfilerChan, + + /// For providing contact with the memory profiler. + #[no_trace] + pub memory_profiler_sender: profile_mem::ProfilerChan, + + /// For providing instructions to an optional devtools server. + #[no_trace] + pub devtools_server_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>, + + #[no_trace] + pub devtools_client_to_script_thread_sender: IpcSender<DevtoolScriptControlMsg>, + + #[no_trace] + pub content_process_shutdown_sender: Sender<()>, +} + +#[derive(JSTraceable)] +pub(crate) struct ScriptThreadReceivers { + /// A [`Receiver`] that receives messages from the constellation. + #[no_trace] + pub constellation_receiver: Receiver<ConstellationControlMsg>, + + /// The [`Receiver`] which receives incoming messages from the `ImageCache`. + #[no_trace] + pub image_cache_receiver: Receiver<ImageCacheMsg>, + + /// For receiving commands from an optional devtools server. Will be ignored if + /// no such server exists. + #[no_trace] + pub devtools_server_receiver: Receiver<DevtoolScriptControlMsg>, + + /// Receiver to receive commands from optional WebGPU server. + #[no_trace] + #[cfg(feature = "webgpu")] + pub webgpu_receiver: RefCell<Receiver<WebGPUMsg>>, +} + +impl ScriptThreadReceivers { + /// Block until a message is received by any of the receivers of this [`ScriptThreadReceivers`] + /// or the given [`TaskQueue`] or [`TimerScheduler`]. Return the first message received. + pub(crate) fn recv( + &self, + task_queue: &TaskQueue<MainThreadScriptMsg>, + timer_scheduler: &TimerScheduler, + ) -> MixedMessage { + select! { + recv(task_queue.select()) -> msg => { + task_queue.take_tasks(msg.unwrap()); + let event = task_queue + .recv() + .expect("Spurious wake-up of the event-loop, task-queue has no tasks available"); + MixedMessage::FromScript(event) + }, + recv(self.constellation_receiver) -> msg => MixedMessage::FromConstellation(msg.unwrap()), + recv(self.devtools_server_receiver) -> msg => MixedMessage::FromDevtools(msg.unwrap()), + recv(self.image_cache_receiver) -> msg => MixedMessage::FromImageCache(msg.unwrap()), + recv(timer_scheduler.wait_channel()) -> _ => MixedMessage::TimerFired, + recv({ + #[cfg(feature = "webgpu")] + { + self.webgpu_receiver.borrow() + } + #[cfg(not(feature = "webgpu"))] + { + &crossbeam_channel::never::<()>() + } + }) -> msg => { + #[cfg(feature = "webgpu")] + { + MixedMessage::FromWebGPUServer(msg.unwrap()) + } + #[cfg(not(feature = "webgpu"))] + { + unreachable!("This should never be hit when webgpu is disabled"); + } + } + } + } + + /// Try to receive a from any of the receivers of this [`ScriptThreadReceivers`] or the given + /// [`TaskQueue`]. Return `None` if no messages are ready to be received. + pub(crate) fn try_recv( + &self, + task_queue: &TaskQueue<MainThreadScriptMsg>, + ) -> Option<MixedMessage> { + if let Ok(message) = self.constellation_receiver.try_recv() { + return MixedMessage::FromConstellation(message).into(); + } + if let Ok(message) = task_queue.take_tasks_and_recv() { + return MixedMessage::FromScript(message).into(); + } + if let Ok(message) = self.devtools_server_receiver.try_recv() { + return MixedMessage::FromDevtools(message).into(); + } + if let Ok(message) = self.image_cache_receiver.try_recv() { + return MixedMessage::FromImageCache(message).into(); + } + #[cfg(feature = "webgpu")] + if let Ok(message) = self.webgpu_receiver.borrow().try_recv() { + return MixedMessage::FromWebGPUServer(message).into(); + } + None + } +} diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index f2af000fafd..0cd2bb91e31 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -18,6 +18,7 @@ use std::sync::Mutex; use std::time::{Duration, Instant}; use std::{fmt, os, ptr, thread}; +use background_hang_monitor_api::ScriptHangAnnotation; use base::id::PipelineId; use content_security_policy::{CheckResult, PolicyDisposition}; use js::conversions::jsstr_to_string; @@ -50,6 +51,7 @@ use js::rust::{ use malloc_size_of::MallocSizeOfOps; use profile_traits::mem::{Report, ReportKind, ReportsChan}; use profile_traits::path; +use profile_traits::time::ProfilerCategory; use servo_config::{opts, pref}; use style::thread_state::{self, ThreadState}; @@ -126,8 +128,8 @@ pub trait ScriptChan: JSTraceable { /// Send a message to the associated event loop. #[allow(clippy::result_unit_err)] fn send(&self, msg: CommonScriptMsg) -> Result<(), ()>; - /// Clone this handle. - fn clone(&self) -> Box<dyn ScriptChan + Send>; + /// Return a cloned version of this sender in a [`Box`]. + fn as_boxed(&self) -> Box<dyn ScriptChan + Send>; } #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)] @@ -162,6 +164,92 @@ pub enum ScriptThreadEventCategory { WebGPUMsg, } +impl From<ScriptThreadEventCategory> for ProfilerCategory { + fn from(category: ScriptThreadEventCategory) -> Self { + match category { + ScriptThreadEventCategory::AttachLayout => ProfilerCategory::ScriptAttachLayout, + ScriptThreadEventCategory::ConstellationMsg => ProfilerCategory::ScriptConstellationMsg, + ScriptThreadEventCategory::DevtoolsMsg => ProfilerCategory::ScriptDevtoolsMsg, + ScriptThreadEventCategory::DocumentEvent => ProfilerCategory::ScriptDocumentEvent, + ScriptThreadEventCategory::DomEvent => ProfilerCategory::ScriptDomEvent, + ScriptThreadEventCategory::EnterFullscreen => ProfilerCategory::ScriptEnterFullscreen, + ScriptThreadEventCategory::ExitFullscreen => ProfilerCategory::ScriptExitFullscreen, + ScriptThreadEventCategory::FileRead => ProfilerCategory::ScriptFileRead, + ScriptThreadEventCategory::FormPlannedNavigation => { + ProfilerCategory::ScriptPlannedNavigation + }, + ScriptThreadEventCategory::HistoryEvent => ProfilerCategory::ScriptHistoryEvent, + ScriptThreadEventCategory::ImageCacheMsg => ProfilerCategory::ScriptImageCacheMsg, + ScriptThreadEventCategory::InputEvent => ProfilerCategory::ScriptInputEvent, + ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent, + ScriptThreadEventCategory::PerformanceTimelineTask => { + ProfilerCategory::ScriptPerformanceEvent + }, + ScriptThreadEventCategory::PortMessage => ProfilerCategory::ScriptPortMessage, + ScriptThreadEventCategory::Resize => ProfilerCategory::ScriptResize, + ScriptThreadEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent, + ScriptThreadEventCategory::ServiceWorkerEvent => { + ProfilerCategory::ScriptServiceWorkerEvent + }, + ScriptThreadEventCategory::SetScrollState => ProfilerCategory::ScriptSetScrollState, + ScriptThreadEventCategory::SetViewport => ProfilerCategory::ScriptSetViewport, + ScriptThreadEventCategory::StylesheetLoad => ProfilerCategory::ScriptStylesheetLoad, + ScriptThreadEventCategory::TimerEvent => ProfilerCategory::ScriptTimerEvent, + ScriptThreadEventCategory::UpdateReplacedElement => { + ProfilerCategory::ScriptUpdateReplacedElement + }, + ScriptThreadEventCategory::WebSocketEvent => ProfilerCategory::ScriptWebSocketEvent, + ScriptThreadEventCategory::WorkerEvent => ProfilerCategory::ScriptWorkerEvent, + ScriptThreadEventCategory::WorkletEvent => ProfilerCategory::ScriptWorkletEvent, + #[cfg(feature = "webgpu")] + ScriptThreadEventCategory::WebGPUMsg => ProfilerCategory::ScriptWebGPUMsg, + } + } +} + +impl From<ScriptThreadEventCategory> for ScriptHangAnnotation { + fn from(category: ScriptThreadEventCategory) -> Self { + match category { + ScriptThreadEventCategory::AttachLayout => ScriptHangAnnotation::AttachLayout, + ScriptThreadEventCategory::ConstellationMsg => ScriptHangAnnotation::ConstellationMsg, + ScriptThreadEventCategory::DevtoolsMsg => ScriptHangAnnotation::DevtoolsMsg, + ScriptThreadEventCategory::DocumentEvent => ScriptHangAnnotation::DocumentEvent, + ScriptThreadEventCategory::DomEvent => ScriptHangAnnotation::DomEvent, + ScriptThreadEventCategory::FileRead => ScriptHangAnnotation::FileRead, + ScriptThreadEventCategory::FormPlannedNavigation => { + ScriptHangAnnotation::FormPlannedNavigation + }, + ScriptThreadEventCategory::HistoryEvent => ScriptHangAnnotation::HistoryEvent, + ScriptThreadEventCategory::ImageCacheMsg => ScriptHangAnnotation::ImageCacheMsg, + ScriptThreadEventCategory::InputEvent => ScriptHangAnnotation::InputEvent, + ScriptThreadEventCategory::NetworkEvent => ScriptHangAnnotation::NetworkEvent, + ScriptThreadEventCategory::Resize => ScriptHangAnnotation::Resize, + ScriptThreadEventCategory::ScriptEvent => ScriptHangAnnotation::ScriptEvent, + ScriptThreadEventCategory::SetScrollState => ScriptHangAnnotation::SetScrollState, + ScriptThreadEventCategory::SetViewport => ScriptHangAnnotation::SetViewport, + ScriptThreadEventCategory::StylesheetLoad => ScriptHangAnnotation::StylesheetLoad, + ScriptThreadEventCategory::TimerEvent => ScriptHangAnnotation::TimerEvent, + ScriptThreadEventCategory::UpdateReplacedElement => { + ScriptHangAnnotation::UpdateReplacedElement + }, + ScriptThreadEventCategory::WebSocketEvent => ScriptHangAnnotation::WebSocketEvent, + ScriptThreadEventCategory::WorkerEvent => ScriptHangAnnotation::WorkerEvent, + ScriptThreadEventCategory::WorkletEvent => ScriptHangAnnotation::WorkletEvent, + ScriptThreadEventCategory::ServiceWorkerEvent => { + ScriptHangAnnotation::ServiceWorkerEvent + }, + ScriptThreadEventCategory::EnterFullscreen => ScriptHangAnnotation::EnterFullscreen, + ScriptThreadEventCategory::ExitFullscreen => ScriptHangAnnotation::ExitFullscreen, + ScriptThreadEventCategory::PerformanceTimelineTask => { + ScriptHangAnnotation::PerformanceTimelineTask + }, + ScriptThreadEventCategory::PortMessage => ScriptHangAnnotation::PortMessage, + #[cfg(feature = "webgpu")] + ScriptThreadEventCategory::WebGPUMsg => ScriptHangAnnotation::WebGPUMsg, + } + } +} + /// An interface for receiving ScriptMsg values in an event loop. Used for synchronous DOM /// APIs that need to abstract over multiple kinds of event loops (worker/main thread) with /// different Receiver interfaces. diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 7622a00d21f..01a079a9836 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -31,17 +31,16 @@ use std::time::{Duration, Instant, SystemTime}; use background_hang_monitor_api::{ BackgroundHangMonitor, BackgroundHangMonitorExitSignal, HangAnnotation, MonitoredComponentId, - MonitoredComponentType, ScriptHangAnnotation, + MonitoredComponentType, }; use base::cross_process_instant::CrossProcessInstant; use base::id::{ BrowsingContextId, HistoryStateId, PipelineId, PipelineNamespace, TopLevelBrowsingContextId, }; use base::Epoch; -use bluetooth_traits::BluetoothRequest; use canvas_traits::webgl::WebGLPipeline; use chrono::{DateTime, Local}; -use crossbeam_channel::{select, unbounded, Receiver, Sender}; +use crossbeam_channel::unbounded; use devtools_traits::{ CSSError, DevtoolScriptControlMsg, DevtoolsPageInfo, NavigationState, ScriptToDevtoolsControlMsg, WorkerId, @@ -52,7 +51,7 @@ use fonts::SystemFontServiceProxy; use headers::{HeaderMapExt, LastModified, ReferrerPolicy as ReferrerPolicyHeader}; use html5ever::{local_name, namespace_url, ns}; use hyper_serde::Serde; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::glue::GetWindowProxyClass; use js::jsapi::{ @@ -73,8 +72,7 @@ use net_traits::{ ResourceFetchTiming, ResourceThreads, ResourceTimingType, }; use percent_encoding::percent_decode; -use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan}; -use profile_traits::time::{self as profile_time, ProfilerCategory}; +use profile_traits::mem::ReportsChan; use profile_traits::time_profile; use script_layout_interface::{ node_id_from_scroll_id, LayoutConfig, LayoutFactory, ReflowGoal, ScriptThreadFactory, @@ -82,9 +80,9 @@ use script_layout_interface::{ use script_traits::webdriver_msg::WebDriverScriptCommand; use script_traits::{ CompositorEvent, ConstellationControlMsg, DiscardBrowsingContext, DocumentActivity, - EventResult, InitialScriptState, JsEvalResult, LayoutMsg, LoadData, LoadOrigin, - MediaSessionActionType, MouseButton, MouseEventType, NavigationHistoryBehavior, NewLayoutInfo, - Painter, ProgressiveWebMetricType, ScriptMsg, ScriptToConstellationChan, ScrollState, + EventResult, InitialScriptState, JsEvalResult, LoadData, LoadOrigin, MediaSessionActionType, + MouseButton, MouseEventType, NavigationHistoryBehavior, NewLayoutInfo, Painter, + ProgressiveWebMetricType, ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, Theme, TouchEventType, TouchId, UntrustedNodeAddress, UpdatePipelineIdReason, WheelDelta, WindowSizeData, WindowSizeType, }; @@ -134,43 +132,30 @@ use crate::dom::mutationobserver::MutationObserver; use crate::dom::node::{window_from_node, Node, ShadowIncluding}; use crate::dom::performanceentry::PerformanceEntry; use crate::dom::performancepainttiming::PerformancePaintTiming; -use crate::dom::serviceworker::TrustedServiceWorkerAddress; use crate::dom::servoparser::{ParserContext, ServoParser}; #[cfg(feature = "webgpu")] use crate::dom::webgpu::identityhub::IdentityHub; use crate::dom::window::Window; use crate::dom::windowproxy::{CreatorBrowsingContextInfo, WindowProxy}; -use crate::dom::worker::TrustedWorkerAddress; use crate::dom::worklet::WorkletThreadPool; use crate::dom::workletglobalscope::WorkletGlobalScopeInit; use crate::fetch::FetchCanceller; +use crate::messaging::{ + MainThreadScriptChan, MainThreadScriptMsg, MixedMessage, ScriptThreadReceivers, + ScriptThreadSenders, +}; use crate::microtask::{Microtask, MicrotaskQueue}; use crate::realms::enter_realm; use crate::script_module::ScriptFetchOptions; use crate::script_runtime::{ - CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory, - ThreadSafeJSContext, + CanGc, CommonScriptMsg, JSContext, Runtime, ScriptThreadEventCategory, ThreadSafeJSContext, }; use crate::task_manager::TaskManager; -use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue}; -use crate::task_source::dom_manipulation::DOMManipulationTaskSource; -use crate::task_source::file_reading::FileReadingTaskSource; -use crate::task_source::gamepad::GamepadTaskSource; -use crate::task_source::history_traversal::HistoryTraversalTaskSource; -use crate::task_source::media_element::MediaElementTaskSource; +use crate::task_queue::TaskQueue; use crate::task_source::networking::NetworkingTaskSource; -use crate::task_source::performance_timeline::PerformanceTimelineTaskSource; -use crate::task_source::port_message::PortMessageQueue; -use crate::task_source::remote_event::RemoteEventTaskSource; -use crate::task_source::rendering::RenderingTaskSource; -use crate::task_source::timer::TimerTaskSource; -use crate::task_source::user_interaction::UserInteractionTaskSource; -use crate::task_source::websocket::WebsocketTaskSource; use crate::task_source::{TaskSource, TaskSourceName}; use crate::{devtools, webdriver_handlers}; -pub type ImageCacheMsg = (PipelineId, PendingImageResponse); - thread_local!(static SCRIPT_THREAD_ROOT: Cell<Option<*const ScriptThread>> = const { Cell::new(None) }); fn with_optional_script_thread<R>(f: impl FnOnce(Option<&ScriptThread>) -> R) -> R { @@ -274,175 +259,6 @@ impl InProgressLoad { } } -#[derive(Debug)] -enum MixedMessage { - FromConstellation(ConstellationControlMsg), - FromScript(MainThreadScriptMsg), - FromDevtools(DevtoolScriptControlMsg), - FromImageCache((PipelineId, PendingImageResponse)), - #[cfg(feature = "webgpu")] - FromWebGPUServer(WebGPUMsg), - TimerFired, -} - -/// Messages used to control the script event loop. -#[derive(Debug)] -pub enum MainThreadScriptMsg { - /// Common variants associated with the script messages - Common(CommonScriptMsg), - /// Notifies the script thread that a new worklet has been loaded, and thus the page should be - /// reflowed. - WorkletLoaded(PipelineId), - /// Notifies the script thread that a new paint worklet has been registered. - RegisterPaintWorklet { - pipeline_id: PipelineId, - name: Atom, - properties: Vec<Atom>, - painter: Box<dyn Painter>, - }, - /// A task related to a not fully-active document has been throttled. - Inactive, - /// Wake-up call from the task queue. - WakeUp, -} - -impl QueuedTaskConversion for MainThreadScriptMsg { - fn task_source_name(&self) -> Option<&TaskSourceName> { - let script_msg = match self { - MainThreadScriptMsg::Common(script_msg) => script_msg, - _ => return None, - }; - match script_msg { - CommonScriptMsg::Task(_category, _boxed, _pipeline_id, task_source) => { - Some(task_source) - }, - _ => None, - } - } - - fn pipeline_id(&self) -> Option<PipelineId> { - let script_msg = match self { - MainThreadScriptMsg::Common(script_msg) => script_msg, - _ => return None, - }; - match script_msg { - CommonScriptMsg::Task(_category, _boxed, pipeline_id, _task_source) => *pipeline_id, - _ => None, - } - } - - fn into_queued_task(self) -> Option<QueuedTask> { - let script_msg = match self { - MainThreadScriptMsg::Common(script_msg) => script_msg, - _ => return None, - }; - let (category, boxed, pipeline_id, task_source) = match script_msg { - CommonScriptMsg::Task(category, boxed, pipeline_id, task_source) => { - (category, boxed, pipeline_id, task_source) - }, - _ => return None, - }; - Some((None, category, boxed, pipeline_id, task_source)) - } - - fn from_queued_task(queued_task: QueuedTask) -> Self { - let (_worker, category, boxed, pipeline_id, task_source) = queued_task; - let script_msg = CommonScriptMsg::Task(category, boxed, pipeline_id, task_source); - MainThreadScriptMsg::Common(script_msg) - } - - fn inactive_msg() -> Self { - MainThreadScriptMsg::Inactive - } - - fn wake_up_msg() -> Self { - MainThreadScriptMsg::WakeUp - } - - fn is_wake_up(&self) -> bool { - matches!(self, MainThreadScriptMsg::WakeUp) - } -} - -impl OpaqueSender<CommonScriptMsg> for Box<dyn ScriptChan + Send> { - fn send(&self, msg: CommonScriptMsg) { - ScriptChan::send(&**self, msg).unwrap(); - } -} - -impl ScriptPort for Receiver<CommonScriptMsg> { - fn recv(&self) -> Result<CommonScriptMsg, ()> { - self.recv().map_err(|_| ()) - } -} - -impl ScriptPort for Receiver<MainThreadScriptMsg> { - fn recv(&self) -> Result<CommonScriptMsg, ()> { - match self.recv() { - Ok(MainThreadScriptMsg::Common(script_msg)) => Ok(script_msg), - Ok(_) => panic!("unexpected main thread event message!"), - Err(_) => Err(()), - } - } -} - -impl ScriptPort for Receiver<(TrustedWorkerAddress, CommonScriptMsg)> { - fn recv(&self) -> Result<CommonScriptMsg, ()> { - self.recv().map(|(_, msg)| msg).map_err(|_| ()) - } -} - -impl ScriptPort for Receiver<(TrustedWorkerAddress, MainThreadScriptMsg)> { - fn recv(&self) -> Result<CommonScriptMsg, ()> { - match self.recv().map(|(_, msg)| msg) { - Ok(MainThreadScriptMsg::Common(script_msg)) => Ok(script_msg), - Ok(_) => panic!("unexpected main thread event message!"), - Err(_) => Err(()), - } - } -} - -impl ScriptPort for Receiver<(TrustedServiceWorkerAddress, CommonScriptMsg)> { - fn recv(&self) -> Result<CommonScriptMsg, ()> { - self.recv().map(|(_, msg)| msg).map_err(|_| ()) - } -} - -/// Encapsulates internal communication of shared messages within the script thread. -#[derive(JSTraceable)] -pub struct SendableMainThreadScriptChan(#[no_trace] pub Sender<CommonScriptMsg>); - -impl ScriptChan for SendableMainThreadScriptChan { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - self.0.send(msg).map_err(|_| ()) - } - - fn clone(&self) -> Box<dyn ScriptChan + Send> { - Box::new(SendableMainThreadScriptChan((self.0).clone())) - } -} - -/// Encapsulates internal communication of main thread messages within the script thread. -#[derive(JSTraceable)] -pub struct MainThreadScriptChan(#[no_trace] pub Sender<MainThreadScriptMsg>); - -impl ScriptChan for MainThreadScriptChan { - fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - self.0 - .send(MainThreadScriptMsg::Common(msg)) - .map_err(|_| ()) - } - - fn clone(&self) -> Box<dyn ScriptChan + Send> { - Box::new(MainThreadScriptChan((self.0).clone())) - } -} - -impl OpaqueSender<CommonScriptMsg> for Sender<MainThreadScriptMsg> { - fn send(&self, msg: CommonScriptMsg) { - self.send(MainThreadScriptMsg::Common(msg)).unwrap() - } -} // We borrow the incomplete parser contexts mutably during parsing, // which is fine except that parsing can trigger evaluation, // which can trigger GC, and so we can end up tracing the script @@ -470,13 +286,19 @@ pub struct ScriptThread { /// Image cache for this script thread. #[no_trace] image_cache: Arc<dyn ImageCache>, + + /// A [`ScriptThreadReceivers`] holding all of the incoming [`Receiver`]s for messages + /// to this [`ScriptThread`]. + receivers: ScriptThreadReceivers, + + /// A [`ScriptThreadMessaging`] that holds all data necessary to communicate to and + /// from the [`ScriptThread`]. + senders: ScriptThreadSenders, + /// A handle to the resource thread. This is an `Arc` to avoid running out of file descriptors if /// there are many iframes. #[no_trace] resource_threads: ResourceThreads, - /// A handle to the bluetooth thread. - #[no_trace] - bluetooth_thread: IpcSender<BluetoothRequest>, /// A queue of tasks to be executed in this script-thread. task_queue: TaskQueue<MainThreadScriptMsg>, @@ -487,88 +309,15 @@ pub struct ScriptThread { /// A flag set to `true` by the BHM on exit, and checked from within the interrupt handler. closing: Arc<AtomicBool>, - /// A channel to hand out to script thread-based entities that need to be able to enqueue - /// events in the event queue. - chan: MainThreadScriptChan, - /// A [`TimerScheduler`] used to schedule timers for this [`ScriptThread`]. Timers are handled /// in the [`ScriptThread`] event loop. #[no_trace] timer_scheduler: RefCell<TimerScheduler>, - dom_manipulation_task_sender: Box<dyn ScriptChan>, - - gamepad_task_sender: Box<dyn ScriptChan>, - - #[no_trace] - media_element_task_sender: Sender<MainThreadScriptMsg>, - - #[no_trace] - user_interaction_task_sender: Sender<MainThreadScriptMsg>, - - networking_task_sender: Box<dyn ScriptChan>, - - #[no_trace] - history_traversal_task_sender: Sender<MainThreadScriptMsg>, - - file_reading_task_sender: Box<dyn ScriptChan>, - - performance_timeline_task_sender: Box<dyn ScriptChan>, - - port_message_sender: Box<dyn ScriptChan>, - - timer_task_sender: Box<dyn ScriptChan>, - - remote_event_task_sender: Box<dyn ScriptChan>, - - rendering_task_sender: Box<dyn ScriptChan>, - - /// A channel to hand out to threads that need to respond to a message from the script thread. - #[no_trace] - control_chan: IpcSender<ConstellationControlMsg>, - - /// The port on which the constellation and layout can communicate with the - /// script thread. - #[no_trace] - control_port: Receiver<ConstellationControlMsg>, - - /// For communicating load url messages to the constellation - #[no_trace] - script_sender: IpcSender<(PipelineId, ScriptMsg)>, - - /// A sender for layout to communicate to the constellation. - #[no_trace] - layout_to_constellation_chan: IpcSender<LayoutMsg>, - /// A proxy to the `SystemFontService` to use for accessing system font lists. #[no_trace] system_font_service: Arc<SystemFontServiceProxy>, - /// The port on which we receive messages from the image cache - #[no_trace] - image_cache_port: Receiver<ImageCacheMsg>, - - /// The channel on which the image cache can send messages to ourself. - #[no_trace] - image_cache_channel: Sender<ImageCacheMsg>, - /// For providing contact with the time profiler. - #[no_trace] - time_profiler_chan: profile_time::ProfilerChan, - - /// For providing contact with the memory profiler. - #[no_trace] - mem_profiler_chan: profile_mem::ProfilerChan, - - /// For providing instructions to an optional devtools server. - #[no_trace] - devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, - /// For receiving commands from an optional devtools server. Will be ignored if - /// no such server exists. - #[no_trace] - devtools_port: Receiver<DevtoolScriptControlMsg>, - #[no_trace] - devtools_sender: IpcSender<DevtoolScriptControlMsg>, - /// The JavaScript runtime. js_runtime: Rc<Runtime>, @@ -579,9 +328,6 @@ pub struct ScriptThread { #[no_trace] closed_pipelines: DomRefCell<HashSet<PipelineId>>, - #[no_trace] - content_process_shutdown_chan: Sender<()>, - /// <https://html.spec.whatwg.org/multipage/#microtask-queue> microtask_queue: Rc<MicrotaskQueue>, @@ -669,11 +415,6 @@ pub struct ScriptThread { #[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>, - /// Receiver to receive commands from optional WebGPU server. - #[no_trace] - #[cfg(feature = "webgpu")] - webgpu_port: RefCell<Option<Receiver<WebGPUMsg>>>, - // Secure context inherited_secure_context: Option<bool>, @@ -740,7 +481,6 @@ impl ScriptThreadFactory for ScriptThread { load_data: LoadData, user_agent: Cow<'static, str>, ) { - let (script_chan, script_port) = unbounded(); thread::Builder::new() .name(format!("Script{:?}", state.id)) .spawn(move || { @@ -755,17 +495,11 @@ impl ScriptThreadFactory for ScriptThread { let parent_info = state.parent_info; let opener = state.opener; let secure = load_data.inherited_secure_context; - let mem_profiler_chan = state.mem_profiler_chan.clone(); + let memory_profiler_sender = state.memory_profiler_sender.clone(); let window_size = state.window_size; - let script_thread = ScriptThread::new( - state, - script_port, - script_chan.clone(), - layout_factory, - system_font_service, - user_agent, - ); + let script_thread = + ScriptThread::new(state, layout_factory, system_font_service, user_agent); SCRIPT_THREAD_ROOT.with(|root| { root.set(Some(&script_thread as *const _)); @@ -788,13 +522,16 @@ impl ScriptThreadFactory for ScriptThread { script_thread.pre_page_load(new_load, load_data); let reporter_name = format!("script-reporter-{:?}", id); - mem_profiler_chan.run_with_memory_reporting( + memory_profiler_sender.run_with_memory_reporting( || { script_thread.start(CanGc::note()); - let _ = script_thread.content_process_shutdown_chan.send(()); + let _ = script_thread + .senders + .content_process_shutdown_sender + .send(()); }, reporter_name, - script_chan, + script_thread.senders.self_sender.0.clone(), CommonScriptMsg::CollectReports, ); @@ -936,7 +673,10 @@ impl ScriptThread { }; let global = window.upcast::<GlobalScope>(); let trusted_global = Trusted::new(global); - let sender = script_thread.script_sender.clone(); + let sender = script_thread + .senders + .pipeline_to_constellation_sender + .clone(); let task = task!(navigate_javascript: move || { // Important re security. See https://github.com/servo/servo/issues/23373 // TODO: check according to https://w3c.github.io/webappsec-csp/#should-block-navigation-request @@ -954,7 +694,7 @@ impl ScriptThread { .queue(task, global.upcast()) .expect("Enqueing navigate js task on the DOM manipulation task source failed"); } else { - if let Some(ref sender) = script_thread.devtools_chan { + if let Some(ref sender) = script_thread.senders.devtools_server_sender { let _ = sender.send(ScriptToDevtoolsControlMsg::Navigate( browsing_context, NavigationState::Start(load_data.url.clone()), @@ -962,7 +702,8 @@ impl ScriptThread { } script_thread - .script_sender + .senders + .pipeline_to_constellation_sender .send((pipeline_id, ScriptMsg::LoadUrl(load_data, history_handling))) .expect("Sending a LoadUrl message to the constellation failed"); } @@ -1054,12 +795,15 @@ impl ScriptThread { .borrow_mut() .get_or_insert_with(|| { let init = WorkletGlobalScopeInit { - to_script_thread_sender: script_thread.chan.0.clone(), + to_script_thread_sender: script_thread.senders.self_sender.0.clone(), resource_threads: script_thread.resource_threads.clone(), - mem_profiler_chan: script_thread.mem_profiler_chan.clone(), - time_profiler_chan: script_thread.time_profiler_chan.clone(), - devtools_chan: script_thread.devtools_chan.clone(), - to_constellation_sender: script_thread.script_sender.clone(), + mem_profiler_chan: script_thread.senders.memory_profiler_sender.clone(), + time_profiler_chan: script_thread.senders.time_profiler_sender.clone(), + devtools_chan: script_thread.senders.devtools_server_sender.clone(), + to_constellation_sender: script_thread + .senders + .pipeline_to_constellation_sender + .clone(), image_cache: script_thread.image_cache.clone(), is_headless: script_thread.headless, user_agent: script_thread.user_agent.clone(), @@ -1145,10 +889,8 @@ impl ScriptThread { } /// Creates a new script thread. - pub fn new( + pub(crate) fn new( state: InitialScriptState, - port: Receiver<MainThreadScriptMsg>, - chan: Sender<MainThreadScriptMsg>, layout_factory: Arc<dyn LayoutFactory>, system_font_service: Arc<SystemFontServiceProxy>, user_agent: Cow<'static, str>, @@ -1157,10 +899,10 @@ impl ScriptThread { let prepare_for_screenshot = opts.output_file.is_some() || opts.exit_after_load || opts.webdriver_port.is_some(); - let boxed_script_sender = Box::new(MainThreadScriptChan(chan.clone())); - + let (self_sender, self_receiver) = unbounded(); + let self_sender = MainThreadScriptChan(self_sender.clone()); let runtime = Runtime::new(Some(NetworkingTaskSource( - boxed_script_sender.clone(), + Box::new(self_sender.clone()), state.id, ))); let cx = runtime.cx(); @@ -1170,14 +912,20 @@ impl ScriptThread { JS_AddInterruptCallback(cx, Some(interrupt_callback)); } + // Ask the router to proxy IPC messages from the control port to us. + let constellation_receiver = + ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(state.constellation_receiver); + // Ask the router to proxy IPC messages from the devtools to us. + let devtools_server_sender = state.devtools_server_sender; let (ipc_devtools_sender, ipc_devtools_receiver) = ipc::channel().unwrap(); - let devtools_port = - ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(ipc_devtools_receiver); - - let (image_cache_channel, image_cache_port) = unbounded(); + let devtools_server_receiver = devtools_server_sender + .as_ref() + .map(|_| ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(ipc_devtools_receiver)) + .unwrap_or_else(crossbeam_channel::never); - let task_queue = TaskQueue::new(port, chan.clone()); + let (image_cache_sender, image_cache_receiver) = unbounded(); + let task_queue = TaskQueue::new(self_receiver, self_sender.0.clone()); let closing = Arc::new(AtomicBool::new(false)); let background_hang_monitor_exit_signal = BHMExitSignal { @@ -1192,8 +940,28 @@ impl ScriptThread { Some(Box::new(background_hang_monitor_exit_signal)), ); - // Ask the router to proxy IPC messages from the control port to us. - let control_port = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(state.control_port); + let receivers = ScriptThreadReceivers { + constellation_receiver, + image_cache_receiver, + devtools_server_receiver, + // Initialized to `never` until WebGPU is initialized. + #[cfg(feature = "webgpu")] + webgpu_receiver: RefCell::new(crossbeam_channel::never()), + }; + + let senders = ScriptThreadSenders { + self_sender, + bluetooth_sender: state.bluetooth_sender, + constellation_sender: state.constellation_sender, + pipeline_to_constellation_sender: state.pipeline_to_constellation_sender.sender.clone(), + layout_to_constellation_ipc_sender: state.layout_to_constellation_ipc_sender, + image_cache_sender, + time_profiler_sender: state.time_profiler_sender, + memory_profiler_sender: state.memory_profiler_sender, + devtools_server_sender, + devtools_client_to_script_thread_sender: ipc_devtools_sender, + content_process_shutdown_sender: state.content_process_shutdown_sender, + }; ScriptThread { documents: DomRefCell::new(DocumentCollection::default()), @@ -1201,94 +969,45 @@ impl ScriptThread { window_proxies: DomRefCell::new(HashMapTracedValues::new()), incomplete_loads: DomRefCell::new(vec![]), incomplete_parser_contexts: IncompleteParserContexts(RefCell::new(vec![])), - + senders, + receivers, image_cache: state.image_cache.clone(), - image_cache_channel, - image_cache_port, - resource_threads: state.resource_threads, - bluetooth_thread: state.bluetooth_thread, - task_queue, - background_hang_monitor, closing, - - chan: MainThreadScriptChan(chan.clone()), timer_scheduler: Default::default(), - dom_manipulation_task_sender: boxed_script_sender.clone(), - gamepad_task_sender: boxed_script_sender.clone(), - media_element_task_sender: chan.clone(), - user_interaction_task_sender: chan.clone(), - networking_task_sender: boxed_script_sender.clone(), - port_message_sender: boxed_script_sender.clone(), - file_reading_task_sender: boxed_script_sender.clone(), - performance_timeline_task_sender: boxed_script_sender.clone(), - timer_task_sender: boxed_script_sender.clone(), - remote_event_task_sender: boxed_script_sender.clone(), - rendering_task_sender: boxed_script_sender.clone(), - - history_traversal_task_sender: chan.clone(), - - control_chan: state.control_chan, - control_port, - script_sender: state.script_to_constellation_chan.sender.clone(), - time_profiler_chan: state.time_profiler_chan.clone(), - mem_profiler_chan: state.mem_profiler_chan, - - devtools_chan: state.devtools_chan, - devtools_port, - devtools_sender: ipc_devtools_sender, - microtask_queue: runtime.microtask_queue.clone(), - js_runtime: Rc::new(runtime), topmost_mouse_over_target: MutNullableDom::new(Default::default()), closed_pipelines: DomRefCell::new(HashSet::new()), - - content_process_shutdown_chan: state.content_process_shutdown_chan, - mutation_observer_microtask_queued: Default::default(), - mutation_observers: Default::default(), - - layout_to_constellation_chan: state.layout_to_constellation_chan, system_font_service, - webgl_chan: state.webgl_chan, #[cfg(feature = "webxr")] webxr_registry: state.webxr_registry, - worklet_thread_pool: Default::default(), - docs_with_no_blocking_loads: Default::default(), - custom_element_reaction_stack: CustomElementReactionStack::new(), - webrender_document: state.webrender_document, compositor_api: state.compositor_api, - profile_script_events: opts.debug.profile_script_events, print_pwm: opts.print_pwm, relayout_event: opts.debug.relayout_event, - prepare_for_screenshot, unminify_js: opts.unminify_js, local_script_source: opts.local_script_source.clone(), unminify_css: opts.unminify_css, - userscripts_path: opts.userscripts.clone(), headless: opts.headless, replace_surrogates: opts.debug.replace_surrogates, user_agent, player_context: state.player_context, - node_ids: Default::default(), is_user_interacting: Cell::new(false), #[cfg(feature = "webgpu")] gpu_id_hub: Arc::new(IdentityHub::default()), - #[cfg(feature = "webgpu")] - webgpu_port: RefCell::new(None), inherited_secure_context: state.inherited_secure_context, layout_factory, } @@ -1467,7 +1186,10 @@ impl ScriptThread { EventResult::DefaultPrevented }; let message = ScriptMsg::TouchEventProcessed(result); - self.script_sender.send((pipeline_id, message)).unwrap(); + self.senders + .pipeline_to_constellation_sender + .send((pipeline_id, message)) + .unwrap(); }, _ => { // TODO: Calling preventDefault on a touchup event should prevent clicks. @@ -1697,40 +1419,9 @@ impl ScriptThread { // Receive at least one message so we don't spinloop. debug!("Waiting for event."); - let mut event = select! { - recv(self.task_queue.select()) -> msg => { - self.task_queue.take_tasks(msg.unwrap()); - let event = self - .task_queue - .recv() - .expect("Spurious wake-up of the event-loop, task-queue has no tasks available"); - MixedMessage::FromScript(event) - }, - recv(self.control_port) -> msg => MixedMessage::FromConstellation(msg.unwrap()), - recv(self.devtools_chan.as_ref().map(|_| &self.devtools_port).unwrap_or(&crossbeam_channel::never())) -> msg - => MixedMessage::FromDevtools(msg.unwrap()), - recv(self.image_cache_port) -> msg => MixedMessage::FromImageCache(msg.unwrap()), - recv(self.timer_scheduler.borrow().wait_channel()) -> _ => MixedMessage::TimerFired, - recv({ - #[cfg(feature = "webgpu")] - { - self.webgpu_port.borrow().as_ref().unwrap_or(&crossbeam_channel::never()) - } - #[cfg(not(feature = "webgpu"))] - { - &crossbeam_channel::never::<()>() - } - }) -> msg => { - #[cfg(feature = "webgpu")] - { - MixedMessage::FromWebGPUServer(msg.unwrap()) - } - #[cfg(not(feature = "webgpu"))] - { - unreachable!("This should never be hit when webgpu is disabled"); - } - }, - }; + let mut event = self + .receivers + .recv(&self.task_queue, &self.timer_scheduler.borrow()); let mut compositor_requested_update_the_rendering = false; loop { @@ -1741,8 +1432,7 @@ impl ScriptThread { .borrow_mut() .dispatch_completed_timers(); - let pipeline_id = self.message_to_pipeline(&event); - let _realm = pipeline_id.map(|id| { + let _realm = event.pipeline_id().map(|id| { let global = self.documents.borrow().find_global(id); global.map(|global| enter_realm(&*global)) }); @@ -1846,27 +1536,9 @@ impl ScriptThread { // If any of our input sources has an event pending, we'll perform another iteration // and check for more resize events. If there are no events pending, we'll move // on and execute the sequential non-resize events we've seen. - match self.control_port.try_recv() { - Err(_) => match self.task_queue.take_tasks_and_recv() { - Err(_) => match self.devtools_port.try_recv() { - Err(_) => match self.image_cache_port.try_recv() { - #[cfg(feature = "webgpu")] - Err(_) => match &*self.webgpu_port.borrow() { - Some(p) => match p.try_recv() { - Err(_) => break, - Ok(ev) => event = MixedMessage::FromWebGPUServer(ev), - }, - None => break, - }, - Ok(ev) => event = MixedMessage::FromImageCache(ev), - #[cfg(not(feature = "webgpu"))] - Err(_) => break, - }, - Ok(ev) => event = MixedMessage::FromDevtools(ev), - }, - Ok(ev) => event = MixedMessage::FromScript(ev), - }, - Ok(ev) => event = MixedMessage::FromConstellation(ev), + match self.receivers.try_recv(&self.task_queue) { + Some(new_event) => event = new_event, + None => break, } } @@ -1875,8 +1547,7 @@ impl ScriptThread { for msg in sequential { debug!("Processing event {:?}.", msg); let category = self.categorize_msg(&msg); - let pipeline_id = self.message_to_pipeline(&msg); - + let pipeline_id = msg.pipeline_id(); let _realm = pipeline_id.and_then(|id| { let global = self.documents.borrow().find_global(id); global.map(|global| enter_realm(&*global)) @@ -1980,112 +1651,6 @@ impl ScriptThread { } } - fn notify_activity_to_hang_monitor(&self, category: &ScriptThreadEventCategory) { - let hang_annotation = match category { - ScriptThreadEventCategory::AttachLayout => ScriptHangAnnotation::AttachLayout, - ScriptThreadEventCategory::ConstellationMsg => ScriptHangAnnotation::ConstellationMsg, - ScriptThreadEventCategory::DevtoolsMsg => ScriptHangAnnotation::DevtoolsMsg, - ScriptThreadEventCategory::DocumentEvent => ScriptHangAnnotation::DocumentEvent, - ScriptThreadEventCategory::DomEvent => ScriptHangAnnotation::DomEvent, - ScriptThreadEventCategory::FileRead => ScriptHangAnnotation::FileRead, - ScriptThreadEventCategory::FormPlannedNavigation => { - ScriptHangAnnotation::FormPlannedNavigation - }, - ScriptThreadEventCategory::HistoryEvent => ScriptHangAnnotation::HistoryEvent, - ScriptThreadEventCategory::ImageCacheMsg => ScriptHangAnnotation::ImageCacheMsg, - ScriptThreadEventCategory::InputEvent => ScriptHangAnnotation::InputEvent, - ScriptThreadEventCategory::NetworkEvent => ScriptHangAnnotation::NetworkEvent, - ScriptThreadEventCategory::Resize => ScriptHangAnnotation::Resize, - ScriptThreadEventCategory::ScriptEvent => ScriptHangAnnotation::ScriptEvent, - ScriptThreadEventCategory::SetScrollState => ScriptHangAnnotation::SetScrollState, - ScriptThreadEventCategory::SetViewport => ScriptHangAnnotation::SetViewport, - ScriptThreadEventCategory::StylesheetLoad => ScriptHangAnnotation::StylesheetLoad, - ScriptThreadEventCategory::TimerEvent => ScriptHangAnnotation::TimerEvent, - ScriptThreadEventCategory::UpdateReplacedElement => { - ScriptHangAnnotation::UpdateReplacedElement - }, - ScriptThreadEventCategory::WebSocketEvent => ScriptHangAnnotation::WebSocketEvent, - ScriptThreadEventCategory::WorkerEvent => ScriptHangAnnotation::WorkerEvent, - ScriptThreadEventCategory::WorkletEvent => ScriptHangAnnotation::WorkletEvent, - ScriptThreadEventCategory::ServiceWorkerEvent => { - ScriptHangAnnotation::ServiceWorkerEvent - }, - ScriptThreadEventCategory::EnterFullscreen => ScriptHangAnnotation::EnterFullscreen, - ScriptThreadEventCategory::ExitFullscreen => ScriptHangAnnotation::ExitFullscreen, - ScriptThreadEventCategory::PerformanceTimelineTask => { - ScriptHangAnnotation::PerformanceTimelineTask - }, - ScriptThreadEventCategory::PortMessage => ScriptHangAnnotation::PortMessage, - #[cfg(feature = "webgpu")] - ScriptThreadEventCategory::WebGPUMsg => ScriptHangAnnotation::WebGPUMsg, - }; - self.background_hang_monitor - .notify_activity(HangAnnotation::Script(hang_annotation)); - } - - fn message_to_pipeline(&self, msg: &MixedMessage) -> Option<PipelineId> { - use script_traits::ConstellationControlMsg::*; - match *msg { - MixedMessage::FromConstellation(ref inner_msg) => match *inner_msg { - StopDelayingLoadEventsMode(id) => Some(id), - NavigationResponse(id, _) => Some(id), - AttachLayout(ref new_layout_info) => new_layout_info - .parent_info - .or(Some(new_layout_info.new_pipeline_id)), - Resize(id, ..) => Some(id), - ThemeChange(id, ..) => Some(id), - ResizeInactive(id, ..) => Some(id), - UnloadDocument(id) => Some(id), - ExitPipeline(id, ..) => Some(id), - ExitScriptThread => None, - SendEvent(id, ..) => Some(id), - Viewport(id, ..) => Some(id), - GetTitle(id) => Some(id), - SetDocumentActivity(id, ..) => Some(id), - SetThrottled(id, ..) => Some(id), - SetThrottledInContainingIframe(id, ..) => Some(id), - NavigateIframe(id, ..) => Some(id), - PostMessage { target: id, .. } => Some(id), - UpdatePipelineId(_, _, _, id, _) => Some(id), - UpdateHistoryState(id, ..) => Some(id), - RemoveHistoryStates(id, ..) => Some(id), - FocusIFrame(id, ..) => Some(id), - WebDriverScriptCommand(id, ..) => Some(id), - TickAllAnimations(id, ..) => Some(id), - WebFontLoaded(id, ..) => Some(id), - DispatchIFrameLoadEvent { - target: _, - parent: id, - child: _, - } => Some(id), - DispatchStorageEvent(id, ..) => Some(id), - ReportCSSError(id, ..) => Some(id), - Reload(id, ..) => Some(id), - PaintMetric(id, ..) => Some(id), - ExitFullScreen(id, ..) => Some(id), - MediaSessionAction(..) => None, - #[cfg(feature = "webgpu")] - SetWebGPUPort(..) => None, - SetScrollStates(id, ..) => Some(id), - SetEpochPaintTime(id, ..) => Some(id), - }, - MixedMessage::FromScript(ref inner_msg) => match *inner_msg { - MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, _, pipeline_id, _)) => { - pipeline_id - }, - MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(_)) => None, - MainThreadScriptMsg::WorkletLoaded(pipeline_id) => Some(pipeline_id), - MainThreadScriptMsg::RegisterPaintWorklet { pipeline_id, .. } => Some(pipeline_id), - MainThreadScriptMsg::Inactive => None, - MainThreadScriptMsg::WakeUp => None, - }, - MixedMessage::FromImageCache((pipeline_id, _)) => Some(pipeline_id), - MixedMessage::FromDevtools(_) | MixedMessage::TimerFired => None, - #[cfg(feature = "webgpu")] - MixedMessage::FromWebGPUServer(..) => None, - } - } - fn profile_event<F, R>( &self, category: ScriptThreadEventCategory, @@ -2095,130 +1660,16 @@ impl ScriptThread { where F: FnOnce() -> R, { - self.notify_activity_to_hang_monitor(&category); + self.background_hang_monitor + .notify_activity(HangAnnotation::Script(category.into())); let start = Instant::now(); let value = if self.profile_script_events { - let profiler_chan = self.time_profiler_chan.clone(); - match category { - ScriptThreadEventCategory::AttachLayout => { - time_profile!(ProfilerCategory::ScriptAttachLayout, None, profiler_chan, f) - }, - ScriptThreadEventCategory::ConstellationMsg => time_profile!( - ProfilerCategory::ScriptConstellationMsg, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::DevtoolsMsg => { - time_profile!(ProfilerCategory::ScriptDevtoolsMsg, None, profiler_chan, f) - }, - ScriptThreadEventCategory::DocumentEvent => time_profile!( - ProfilerCategory::ScriptDocumentEvent, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::DomEvent => { - time_profile!(ProfilerCategory::ScriptDomEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::FileRead => { - time_profile!(ProfilerCategory::ScriptFileRead, None, profiler_chan, f) - }, - ScriptThreadEventCategory::FormPlannedNavigation => time_profile!( - ProfilerCategory::ScriptPlannedNavigation, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::HistoryEvent => { - time_profile!(ProfilerCategory::ScriptHistoryEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::ImageCacheMsg => time_profile!( - ProfilerCategory::ScriptImageCacheMsg, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::InputEvent => { - time_profile!(ProfilerCategory::ScriptInputEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::NetworkEvent => { - time_profile!(ProfilerCategory::ScriptNetworkEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::PortMessage => { - time_profile!(ProfilerCategory::ScriptPortMessage, None, profiler_chan, f) - }, - ScriptThreadEventCategory::Resize => { - time_profile!(ProfilerCategory::ScriptResize, None, profiler_chan, f) - }, - ScriptThreadEventCategory::ScriptEvent => { - time_profile!(ProfilerCategory::ScriptEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::SetScrollState => time_profile!( - ProfilerCategory::ScriptSetScrollState, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::UpdateReplacedElement => time_profile!( - ProfilerCategory::ScriptUpdateReplacedElement, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::StylesheetLoad => time_profile!( - ProfilerCategory::ScriptStylesheetLoad, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::SetViewport => { - time_profile!(ProfilerCategory::ScriptSetViewport, None, profiler_chan, f) - }, - ScriptThreadEventCategory::TimerEvent => { - time_profile!(ProfilerCategory::ScriptTimerEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::WebSocketEvent => time_profile!( - ProfilerCategory::ScriptWebSocketEvent, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::WorkerEvent => { - time_profile!(ProfilerCategory::ScriptWorkerEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::WorkletEvent => { - time_profile!(ProfilerCategory::ScriptWorkletEvent, None, profiler_chan, f) - }, - ScriptThreadEventCategory::ServiceWorkerEvent => time_profile!( - ProfilerCategory::ScriptServiceWorkerEvent, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::EnterFullscreen => time_profile!( - ProfilerCategory::ScriptEnterFullscreen, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::ExitFullscreen => time_profile!( - ProfilerCategory::ScriptExitFullscreen, - None, - profiler_chan, - f - ), - ScriptThreadEventCategory::PerformanceTimelineTask => time_profile!( - ProfilerCategory::ScriptPerformanceEvent, - None, - profiler_chan, - f - ), - #[cfg(feature = "webgpu")] - ScriptThreadEventCategory::WebGPUMsg => { - time_profile!(ProfilerCategory::ScriptWebGPUMsg, None, profiler_chan, f) - }, - } + time_profile!( + category.into(), + None, + self.senders.time_profiler_sender.clone(), + f + ) } else { f() }; @@ -2371,12 +1822,8 @@ impl ScriptThread { }, #[cfg(feature = "webgpu")] ConstellationControlMsg::SetWebGPUPort(port) => { - if self.webgpu_port.borrow().is_some() { - warn!("WebGPU port already exists for this content process"); - } else { - let p = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(port); - *self.webgpu_port.borrow_mut() = Some(p); - } + *self.receivers.webgpu_receiver.borrow_mut() = + ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(port); }, msg @ ConstellationControlMsg::AttachLayout(..) | msg @ ConstellationControlMsg::Viewport(..) | @@ -2470,7 +1917,9 @@ impl ScriptThread { WebGPUMsg::FreeTextureView(id) => self.gpu_id_hub.free_texture_view_id(id), WebGPUMsg::FreeComputePass(id) => self.gpu_id_hub.free_compute_pass_id(id), WebGPUMsg::FreeRenderPass(id) => self.gpu_id_hub.free_render_pass_id(id), - WebGPUMsg::Exit => *self.webgpu_port.borrow_mut() = None, + WebGPUMsg::Exit => { + *self.receivers.webgpu_receiver.borrow_mut() = crossbeam_channel::never() + }, WebGPUMsg::DeviceLost { pipeline_id, device, @@ -2961,7 +2410,8 @@ impl ScriptThread { fn handle_set_throttled_msg(&self, id: PipelineId, throttled: bool) { // Separate message sent since parent script thread could be different (Iframe of different // domain) - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((id, ScriptMsg::SetThrottledComplete(throttled))) .unwrap(); @@ -3194,7 +2644,8 @@ impl ScriptThread { window_proxy.stop_delaying_load_events_mode(); } } - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((*id, ScriptMsg::AbortLoadUrl)) .unwrap(); return None; @@ -3210,70 +2661,6 @@ impl ScriptThread { } } - pub fn dom_manipulation_task_source( - &self, - pipeline_id: PipelineId, - ) -> DOMManipulationTaskSource { - DOMManipulationTaskSource(self.dom_manipulation_task_sender.clone(), pipeline_id) - } - - pub fn gamepad_task_source(&self, pipeline_id: PipelineId) -> GamepadTaskSource { - GamepadTaskSource(self.gamepad_task_sender.clone(), pipeline_id) - } - - pub fn media_element_task_source(&self, pipeline_id: PipelineId) -> MediaElementTaskSource { - MediaElementTaskSource(self.media_element_task_sender.clone(), pipeline_id) - } - - pub fn performance_timeline_task_source( - &self, - pipeline_id: PipelineId, - ) -> PerformanceTimelineTaskSource { - PerformanceTimelineTaskSource(self.performance_timeline_task_sender.clone(), pipeline_id) - } - - pub fn history_traversal_task_source( - &self, - pipeline_id: PipelineId, - ) -> HistoryTraversalTaskSource { - HistoryTraversalTaskSource(self.history_traversal_task_sender.clone(), pipeline_id) - } - - pub fn user_interaction_task_source( - &self, - pipeline_id: PipelineId, - ) -> UserInteractionTaskSource { - UserInteractionTaskSource(self.user_interaction_task_sender.clone(), pipeline_id) - } - - pub fn networking_task_source(&self, pipeline_id: PipelineId) -> NetworkingTaskSource { - NetworkingTaskSource(self.networking_task_sender.clone(), pipeline_id) - } - - pub fn port_message_queue(&self, pipeline_id: PipelineId) -> PortMessageQueue { - PortMessageQueue(self.port_message_sender.clone(), pipeline_id) - } - - pub fn file_reading_task_source(&self, pipeline_id: PipelineId) -> FileReadingTaskSource { - FileReadingTaskSource(self.file_reading_task_sender.clone(), pipeline_id) - } - - pub fn remote_event_task_source(&self, pipeline_id: PipelineId) -> RemoteEventTaskSource { - RemoteEventTaskSource(self.remote_event_task_sender.clone(), pipeline_id) - } - - fn rendering_task_source(&self, pipeline_id: PipelineId) -> RenderingTaskSource { - RenderingTaskSource(self.rendering_task_sender.clone(), pipeline_id) - } - - pub fn timer_task_source(&self, pipeline_id: PipelineId) -> TimerTaskSource { - TimerTaskSource(self.timer_task_sender.clone(), pipeline_id) - } - - pub fn websocket_task_source(&self, pipeline_id: PipelineId) -> WebsocketTaskSource { - WebsocketTaskSource(self.remote_event_task_sender.clone(), pipeline_id) - } - /// Handles a request for the window title. fn handle_get_title_msg(&self, pipeline_id: PipelineId) { let document = match self.documents.borrow().find_document(pipeline_id) { @@ -3313,7 +2700,8 @@ impl ScriptThread { document.window().layout_mut().exit_now(); debug!("{id}: Sending PipelineExited message to constellation"); - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((id, ScriptMsg::PipelineExited)) .ok(); @@ -3454,7 +2842,8 @@ impl ScriptThread { ) -> Option<(BrowsingContextId, Option<PipelineId>)> { let (result_sender, result_receiver) = ipc::channel().unwrap(); let msg = ScriptMsg::GetBrowsingContextInfo(pipeline_id, result_sender); - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((pipeline_id, msg)) .expect("Failed to send to constellation."); result_receiver @@ -3469,7 +2858,8 @@ impl ScriptThread { ) -> Option<TopLevelBrowsingContextId> { let (result_sender, result_receiver) = ipc::channel().unwrap(); let msg = ScriptMsg::GetTopForBrowsingContext(browsing_context_id, result_sender); - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((sender_pipeline, msg)) .expect("Failed to send to constellation."); result_receiver @@ -3593,7 +2983,8 @@ impl ScriptThread { ) -> DomRoot<ServoParser> { let final_url = metadata.final_url.clone(); { - self.script_sender + self.senders + .pipeline_to_constellation_sender .send(( incomplete.pipeline_id, ScriptMsg::SetFinalUrl(final_url.clone()), @@ -3605,8 +2996,6 @@ impl ScriptThread { incomplete.url, incomplete.pipeline_id ); - let MainThreadScriptChan(ref sender) = self.chan; - let origin = if final_url.as_str() == "about:blank" || final_url.as_str() == "about:srcdoc" { incomplete.origin.clone() @@ -3615,32 +3004,19 @@ impl ScriptThread { }; let script_to_constellation_chan = ScriptToConstellationChan { - sender: self.script_sender.clone(), + sender: self.senders.pipeline_to_constellation_sender.clone(), pipeline_id: incomplete.pipeline_id, }; let task_manager = TaskManager::new( - self.dom_manipulation_task_source(incomplete.pipeline_id), - self.file_reading_task_source(incomplete.pipeline_id), - self.gamepad_task_source(incomplete.pipeline_id), - self.history_traversal_task_source(incomplete.pipeline_id), - self.media_element_task_source(incomplete.pipeline_id), - self.networking_task_source(incomplete.pipeline_id), - self.performance_timeline_task_source(incomplete.pipeline_id) - .clone(), - self.port_message_queue(incomplete.pipeline_id), - self.user_interaction_task_source(incomplete.pipeline_id), - self.remote_event_task_source(incomplete.pipeline_id), - self.rendering_task_source(incomplete.pipeline_id), - self.timer_task_source(incomplete.pipeline_id), - self.websocket_task_source(incomplete.pipeline_id), + Box::new(self.senders.self_sender.clone()), + incomplete.pipeline_id, ); - let paint_time_metrics = PaintTimeMetrics::new( incomplete.pipeline_id, - self.time_profiler_chan.clone(), - self.layout_to_constellation_chan.clone(), - self.control_chan.clone(), + self.senders.time_profiler_sender.clone(), + self.senders.layout_to_constellation_ipc_sender.clone(), + self.senders.constellation_sender.clone(), final_url.clone(), incomplete.navigation_start, ); @@ -3649,12 +3025,12 @@ impl ScriptThread { id: incomplete.pipeline_id, url: final_url.clone(), is_iframe: incomplete.parent_info.is_some(), - constellation_chan: self.layout_to_constellation_chan.clone(), - script_chan: self.control_chan.clone(), + constellation_chan: self.senders.layout_to_constellation_ipc_sender.clone(), + script_chan: self.senders.constellation_sender.clone(), image_cache: self.image_cache.clone(), system_font_service: self.system_font_service.clone(), resource_threads: self.resource_threads.clone(), - time_profiler_chan: self.time_profiler_chan.clone(), + time_profiler_chan: self.senders.time_profiler_sender.clone(), compositor_api: self.compositor_api.clone(), paint_time_metrics, window_size: incomplete.window_size, @@ -3663,18 +3039,18 @@ impl ScriptThread { // Create the window and document objects. let window = Window::new( self.js_runtime.clone(), - MainThreadScriptChan(sender.clone()), + self.senders.self_sender.clone(), task_manager, self.layout_factory.create(layout_config), - self.image_cache_channel.clone(), + self.senders.image_cache_sender.clone(), self.image_cache.clone(), self.resource_threads.clone(), - self.bluetooth_thread.clone(), - self.mem_profiler_chan.clone(), - self.time_profiler_chan.clone(), - self.devtools_chan.clone(), + self.senders.bluetooth_sender.clone(), + self.senders.memory_profiler_sender.clone(), + self.senders.time_profiler_sender.clone(), + self.senders.devtools_server_sender.clone(), script_to_constellation_chan, - self.control_chan.clone(), + self.senders.constellation_sender.clone(), incomplete.pipeline_id, incomplete.parent_info, incomplete.window_size, @@ -3807,7 +3183,8 @@ impl ScriptThread { ); } - self.script_sender + self.senders + .pipeline_to_constellation_sender .send((incomplete.pipeline_id, ScriptMsg::ActivateDocument)) .unwrap(); @@ -3848,14 +3225,14 @@ impl ScriptThread { url: ServoUrl, (bc, p, w): (BrowsingContextId, PipelineId, Option<WorkerId>), ) { - if let Some(ref chan) = self.devtools_chan { + if let Some(ref chan) = self.senders.devtools_server_sender { let page_info = DevtoolsPageInfo { title: String::from(title), url, }; chan.send(ScriptToDevtoolsControlMsg::NewGlobal( (bc, p, w), - self.devtools_sender.clone(), + self.senders.devtools_client_to_script_thread_sender.clone(), page_info.clone(), )) .unwrap(); @@ -4026,7 +3403,8 @@ impl ScriptThread { let cancel_chan = incomplete.canceller.initialize(); - self.script_sender + self.senders + .pipeline_to_constellation_sender .send(( id, ScriptMsg::InitiateNavigateRequest(req_init, cancel_chan), @@ -4153,7 +3531,7 @@ impl ScriptThread { column: u32, msg: String, ) { - let sender = match self.devtools_chan { + let sender = match self.senders.devtools_server_sender { Some(ref sender) => sender, None => return, }; diff --git a/components/script/task_manager.rs b/components/script/task_manager.rs index 6867e59fc0a..08d018f1066 100644 --- a/components/script/task_manager.rs +++ b/components/script/task_manager.rs @@ -6,7 +6,10 @@ use std::collections::HashMap; use std::sync::atomic::AtomicBool; use std::sync::Arc; +use base::id::PipelineId; + use crate::dom::bindings::cell::DomRefCell; +use crate::messaging::MainThreadScriptChan; use crate::task::TaskCanceller; use crate::task_source::dom_manipulation::DOMManipulationTaskSource; use crate::task_source::file_reading::FileReadingTaskSource; @@ -24,15 +27,20 @@ use crate::task_source::websocket::WebsocketTaskSource; use crate::task_source::TaskSourceName; macro_rules! task_source_functions { - ($self:ident,$with_canceller:ident,$task_source:ident,$task_source_type:ident,$task_source_name:ident) => { - pub fn $with_canceller(&$self) -> ($task_source_type, TaskCanceller) { + ($self:ident, $task_source:ident, $task_source_type:ident, $task_source_name:ident) => { + pub(crate) fn $task_source(&$self) -> $task_source_type { + $self.$task_source.clone() + } + }; + ($self:ident, $with_canceller:ident, $task_source:ident, $task_source_type:ident, $task_source_name:ident) => { + pub(crate) fn $with_canceller(&$self) -> ($task_source_type, TaskCanceller) { ($self.$task_source.clone(), $self.task_canceller(TaskSourceName::$task_source_name)) } - pub fn $task_source(&$self) -> $task_source_type { + pub(crate) fn $task_source(&$self) -> $task_source_type { $self.$task_source.clone() } - } + }; } #[derive(JSTraceable, MallocSizeOf)] @@ -69,35 +77,27 @@ pub struct TaskManager { impl TaskManager { #[allow(clippy::too_many_arguments)] - pub fn new( - dom_manipulation_task_source: DOMManipulationTaskSource, - file_reading_task_source: FileReadingTaskSource, - gamepad_task_source: GamepadTaskSource, - history_traversal_task_source: HistoryTraversalTaskSource, - media_element_task_source: MediaElementTaskSource, - networking_task_source: NetworkingTaskSource, - performance_timeline_task_source: PerformanceTimelineTaskSource, - port_message_queue: PortMessageQueue, - user_interaction_task_source: UserInteractionTaskSource, - remote_event_task_source: RemoteEventTaskSource, - rendering_task_source: RenderingTaskSource, - timer_task_source: TimerTaskSource, - websocket_task_source: WebsocketTaskSource, - ) -> Self { + pub(crate) fn new(sender: Box<MainThreadScriptChan>, pipeline_id: PipelineId) -> Self { TaskManager { - dom_manipulation_task_source, - file_reading_task_source, - gamepad_task_source, - history_traversal_task_source, - media_element_task_source, - networking_task_source, - performance_timeline_task_source, - port_message_queue, - user_interaction_task_source, - remote_event_task_source, - rendering_task_source, - timer_task_source, - websocket_task_source, + dom_manipulation_task_source: DOMManipulationTaskSource(sender.clone(), pipeline_id), + file_reading_task_source: FileReadingTaskSource(sender.clone(), pipeline_id), + gamepad_task_source: GamepadTaskSource(sender.clone(), pipeline_id), + history_traversal_task_source: HistoryTraversalTaskSource( + sender.0.clone(), + pipeline_id, + ), + media_element_task_source: MediaElementTaskSource(sender.0.clone(), pipeline_id), + networking_task_source: NetworkingTaskSource(sender.clone(), pipeline_id), + performance_timeline_task_source: PerformanceTimelineTaskSource( + sender.clone(), + pipeline_id, + ), + port_message_queue: PortMessageQueue(sender.clone(), pipeline_id), + user_interaction_task_source: UserInteractionTaskSource(sender.0.clone(), pipeline_id), + remote_event_task_source: RemoteEventTaskSource(sender.clone(), pipeline_id), + rendering_task_source: RenderingTaskSource(sender.clone(), pipeline_id), + timer_task_source: TimerTaskSource(sender.clone(), pipeline_id), + websocket_task_source: WebsocketTaskSource(sender.clone(), pipeline_id), task_cancellers: Default::default(), } } @@ -110,13 +110,7 @@ impl TaskManager { DOMManipulation ); - task_source_functions!( - self, - gamepad_task_source_with_canceller, - gamepad_task_source, - GamepadTaskSource, - Gamepad - ); + task_source_functions!(self, gamepad_task_source, GamepadTaskSource, Gamepad); task_source_functions!( self, @@ -128,7 +122,6 @@ impl TaskManager { task_source_functions!( self, - user_interaction_task_source_with_canceller, user_interaction_task_source, UserInteractionTaskSource, UserInteraction @@ -144,7 +137,6 @@ impl TaskManager { task_source_functions!( self, - file_reading_task_source_with_canceller, file_reading_task_source, FileReadingTaskSource, FileReading @@ -152,59 +144,25 @@ impl TaskManager { task_source_functions!( self, - history_traversal_task_source_with_canceller, - history_traversal_task_source, - HistoryTraversalTaskSource, - HistoryTraversal - ); - - task_source_functions!( - self, - performance_timeline_task_source_with_canceller, performance_timeline_task_source, PerformanceTimelineTaskSource, PerformanceTimeline ); - task_source_functions!( - self, - port_message_queue_with_canceller, - port_message_queue, - PortMessageQueue, - PortMessage - ); + task_source_functions!(self, port_message_queue, PortMessageQueue, PortMessage); task_source_functions!( self, - remote_event_task_source_with_canceller, remote_event_task_source, RemoteEventTaskSource, RemoteEvent ); - task_source_functions!( - self, - rendering_task_source_with_canceller, - rendering_task_source, - RenderingTaskSource, - Rendering - ); + task_source_functions!(self, rendering_task_source, RenderingTaskSource, Rendering); - task_source_functions!( - self, - timer_task_source_with_canceller, - timer_task_source, - TimerTaskSource, - Timer - ); + task_source_functions!(self, timer_task_source, TimerTaskSource, Timer); - task_source_functions!( - self, - websocket_task_source_with_canceller, - websocket_task_source, - WebsocketTaskSource, - Websocket - ); + task_source_functions!(self, websocket_task_source, WebsocketTaskSource, Websocket); pub fn task_canceller(&self, name: TaskSourceName) -> TaskCanceller { let mut flags = self.task_cancellers.borrow_mut(); diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index 1469db66155..c7800c76239 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -22,7 +22,7 @@ pub struct DOMManipulationTaskSource(pub Box<dyn ScriptChan + Send>, #[no_trace] impl Clone for DOMManipulationTaskSource { fn clone(&self) -> DOMManipulationTaskSource { - DOMManipulationTaskSource(self.0.clone(), self.1) + DOMManipulationTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index a7ff92e1c85..1f46a41007a 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -18,7 +18,7 @@ pub struct FileReadingTaskSource( impl Clone for FileReadingTaskSource { fn clone(&self) -> FileReadingTaskSource { - FileReadingTaskSource(self.0.clone(), self.1) + FileReadingTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/gamepad.rs b/components/script/task_source/gamepad.rs index 9d38257bace..c0ce2736d6a 100644 --- a/components/script/task_source/gamepad.rs +++ b/components/script/task_source/gamepad.rs @@ -19,7 +19,7 @@ pub struct GamepadTaskSource( impl Clone for GamepadTaskSource { fn clone(&self) -> GamepadTaskSource { - GamepadTaskSource(self.0.clone(), self.1) + GamepadTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/history_traversal.rs b/components/script/task_source/history_traversal.rs index 4bb90a1ffcb..9eb2daa4dfd 100644 --- a/components/script/task_source/history_traversal.rs +++ b/components/script/task_source/history_traversal.rs @@ -5,13 +5,13 @@ use base::id::PipelineId; use crossbeam_channel::Sender; +use crate::messaging::MainThreadScriptMsg; use crate::script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use crate::script_thread::MainThreadScriptMsg; use crate::task::{TaskCanceller, TaskOnce}; use crate::task_source::{TaskSource, TaskSourceName}; #[derive(Clone, JSTraceable)] -pub struct HistoryTraversalTaskSource( +pub(crate) struct HistoryTraversalTaskSource( #[no_trace] pub Sender<MainThreadScriptMsg>, #[no_trace] pub PipelineId, ); diff --git a/components/script/task_source/media_element.rs b/components/script/task_source/media_element.rs index 944ffc4f5bf..f1dfc7f88e7 100644 --- a/components/script/task_source/media_element.rs +++ b/components/script/task_source/media_element.rs @@ -14,13 +14,13 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::event::SimpleEventTask; use crate::dom::eventtarget::EventTarget; use crate::dom::window::Window; +use crate::messaging::MainThreadScriptMsg; use crate::script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use crate::script_thread::MainThreadScriptMsg; use crate::task::{TaskCanceller, TaskOnce}; use crate::task_source::{TaskSource, TaskSourceName}; #[derive(Clone, JSTraceable)] -pub struct MediaElementTaskSource( +pub(crate) struct MediaElementTaskSource( #[no_trace] pub Sender<MainThreadScriptMsg>, #[no_trace] pub PipelineId, ); diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs index f142c1f6ae0..1e5f35a1153 100644 --- a/components/script/task_source/networking.rs +++ b/components/script/task_source/networking.rs @@ -16,7 +16,7 @@ pub struct NetworkingTaskSource( impl Clone for NetworkingTaskSource { fn clone(&self) -> NetworkingTaskSource { - NetworkingTaskSource(self.0.clone(), self.1) + NetworkingTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs index 9bcfe4bc1d8..d18ceacf663 100644 --- a/components/script/task_source/performance_timeline.rs +++ b/components/script/task_source/performance_timeline.rs @@ -25,7 +25,7 @@ pub struct PerformanceTimelineTaskSource( impl Clone for PerformanceTimelineTaskSource { fn clone(&self) -> PerformanceTimelineTaskSource { - PerformanceTimelineTaskSource(self.0.clone(), self.1) + PerformanceTimelineTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/port_message.rs b/components/script/task_source/port_message.rs index 0ca613c647c..ebc06489ca1 100644 --- a/components/script/task_source/port_message.rs +++ b/components/script/task_source/port_message.rs @@ -18,7 +18,7 @@ pub struct PortMessageQueue( impl Clone for PortMessageQueue { fn clone(&self) -> PortMessageQueue { - PortMessageQueue(self.0.clone(), self.1) + PortMessageQueue(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/remote_event.rs b/components/script/task_source/remote_event.rs index 9a70d2a0234..12dbc5321a8 100644 --- a/components/script/task_source/remote_event.rs +++ b/components/script/task_source/remote_event.rs @@ -16,7 +16,7 @@ pub struct RemoteEventTaskSource( impl Clone for RemoteEventTaskSource { fn clone(&self) -> RemoteEventTaskSource { - RemoteEventTaskSource(self.0.clone(), self.1) + RemoteEventTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/rendering.rs b/components/script/task_source/rendering.rs index 0c652add2bb..d6d0b2a5018 100644 --- a/components/script/task_source/rendering.rs +++ b/components/script/task_source/rendering.rs @@ -16,7 +16,7 @@ pub struct RenderingTaskSource(pub Box<dyn ScriptChan + Send>, #[no_trace] pub P impl Clone for RenderingTaskSource { fn clone(&self) -> RenderingTaskSource { - RenderingTaskSource(self.0.clone(), self.1) + RenderingTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/timer.rs b/components/script/task_source/timer.rs index 4f8ad10d811..1c274231693 100644 --- a/components/script/task_source/timer.rs +++ b/components/script/task_source/timer.rs @@ -19,7 +19,7 @@ pub struct TimerTaskSource( impl Clone for TimerTaskSource { fn clone(&self) -> TimerTaskSource { - TimerTaskSource(self.0.clone(), self.1) + TimerTaskSource(self.0.as_boxed(), self.1) } } diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 9ddc06d9185..19ed025fc9a 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -14,8 +14,8 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::event::{EventBubbles, EventCancelable, EventTask}; use crate::dom::eventtarget::EventTarget; use crate::dom::window::Window; +use crate::messaging::MainThreadScriptMsg; use crate::script_runtime::{CommonScriptMsg, ScriptThreadEventCategory}; -use crate::script_thread::MainThreadScriptMsg; use crate::task::{TaskCanceller, TaskOnce}; use crate::task_source::{TaskSource, TaskSourceName}; diff --git a/components/script/task_source/websocket.rs b/components/script/task_source/websocket.rs index 2d05067e28b..2ae11f99eb8 100644 --- a/components/script/task_source/websocket.rs +++ b/components/script/task_source/websocket.rs @@ -16,7 +16,7 @@ pub struct WebsocketTaskSource( impl Clone for WebsocketTaskSource { fn clone(&self) -> WebsocketTaskSource { - WebsocketTaskSource(self.0.clone(), self.1) + WebsocketTaskSource(self.0.as_boxed(), self.1) } } |