aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/worklet.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/worklet.rs')
-rw-r--r--components/script/dom/worklet.rs32
1 files changed, 22 insertions, 10 deletions
diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs
index e5e55b97453..bbcc777ab11 100644
--- a/components/script/dom/worklet.rs
+++ b/components/script/dom/worklet.rs
@@ -11,6 +11,7 @@
//! a backup thread, not on the primary worklet thread.
use app_units::Au;
+use canvas_traits::CanvasData;
use dom::bindings::codegen::Bindings::RequestBinding::RequestCredentials;
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::WorkletBinding::WorkletMethods;
@@ -38,6 +39,7 @@ use dom::workletglobalscope::WorkletGlobalScopeType;
use dom::workletglobalscope::WorkletTask;
use dom_struct::dom_struct;
use euclid::Size2D;
+use ipc_channel::ipc::IpcSender;
use js::jsapi::JSGCParamKey;
use js::jsapi::JSTracer;
use js::jsapi::JS_GC;
@@ -45,7 +47,6 @@ use js::jsapi::JS_GetGCParameter;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
use net_traits::IpcSend;
-use net_traits::image::base::Image;
use net_traits::load_whole_resource;
use net_traits::request::Destination;
use net_traits::request::RequestInit;
@@ -58,7 +59,6 @@ use script_runtime::new_rt_and_cx;
use script_thread::MainThreadScriptMsg;
use script_thread::Runnable;
use script_thread::ScriptThread;
-use script_traits::PaintWorkletError;
use script_traits::PaintWorkletExecutor;
use servo_atoms::Atom;
use servo_rand;
@@ -76,7 +76,6 @@ use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::thread;
-use std::time::Duration;
use style::thread_state;
use swapper::Swapper;
use swapper::swapper;
@@ -85,7 +84,6 @@ use uuid::Uuid;
// Magic numbers
const WORKLET_THREAD_POOL_SIZE: u32 = 3;
const MIN_GC_THRESHOLD: u32 = 1_000_000;
-const PAINT_TIMEOUT_MILLISECONDS: u64 = 10;
#[dom_struct]
/// https://drafts.css-houdini.org/worklets/#worklet
@@ -163,6 +161,7 @@ impl WorkletMethods for Worklet {
&promise);
// Step 5.
+ debug!("Returning promise.");
promise
}
}
@@ -234,6 +233,17 @@ impl PendingTasksStruct {
/// The thread pool lives in the script thread, and is initialized
/// when a worklet adds a module. It is dropped when the script thread
/// is dropped, and asks each of the worklet threads to quit.
+///
+/// The layout thread can end up blocking on the primary worklet thread
+/// (e.g. when invoking a paint callback), so it is important to avoid
+/// deadlock by making sure the primary worklet thread doesn't end up
+/// blocking waiting on layout. In particular, since the constellation
+/// can block waiting on layout, this means the primary worklet thread
+/// can't block waiting on the constellation. In general, the primary
+/// worklet thread shouldn't perform any blocking operations. If a worklet
+/// thread needs to do anything blocking, it should send a control
+/// message, to make sure that the blocking operation is performed
+/// by a backup thread, not by the primary thread.
#[derive(Clone, JSTraceable)]
pub struct WorkletThreadPool {
@@ -551,6 +561,7 @@ impl WorkletThread {
match self.global_scopes.entry(worklet_id) {
hash_map::Entry::Occupied(entry) => Root::from_ref(entry.get()),
hash_map::Entry::Vacant(entry) => {
+ debug!("Creating new worklet global scope.");
let result = global_type.new(&self.runtime, pipeline_id, base_url, &self.global_init);
entry.insert(JS::from_ref(&*result));
result
@@ -562,6 +573,7 @@ impl WorkletThread {
/// https://drafts.css-houdini.org/worklets/#fetch-and-invoke-a-worklet-script
fn fetch_and_invoke_a_worklet_script(&self,
global_scope: &WorkletGlobalScope,
+ pipeline_id: PipelineId,
origin: ImmutableOrigin,
script_url: ServoUrl,
credentials: RequestCredentials,
@@ -612,7 +624,9 @@ impl WorkletThread {
debug!("Finished adding script.");
let old_counter = pending_tasks_struct.decrement_counter_by(1);
if old_counter == 1 {
- // TODO: trigger a reflow?
+ debug!("Resolving promise.");
+ let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id);
+ self.script_sender.send(msg).expect("Worklet thread outlived script thread.");
self.run_in_script_thread(promise.resolve_runnable(()));
}
}
@@ -638,6 +652,7 @@ impl WorkletThread {
global_type,
base_url);
self.fetch_and_invoke_a_worklet_script(&*global,
+ pipeline_id,
origin,
script_url,
credentials,
@@ -678,13 +693,10 @@ impl PaintWorkletExecutor for WorkletExecutor {
/// https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image
fn draw_a_paint_image(&self,
name: Atom,
- concrete_object_size: Size2D<Au>)
- -> Result<Image, PaintWorkletError>
+ concrete_object_size: Size2D<Au>,
+ sender: IpcSender<CanvasData>)
{
- let (sender, receiver) = mpsc::channel();
let task = WorkletTask::Paint(PaintWorkletTask::DrawAPaintImage(name, concrete_object_size, sender));
- let timeout = Duration::from_millis(PAINT_TIMEOUT_MILLISECONDS);
self.schedule_a_worklet_task(task);
- receiver.recv_timeout(timeout)?
}
}