aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-12-26 04:34:54 +0100
committerGitHub <noreply@github.com>2024-12-26 03:34:54 +0000
commit5f927a2c285c779b631ba36520904189ebd5cd4c (patch)
treefd9326f2f730fad0ced85c9f8765aa866fba95e5 /components/script
parent1e95712772284e434ab8f4c028d6cf78d2f63e1c (diff)
downloadservo-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')
-rw-r--r--components/script/dom/abstractworkerglobalscope.rs4
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs2
-rw-r--r--components/script/dom/document.rs3
-rw-r--r--components/script/dom/globalscope.rs7
-rw-r--r--components/script/dom/paintworkletglobalscope.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs2
-rw-r--r--components/script/dom/testworkletglobalscope.rs2
-rw-r--r--components/script/dom/window.rs12
-rw-r--r--components/script/dom/worklet.rs5
-rw-r--r--components/script/dom/workletglobalscope.rs8
-rw-r--r--components/script/lib.rs3
-rw-r--r--components/script/messaging.rs398
-rw-r--r--components/script/script_runtime.rs92
-rw-r--r--components/script/script_thread.rs912
-rw-r--r--components/script/task_manager.rs116
-rw-r--r--components/script/task_source/dom_manipulation.rs2
-rw-r--r--components/script/task_source/file_reading.rs2
-rw-r--r--components/script/task_source/gamepad.rs2
-rw-r--r--components/script/task_source/history_traversal.rs4
-rw-r--r--components/script/task_source/media_element.rs4
-rw-r--r--components/script/task_source/networking.rs2
-rw-r--r--components/script/task_source/performance_timeline.rs2
-rw-r--r--components/script/task_source/port_message.rs2
-rw-r--r--components/script/task_source/remote_event.rs2
-rw-r--r--components/script/task_source/rendering.rs2
-rw-r--r--components/script/task_source/timer.rs2
-rw-r--r--components/script/task_source/user_interaction.rs2
-rw-r--r--components/script/task_source/websocket.rs2
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)
}
}