diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index d1b7ba9c44a..68efd51b485 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -147,6 +147,13 @@ impl WorkletMethods for Worklet { } } +impl Drop for Worklet { + fn drop(&mut self) { + let script_thread = ScriptThread::worklet_thread_pool(); + script_thread.exit_worklet(self.worklet_id); + } +} + /// A guid for worklets. #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)] pub struct WorkletId(Uuid); @@ -301,10 +308,14 @@ impl WorkletThreadPool { promise: TrustedPromise::new(promise.clone()), }); } - // If any of the threads are blocked waiting on data, wake them up. - let _ = self.cold_backup_sender.send(WorkletData::WakeUp); - let _ = self.hot_backup_sender.send(WorkletData::WakeUp); - let _ = self.primary_sender.send(WorkletData::WakeUp); + self.wake_threads(); + } + + pub(crate) fn exit_worklet(&self, worklet_id: WorkletId) { + for sender in &[&self.control_sender_0, &self.control_sender_1, &self.control_sender_2] { + let _ = sender.send(WorkletControl::ExitWorklet(worklet_id)); + } + self.wake_threads(); } /// For testing. @@ -314,6 +325,13 @@ impl WorkletThreadPool { let _ = self.primary_sender.send(msg); receiver.recv().expect("Test worklet has died?") } + + fn wake_threads(&self) { + // If any of the threads are blocked waiting on data, wake them up. + let _ = self.cold_backup_sender.send(WorkletData::WakeUp); + let _ = self.hot_backup_sender.send(WorkletData::WakeUp); + let _ = self.primary_sender.send(WorkletData::WakeUp); + } } /// The data messages sent to worklet threads @@ -327,6 +345,7 @@ enum WorkletData { /// The control message sent to worklet threads enum WorkletControl { + ExitWorklet(WorkletId), FetchAndInvokeAWorkletScript { pipeline_id: PipelineId, worklet_id: WorkletId, @@ -621,6 +640,9 @@ impl WorkletThread { /// Process a control message. fn process_control(&mut self, control: WorkletControl) { match control { + WorkletControl::ExitWorklet(worklet_id) => { + self.global_scopes.remove(&worklet_id); + }, WorkletControl::FetchAndInvokeAWorkletScript { pipeline_id, worklet_id, global_type, origin, base_url, script_url, credentials, pending_tasks_struct, promise,