diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/abstractworkerglobalscope.rs | 21 | ||||
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 13 | ||||
-rw-r--r-- | components/script/dom/dedicatedworkerglobalscope.rs | 57 | ||||
-rw-r--r-- | components/script/dom/dissimilaroriginwindow.rs | 4 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 103 | ||||
-rw-r--r-- | components/script/dom/serviceworkerglobalscope.rs | 87 | ||||
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 367 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 8 | ||||
-rw-r--r-- | components/script/dom/webidls/WebGL2RenderingContext.webidl | 8 | ||||
-rw-r--r-- | components/script/dom/window.rs | 5 | ||||
-rw-r--r-- | components/script/dom/workerglobalscope.rs | 12 | ||||
-rw-r--r-- | components/script/dom/workletglobalscope.rs | 4 |
12 files changed, 539 insertions, 150 deletions
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs index e8e41375b70..d5186f91845 100644 --- a/components/script/dom/abstractworkerglobalscope.rs +++ b/components/script/dom/abstractworkerglobalscope.rs @@ -81,32 +81,27 @@ impl ScriptPort for Receiver<DedicatedWorkerScriptMsg> { } pub trait WorkerEventLoopMethods { - type TimerMsg: Send; type WorkerMsg: QueuedTaskConversion + Send; type Event; - fn timer_event_port(&self) -> &Receiver<Self::TimerMsg>; fn task_queue(&self) -> &TaskQueue<Self::WorkerMsg>; fn handle_event(&self, event: Self::Event); fn handle_worker_post_event(&self, worker: &TrustedWorkerAddress) -> Option<AutoWorkerReset>; fn from_worker_msg(&self, msg: Self::WorkerMsg) -> Self::Event; - fn from_timer_msg(&self, msg: Self::TimerMsg) -> Self::Event; fn from_devtools_msg(&self, msg: DevtoolScriptControlMsg) -> Self::Event; } // https://html.spec.whatwg.org/multipage/#worker-event-loop -pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>( +pub fn run_worker_event_loop<T, WorkerMsg, Event>( worker_scope: &T, worker: Option<&TrustedWorkerAddress>, ) where - TimerMsg: Send, WorkerMsg: QueuedTaskConversion + Send, - T: WorkerEventLoopMethods<TimerMsg = TimerMsg, WorkerMsg = WorkerMsg, Event = Event> + T: WorkerEventLoopMethods<WorkerMsg = WorkerMsg, Event = Event> + DerivedFrom<WorkerGlobalScope> + DerivedFrom<GlobalScope> + DomObject, { let scope = worker_scope.upcast::<WorkerGlobalScope>(); - let timer_event_port = worker_scope.timer_event_port(); let devtools_port = match scope.from_devtools_sender() { Some(_) => Some(scope.from_devtools_receiver()), None => None, @@ -117,7 +112,6 @@ pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>( task_queue.take_tasks(msg.unwrap()); worker_scope.from_worker_msg(task_queue.recv().unwrap()) }, - recv(timer_event_port) -> msg => worker_scope.from_timer_msg(msg.unwrap()), recv(devtools_port.unwrap_or(&crossbeam_channel::never())) -> msg => worker_scope.from_devtools_msg(msg.unwrap()), }; @@ -132,13 +126,10 @@ pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>( // Batch all events that are ready. // The task queue will throttle non-priority tasks if necessary. match task_queue.try_recv() { - Err(_) => match timer_event_port.try_recv() { - Err(_) => match devtools_port.map(|port| port.try_recv()) { - None => {}, - Some(Err(_)) => break, - Some(Ok(ev)) => sequential.push(worker_scope.from_devtools_msg(ev)), - }, - Ok(ev) => sequential.push(worker_scope.from_timer_msg(ev)), + Err(_) => match devtools_port.map(|port| port.try_recv()) { + None => {}, + Some(Err(_)) => break, + Some(Ok(ev)) => sequential.push(worker_scope.from_devtools_msg(ev)), }, Ok(ev) => sequential.push(worker_scope.from_worker_msg(ev)), } diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index fe3398417b2..39e8bfa275d 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -7408,7 +7408,16 @@ class CGIterableMethodGenerator(CGGeneric): rooted!(in(*cx) let mut call_arg2 = UndefinedValue()); let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(*_obj)]; rooted!(in(*cx) let mut ignoredReturnVal = UndefinedValue()); - for i in 0..(*this).get_iterable_length() { + + // This has to be a while loop since get_iterable_length() may change during + // the callback, and we need to avoid iterator invalidation. + // + // It is possible for this to loop infinitely, but that matches the spec + // and other browsers. + // + // https://heycam.github.io/webidl/#es-forEach + let mut i = 0; + while i < (*this).get_iterable_length() { (*this).get_value_at_index(i).to_jsval(*cx, call_arg1.handle_mut()); (*this).get_key_at_index(i).to_jsval(*cx, call_arg2.handle_mut()); call_args[0] = call_arg1.handle().get(); @@ -7418,6 +7427,8 @@ class CGIterableMethodGenerator(CGGeneric): ignoredReturnVal.handle_mut()) { return false; } + + i += 1; } let result = (); diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 9b16b0348d7..2f339d1f8f8 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -37,7 +37,7 @@ use crate::task_source::TaskSourceName; use crossbeam_channel::{unbounded, Receiver, Sender}; use devtools_traits::DevtoolScriptControlMsg; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use ipc_channel::ipc::IpcReceiver; use ipc_channel::router::ROUTER; use js::jsapi::JS_AddInterruptCallback; use js::jsapi::{Heap, JSContext, JSObject}; @@ -48,7 +48,7 @@ use net_traits::image_cache::ImageCache; use net_traits::request::{CredentialsMode, Destination, ParserMetadata}; use net_traits::request::{Referrer, RequestBuilder, RequestMode}; use net_traits::IpcSend; -use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin}; +use script_traits::{WorkerGlobalScopeInit, WorkerScriptLoadOrigin}; use servo_rand::random; use servo_url::ServoUrl; use std::mem::replace; @@ -93,7 +93,6 @@ pub enum DedicatedWorkerScriptMsg { pub enum MixedMessage { FromWorker(DedicatedWorkerScriptMsg), - FromScheduler((TrustedWorkerAddress, TimerEvent)), FromDevtools(DevtoolScriptControlMsg), } @@ -174,8 +173,6 @@ pub struct DedicatedWorkerGlobalScope { task_queue: TaskQueue<DedicatedWorkerScriptMsg>, #[ignore_malloc_size_of = "Defined in std"] own_sender: Sender<DedicatedWorkerScriptMsg>, - #[ignore_malloc_size_of = "Defined in std"] - timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>, #[ignore_malloc_size_of = "Trusted<T> has unclear ownership like Dom<T>"] worker: DomRefCell<Option<TrustedWorkerAddress>>, #[ignore_malloc_size_of = "Can't measure trait objects"] @@ -186,14 +183,9 @@ pub struct DedicatedWorkerGlobalScope { } impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope { - type TimerMsg = (TrustedWorkerAddress, TimerEvent); type WorkerMsg = DedicatedWorkerScriptMsg; type Event = MixedMessage; - fn timer_event_port(&self) -> &Receiver<(TrustedWorkerAddress, TimerEvent)> { - &self.timer_event_port - } - fn task_queue(&self) -> &TaskQueue<DedicatedWorkerScriptMsg> { &self.task_queue } @@ -211,10 +203,6 @@ impl WorkerEventLoopMethods for DedicatedWorkerGlobalScope { MixedMessage::FromWorker(msg) } - fn from_timer_msg(&self, msg: (TrustedWorkerAddress, TimerEvent)) -> MixedMessage { - MixedMessage::FromScheduler(msg) - } - fn from_devtools_msg(&self, msg: DevtoolScriptControlMsg) -> MixedMessage { MixedMessage::FromDevtools(msg) } @@ -231,8 +219,6 @@ impl DedicatedWorkerGlobalScope { parent_sender: Box<dyn ScriptChan + Send>, own_sender: Sender<DedicatedWorkerScriptMsg>, receiver: Receiver<DedicatedWorkerScriptMsg>, - timer_event_chan: IpcSender<TimerEvent>, - timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>, closing: Arc<AtomicBool>, image_cache: Arc<dyn ImageCache>, ) -> DedicatedWorkerGlobalScope { @@ -244,12 +230,10 @@ impl DedicatedWorkerGlobalScope { worker_url, runtime, from_devtools_receiver, - timer_event_chan, Some(closing), ), task_queue: TaskQueue::new(receiver, own_sender.clone()), own_sender: own_sender, - timer_event_port: timer_event_port, parent_sender: parent_sender, worker: DomRefCell::new(None), image_cache: image_cache, @@ -267,8 +251,6 @@ impl DedicatedWorkerGlobalScope { parent_sender: Box<dyn ScriptChan + Send>, own_sender: Sender<DedicatedWorkerScriptMsg>, receiver: Receiver<DedicatedWorkerScriptMsg>, - timer_event_chan: IpcSender<TimerEvent>, - timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>, closing: Arc<AtomicBool>, image_cache: Arc<dyn ImageCache>, ) -> DomRoot<DedicatedWorkerGlobalScope> { @@ -283,8 +265,6 @@ impl DedicatedWorkerGlobalScope { parent_sender, own_sender, receiver, - timer_event_chan, - timer_event_port, closing, image_cache, )); @@ -347,10 +327,14 @@ impl DedicatedWorkerGlobalScope { let runtime = unsafe { if let Some(pipeline_id) = pipeline_id { - new_child_runtime( - parent, - Some(NetworkingTaskSource(parent_sender.clone(), pipeline_id)), - ) + let task_source = NetworkingTaskSource( + Box::new(WorkerThreadWorkerChan { + sender: own_sender.clone(), + worker: worker.clone(), + }), + pipeline_id, + ); + new_child_runtime(parent, Some(task_source)) } else { new_child_runtime(parent, None) } @@ -362,17 +346,6 @@ impl DedicatedWorkerGlobalScope { devtools_mpsc_chan, ); - let (timer_tx, timer_rx) = unbounded(); - let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap(); - let worker_for_route = worker.clone(); - ROUTER.add_route( - timer_ipc_port.to_opaque(), - Box::new(move |message| { - let event = message.to().unwrap(); - timer_tx.send((worker_for_route.clone(), event)).unwrap(); - }), - ); - let global = DedicatedWorkerGlobalScope::new( init, DOMString::from_string(worker_name), @@ -383,8 +356,6 @@ impl DedicatedWorkerGlobalScope { parent_sender.clone(), own_sender, receiver, - timer_ipc_chan, - timer_rx, closing, image_cache, ); @@ -513,14 +484,6 @@ impl DedicatedWorkerGlobalScope { }, _ => debug!("got an unusable devtools control message inside the worker!"), }, - MixedMessage::FromScheduler((linked_worker, timer_event)) => match timer_event { - TimerEvent(TimerSource::FromWorker, id) => { - let _ar = AutoWorkerReset::new(self, linked_worker); - let scope = self.upcast::<WorkerGlobalScope>(); - scope.handle_fire_timer(id); - }, - TimerEvent(_, _) => panic!("A worker received a TimerEvent from a window."), - }, MixedMessage::FromWorker(DedicatedWorkerScriptMsg::CommonWorker( linked_worker, msg, diff --git a/components/script/dom/dissimilaroriginwindow.rs b/components/script/dom/dissimilaroriginwindow.rs index ac596048717..ac866a90ff8 100644 --- a/components/script/dom/dissimilaroriginwindow.rs +++ b/components/script/dom/dissimilaroriginwindow.rs @@ -15,7 +15,6 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::windowproxy::WindowProxy; use crate::script_runtime::JSContext; use dom_struct::dom_struct; -use ipc_channel::ipc; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, UndefinedValue}; use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue}; @@ -48,8 +47,6 @@ impl DissimilarOriginWindow { #[allow(unsafe_code)] pub fn new(global_to_clone_from: &GlobalScope, window_proxy: &WindowProxy) -> DomRoot<Self> { let cx = global_to_clone_from.get_cx(); - // Any timer events fired on this window are ignored. - let (timer_event_chan, _) = ipc::channel().unwrap(); let win = Box::new(Self { globalscope: GlobalScope::new_inherited( PipelineId::new(), @@ -59,7 +56,6 @@ impl DissimilarOriginWindow { global_to_clone_from.script_to_constellation_chan().clone(), global_to_clone_from.scheduler_chan().clone(), global_to_clone_from.resource_threads().clone(), - timer_event_chan, global_to_clone_from.origin().clone(), // FIXME(nox): The microtask queue is probably not important // here, but this whole DOM interface is a hack anyway. diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 1933d1e926e..4896c59e048 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -39,6 +39,7 @@ 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::timer::TimerTaskSource; use crate::task_source::websocket::WebsocketTaskSource; use crate::task_source::TaskSource; use crate::task_source::TaskSourceName; @@ -134,8 +135,13 @@ pub struct GlobalScope { /// including resource_thread, filemanager_thread and storage_thread resource_threads: ResourceThreads, + /// The mechanism by which time-outs and intervals are scheduled. + /// <https://html.spec.whatwg.org/multipage/#timers> timers: OneshotTimers, + /// Have timers been initialized? + init_timers: Cell<bool>, + /// The origin of the globalscope origin: MutableOrigin, @@ -188,6 +194,13 @@ struct MessageListener { context: Trusted<GlobalScope>, } +/// A wrapper between timer events coming in over IPC, and the event-loop. +struct TimerListener { + canceller: TaskCanceller, + task_source: TimerTaskSource, + context: Trusted<GlobalScope>, +} + /// Data representing a message-port managed by this global. #[derive(JSTraceable, MallocSizeOf)] pub enum ManagedMessagePort { @@ -212,6 +225,34 @@ pub enum MessagePortState { UnManaged, } +impl TimerListener { + /// Handle a timer-event coming-in over IPC, + /// by queuing the appropriate task on the relevant event-loop. + fn handle(&self, event: TimerEvent) { + let context = self.context.clone(); + // Step 18, queue a task, + // https://html.spec.whatwg.org/multipage/#timer-initialisation-steps + let _ = self.task_source.queue_with_canceller( + task!(timer_event: move || { + let global = context.root(); + let TimerEvent(source, id) = event; + match source { + TimerSource::FromWorker => { + global.downcast::<WorkerGlobalScope>().expect("Window timer delivered to worker"); + }, + TimerSource::FromWindow(pipeline) => { + assert_eq!(pipeline, global.pipeline_id()); + global.downcast::<Window>().expect("Worker timer delivered to window"); + }, + }; + // Step 7, substeps run in a task. + global.fire_timer(id); + }), + &self.canceller, + ); + } +} + impl MessageListener { /// A new message came in, handle it via a task enqueued on the event-loop. /// A task is required, since we are using a trusted globalscope, @@ -297,7 +338,6 @@ impl GlobalScope { script_to_constellation_chan: ScriptToConstellationChan, scheduler_chan: IpcSender<TimerSchedulerMsg>, resource_threads: ResourceThreads, - timer_event_chan: IpcSender<TimerEvent>, origin: MutableOrigin, microtask_queue: Rc<MicrotaskQueue>, is_headless: bool, @@ -318,7 +358,8 @@ impl GlobalScope { scheduler_chan: scheduler_chan.clone(), in_error_reporting_mode: Default::default(), resource_threads, - timers: OneshotTimers::new(timer_event_chan, scheduler_chan), + timers: OneshotTimers::new(scheduler_chan), + init_timers: Default::default(), origin, microtask_queue, list_auto_close_worker: Default::default(), @@ -349,6 +390,36 @@ impl GlobalScope { false } + /// Setup the IPC-to-event-loop glue for timers to schedule themselves. + fn setup_timers(&self) { + if self.init_timers.get() { + return; + } + self.init_timers.set(true); + + let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap(); + self.timers.setup_scheduling(timer_ipc_chan); + + // Setup route from IPC to task-queue for the timer-task-source. + let context = Trusted::new(&*self); + let (task_source, canceller) = ( + self.timer_task_source(), + self.task_canceller(TaskSourceName::Timer), + ); + let timer_listener = TimerListener { + context, + task_source, + canceller, + }; + ROUTER.add_route( + timer_ipc_port.to_opaque(), + Box::new(move |message| { + let event = message.to().unwrap(); + timer_listener.handle(event); + }), + ); + } + /// Complete the transfer of a message-port. fn complete_port_transfer(&self, port_id: MessagePortId, tasks: VecDeque<PortMessageTask>) { let should_start = if let MessagePortState::Managed(_id, message_ports) = @@ -1063,6 +1134,18 @@ impl GlobalScope { unreachable!(); } + /// `TaskSource` to send messages to the timer queue of + /// this global scope. + pub fn timer_task_source(&self) -> TimerTaskSource { + if let Some(window) = self.downcast::<Window>() { + return window.task_manager().timer_task_source(); + } + if let Some(worker) = self.downcast::<WorkerGlobalScope>() { + return worker.timer_task_source(); + } + unreachable!(); + } + /// `TaskSource` to send messages to the remote-event task source of /// this global scope. pub fn remote_event_task_source(&self) -> RemoteEventTaskSource { @@ -1145,11 +1228,13 @@ impl GlobalScope { ) } + /// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps> pub fn schedule_callback( &self, callback: OneshotTimerCallback, duration: MsDuration, ) -> OneshotTimerHandle { + self.setup_timers(); self.timers .schedule_callback(callback, duration, self.timer_source()) } @@ -1158,6 +1243,7 @@ impl GlobalScope { self.timers.unschedule_callback(handle); } + /// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps> pub fn set_timeout_or_interval( &self, callback: TimerCallback, @@ -1165,6 +1251,7 @@ impl GlobalScope { timeout: i32, is_interval: IsInterval, ) -> i32 { + self.setup_timers(); self.timers.set_timeout_or_interval( self, callback, @@ -1176,27 +1263,27 @@ impl GlobalScope { } pub fn clear_timeout_or_interval(&self, handle: i32) { - self.timers.clear_timeout_or_interval(self, handle) + self.timers.clear_timeout_or_interval(self, handle); } pub fn fire_timer(&self, handle: TimerEventId) { - self.timers.fire_timer(handle, self) + self.timers.fire_timer(handle, self); } pub fn resume(&self) { - self.timers.resume() + self.timers.resume(); } pub fn suspend(&self) { - self.timers.suspend() + self.timers.suspend(); } pub fn slow_down_timers(&self) { - self.timers.slow_down() + self.timers.slow_down(); } pub fn speed_up_timers(&self) { - self.timers.speed_up() + self.timers.speed_up(); } fn timer_source(&self) -> TimerSource { diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs index cb72a4a25e4..2a3f4d7041a 100644 --- a/components/script/dom/serviceworkerglobalscope.rs +++ b/components/script/dom/serviceworkerglobalscope.rs @@ -28,24 +28,22 @@ use crate::script_runtime::{ }; use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue}; use crate::task_source::TaskSourceName; -use crossbeam_channel::{unbounded, Receiver, Sender}; +use crossbeam_channel::{after, unbounded, Receiver, Sender}; use devtools_traits::DevtoolScriptControlMsg; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use js::jsapi::{JSContext, JS_AddInterruptCallback}; use js::jsval::UndefinedValue; use msg::constellation_msg::PipelineId; use net_traits::request::{CredentialsMode, Destination, ParserMetadata, Referrer, RequestBuilder}; use net_traits::{CustomResponseMediator, IpcSend}; -use script_traits::{ - ScopeThings, ServiceWorkerMsg, TimerEvent, WorkerGlobalScopeInit, WorkerScriptLoadOrigin, -}; +use script_traits::{ScopeThings, ServiceWorkerMsg, WorkerGlobalScopeInit, WorkerScriptLoadOrigin}; use servo_config::pref; use servo_rand::random; use servo_url::ServoUrl; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; use style::thread_state::{self, ThreadState}; /// Messages used to control service worker event loop @@ -118,7 +116,6 @@ impl QueuedTaskConversion for ServiceWorkerScriptMsg { pub enum MixedMessage { FromServiceWorker(ServiceWorkerScriptMsg), FromDevtools(DevtoolScriptControlMsg), - FromTimeoutThread(()), } #[derive(Clone, JSTraceable)] @@ -147,26 +144,30 @@ unsafe_no_jsmanaged_fields!(TaskQueue<ServiceWorkerScriptMsg>); #[dom_struct] pub struct ServiceWorkerGlobalScope { workerglobalscope: WorkerGlobalScope, + #[ignore_malloc_size_of = "Defined in std"] task_queue: TaskQueue<ServiceWorkerScriptMsg>, + #[ignore_malloc_size_of = "Defined in std"] own_sender: Sender<ServiceWorkerScriptMsg>, + + /// A port on which a single "time-out" message can be received, + /// indicating the sw should stop running, + /// while still draining the task-queue + // and running all enqueued, and not cancelled, tasks. #[ignore_malloc_size_of = "Defined in std"] - timer_event_port: Receiver<()>, + time_out_port: Receiver<Instant>, + #[ignore_malloc_size_of = "Defined in std"] swmanager_sender: IpcSender<ServiceWorkerMsg>, + scope_url: ServoUrl, } impl WorkerEventLoopMethods for ServiceWorkerGlobalScope { - type TimerMsg = (); type WorkerMsg = ServiceWorkerScriptMsg; type Event = MixedMessage; - fn timer_event_port(&self) -> &Receiver<()> { - &self.timer_event_port - } - fn task_queue(&self) -> &TaskQueue<ServiceWorkerScriptMsg> { &self.task_queue } @@ -183,10 +184,6 @@ impl WorkerEventLoopMethods for ServiceWorkerGlobalScope { MixedMessage::FromServiceWorker(msg) } - fn from_timer_msg(&self, msg: ()) -> MixedMessage { - MixedMessage::FromTimeoutThread(msg) - } - fn from_devtools_msg(&self, msg: DevtoolScriptControlMsg) -> MixedMessage { MixedMessage::FromDevtools(msg) } @@ -200,8 +197,7 @@ impl ServiceWorkerGlobalScope { runtime: Runtime, own_sender: Sender<ServiceWorkerScriptMsg>, receiver: Receiver<ServiceWorkerScriptMsg>, - timer_event_chan: IpcSender<TimerEvent>, - timer_event_port: Receiver<()>, + time_out_port: Receiver<Instant>, swmanager_sender: IpcSender<ServiceWorkerMsg>, scope_url: ServoUrl, ) -> ServiceWorkerGlobalScope { @@ -213,12 +209,11 @@ impl ServiceWorkerGlobalScope { worker_url, runtime, from_devtools_receiver, - timer_event_chan, None, ), task_queue: TaskQueue::new(receiver, own_sender.clone()), - timer_event_port: timer_event_port, own_sender: own_sender, + time_out_port, swmanager_sender: swmanager_sender, scope_url: scope_url, } @@ -232,8 +227,7 @@ impl ServiceWorkerGlobalScope { runtime: Runtime, own_sender: Sender<ServiceWorkerScriptMsg>, receiver: Receiver<ServiceWorkerScriptMsg>, - timer_event_chan: IpcSender<TimerEvent>, - timer_event_port: Receiver<()>, + time_out_port: Receiver<Instant>, swmanager_sender: IpcSender<ServiceWorkerMsg>, scope_url: ServoUrl, ) -> DomRoot<ServiceWorkerGlobalScope> { @@ -245,8 +239,7 @@ impl ServiceWorkerGlobalScope { runtime, own_sender, receiver, - timer_event_chan, - timer_event_port, + time_out_port, swmanager_sender, scope_url, )); @@ -320,9 +313,12 @@ impl ServiceWorkerGlobalScope { let (devtools_mpsc_chan, devtools_mpsc_port) = unbounded(); ROUTER .route_ipc_receiver_to_crossbeam_sender(devtools_receiver, devtools_mpsc_chan); - // TODO XXXcreativcoder use this timer_ipc_port, when we have a service worker instance here - let (timer_ipc_chan, _timer_ipc_port) = ipc::channel().unwrap(); - let (timer_chan, timer_port) = unbounded(); + + // Service workers are time limited + // https://w3c.github.io/ServiceWorker/#service-worker-lifetime + let sw_lifetime_timeout = pref!(dom.serviceworker.timeout_seconds) as u64; + let time_out_port = after(Duration::new(sw_lifetime_timeout, 0)); + let global = ServiceWorkerGlobalScope::new( init, url, @@ -330,8 +326,7 @@ impl ServiceWorkerGlobalScope { runtime, own_sender, receiver, - timer_ipc_chan, - timer_port, + time_out_port, swmanager_sender, scope_url, ); @@ -343,15 +338,6 @@ impl ServiceWorkerGlobalScope { } scope.execute_script(DOMString::from(source)); - // Service workers are time limited - thread::Builder::new() - .name("SWTimeoutThread".to_owned()) - .spawn(move || { - let sw_lifetime_timeout = pref!(dom.serviceworker.timeout_seconds) as u64; - thread::sleep(Duration::new(sw_lifetime_timeout, 0)); - let _ = timer_chan.send(()); - }) - .expect("Thread spawning failed"); global.dispatch_activate(); let reporter_name = format!("service-worker-reporter-{}", random::<u64>()); @@ -364,8 +350,9 @@ impl ServiceWorkerGlobalScope { // by inside settings until it is destroyed. // The worker processing model remains on this step // until the event loop is destroyed, - // which happens after the closing flag is set to true. - while !scope.is_closing() { + // which happens after the closing flag is set to true, + // or until the worker has run beyond its allocated time. + while !scope.is_closing() || !global.has_timed_out() { run_worker_event_loop(&*global, None); } }, @@ -398,15 +385,21 @@ impl ServiceWorkerGlobalScope { self.handle_script_event(msg); true }, - MixedMessage::FromTimeoutThread(_) => { - let _ = self - .swmanager_sender - .send(ServiceWorkerMsg::Timeout(self.scope_url.clone())); - false - }, } } + fn has_timed_out(&self) -> bool { + // Note: this should be included in the `select` inside `run_worker_event_loop`, + // otherwise a block on the select can prevent the timeout. + if self.time_out_port.try_recv().is_ok() { + let _ = self + .swmanager_sender + .send(ServiceWorkerMsg::Timeout(self.scope_url.clone())); + return true; + } + false + } + fn handle_script_event(&self, msg: ServiceWorkerScriptMsg) { use self::ServiceWorkerScriptMsg::*; diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index d9a3e81b46a..2c63b775bb1 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -25,7 +25,7 @@ use crate::dom::webglprogram::WebGLProgram; use crate::dom::webglquery::WebGLQuery; use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ - LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, + LayoutCanvasWebGLRenderingContextHelpers, Size2DExt, WebGLRenderingContext, }; use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue}; use crate::dom::webglshader::WebGLShader; @@ -42,13 +42,15 @@ use canvas_traits::webgl::{ webgl_channel, GLContextAttributes, WebGLCommand, WebGLResult, WebGLVersion, }; use dom_struct::dom_struct; -use euclid::default::Size2D; +use euclid::default::{Point2D, Rect, Size2D}; use ipc_channel::ipc; use js::jsapi::{JSObject, Type}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value}; use js::rust::CustomAutoRooterGuard; use js::typedarray::ArrayBufferView; use script_layout_interface::HTMLCanvasDataSource; +use std::cell::Cell; +use std::cmp; use std::ptr::NonNull; #[dom_struct] @@ -65,6 +67,9 @@ pub struct WebGL2RenderingContext { bound_transform_feedback_buffer: MutNullableDom<WebGLBuffer>, bound_uniform_buffer: MutNullableDom<WebGLBuffer>, current_transform_feedback: MutNullableDom<WebGLTransformFeedback>, + texture_pack_row_length: Cell<usize>, + texture_pack_skip_pixels: Cell<usize>, + texture_pack_skip_rows: Cell<usize>, } fn typedarray_elem_size(typeid: Type) -> usize { @@ -77,6 +82,17 @@ fn typedarray_elem_size(typeid: Type) -> usize { } } +struct ReadPixelsAllowedFormats<'a> { + array_types: &'a [Type], + channels: usize, +} + +struct ReadPixelsSizes { + row_stride: usize, + skipped_bytes: usize, + size: usize, +} + impl WebGL2RenderingContext { fn new_inherited( window: &Window, @@ -104,6 +120,9 @@ impl WebGL2RenderingContext { bound_transform_feedback_buffer: MutNullableDom::new(None), bound_uniform_buffer: MutNullableDom::new(None), current_transform_feedback: MutNullableDom::new(None), + texture_pack_row_length: Cell::new(0), + texture_pack_skip_pixels: Cell::new(0), + texture_pack_skip_rows: Cell::new(0), }) } @@ -147,6 +166,213 @@ impl WebGL2RenderingContext { slot.set(None); } } + + fn calc_read_pixel_formats( + &self, + pixel_type: u32, + format: u32, + ) -> WebGLResult<ReadPixelsAllowedFormats> { + let array_types = match pixel_type { + constants::BYTE => &[Type::Int8][..], + constants::SHORT => &[Type::Int16][..], + constants::INT => &[Type::Int32][..], + constants::UNSIGNED_BYTE => &[Type::Uint8, Type::Uint8Clamped][..], + constants::UNSIGNED_SHORT | + constants::UNSIGNED_SHORT_4_4_4_4 | + constants::UNSIGNED_SHORT_5_5_5_1 | + constants::UNSIGNED_SHORT_5_6_5 => &[Type::Uint16][..], + constants::UNSIGNED_INT | + constants::UNSIGNED_INT_2_10_10_10_REV | + constants::UNSIGNED_INT_10F_11F_11F_REV | + constants::UNSIGNED_INT_5_9_9_9_REV => &[Type::Uint32][..], + constants::FLOAT => &[Type::Float32][..], + constants::HALF_FLOAT => &[Type::Uint16][..], + _ => return Err(InvalidEnum), + }; + let channels = match format { + constants::ALPHA | constants::RED | constants::RED_INTEGER => 1, + constants::RG | constants::RG_INTEGER => 2, + constants::RGB | constants::RGB_INTEGER => 3, + constants::RGBA | constants::RGBA_INTEGER => 4, + _ => return Err(InvalidEnum), + }; + Ok(ReadPixelsAllowedFormats { + array_types, + channels, + }) + } + + fn calc_read_pixel_sizes( + &self, + width: i32, + height: i32, + bytes_per_pixel: usize, + ) -> WebGLResult<ReadPixelsSizes> { + if width < 0 || height < 0 { + return Err(InvalidValue); + } + + // See also https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.36 + let pixels_per_row = if self.texture_pack_row_length.get() > 0 { + self.texture_pack_row_length.get() + } else { + width as usize + }; + if self.texture_pack_skip_pixels.get() + width as usize > pixels_per_row { + return Err(InvalidOperation); + } + + let bytes_per_row = pixels_per_row + .checked_mul(bytes_per_pixel) + .ok_or(InvalidOperation)?; + let row_padding_bytes = { + let pack_alignment = self.base.get_texture_packing_alignment() as usize; + match bytes_per_row % pack_alignment { + 0 => 0, + remainder => pack_alignment - remainder, + } + }; + let row_stride = bytes_per_row + row_padding_bytes; + let size = if width == 0 || height == 0 { + 0 + } else { + let full_row_bytes = row_stride + .checked_mul(height as usize - 1) + .ok_or(InvalidOperation)?; + let last_row_bytes = bytes_per_pixel + .checked_mul(width as usize) + .ok_or(InvalidOperation)?; + let result = full_row_bytes + .checked_add(last_row_bytes) + .ok_or(InvalidOperation)?; + result + }; + let skipped_bytes = { + let skipped_row_bytes = self + .texture_pack_skip_rows + .get() + .checked_mul(row_stride) + .ok_or(InvalidOperation)?; + let skipped_pixel_bytes = self + .texture_pack_skip_pixels + .get() + .checked_mul(bytes_per_pixel) + .ok_or(InvalidOperation)?; + let result = skipped_row_bytes + .checked_add(skipped_pixel_bytes) + .ok_or(InvalidOperation)?; + result + }; + Ok(ReadPixelsSizes { + row_stride, + skipped_bytes, + size, + }) + } + + #[allow(unsafe_code)] + fn read_pixels_into( + &self, + x: i32, + y: i32, + width: i32, + height: i32, + format: u32, + pixel_type: u32, + dst: &mut ArrayBufferView, + dst_elem_offset: u32, + ) { + handle_potential_webgl_error!(self.base, self.base.validate_framebuffer(), return); + + if self.bound_pixel_pack_buffer.get().is_some() { + return self.base.webgl_error(InvalidOperation); + } + + let dst_byte_offset = { + let dst_elem_size = typedarray_elem_size(dst.get_array_type()); + dst_elem_offset as usize * dst_elem_size + }; + if dst_byte_offset > dst.len() { + return self.base.webgl_error(InvalidValue); + } + + let dst_array_type = dst.get_array_type(); + let ReadPixelsAllowedFormats { + array_types: allowed_array_types, + channels, + } = match self.calc_read_pixel_formats(pixel_type, format) { + Ok(result) => result, + Err(error) => return self.base.webgl_error(error), + }; + if !allowed_array_types.contains(&dst_array_type) { + return self.base.webgl_error(InvalidOperation); + } + if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE { + return self.base.webgl_error(InvalidOperation); + } + + let bytes_per_pixel = typedarray_elem_size(dst_array_type) * channels; + let ReadPixelsSizes { + row_stride, + skipped_bytes, + size, + } = match self.calc_read_pixel_sizes(width, height, bytes_per_pixel) { + Ok(result) => result, + Err(error) => return self.base.webgl_error(error), + }; + let dst_end = dst_byte_offset + skipped_bytes + size; + let dst_pixels = unsafe { dst.as_mut_slice() }; + if dst_pixels.len() < dst_end { + return self.base.webgl_error(InvalidOperation); + } + + let dst_byte_offset = { + let margin_left = cmp::max(0, -x) as usize; + let margin_top = cmp::max(0, -y) as usize; + dst_byte_offset + + skipped_bytes + + margin_left * bytes_per_pixel + + margin_top * row_stride + }; + let src_rect = { + let (fb_width, fb_height) = handle_potential_webgl_error!( + self.base, + self.base + .get_current_framebuffer_size() + .ok_or(InvalidOperation), + return + ); + let src_origin = Point2D::new(x, y); + let src_size = Size2D::new(width as u32, height as u32); + let fb_size = Size2D::new(fb_width as u32, fb_height as u32); + match pixels::clip(src_origin, src_size.to_u64(), fb_size.to_u64()) { + Some(rect) => rect.to_u32(), + None => return, + } + }; + let src_row_bytes = handle_potential_webgl_error!( + self.base, + src_rect + .size + .width + .checked_mul(bytes_per_pixel as u32) + .ok_or(InvalidOperation), + return + ); + + let (sender, receiver) = ipc::bytes_channel().unwrap(); + self.base.send_command(WebGLCommand::ReadPixels( + src_rect, format, pixel_type, sender, + )); + let src = receiver.recv().unwrap(); + + for i in 0..src_rect.size.height as usize { + let src_start = i * src_row_bytes as usize; + let dst_start = dst_byte_offset + i * row_stride; + dst_pixels[dst_start..dst_start + src_row_bytes as usize] + .copy_from_slice(&src[src_start..src_start + src_row_bytes as usize]); + } + } } impl WebGL2RenderingContextMethods for WebGL2RenderingContext { @@ -936,9 +1162,18 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { self.base.LineWidth(width) } - /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.2 fn PixelStorei(&self, param_name: u32, param_value: i32) { - self.base.PixelStorei(param_name, param_value) + if param_value < 0 { + return self.base.webgl_error(InvalidValue); + } + + match param_name { + constants::PACK_ROW_LENGTH => self.texture_pack_row_length.set(param_value as _), + constants::PACK_SKIP_PIXELS => self.texture_pack_skip_pixels.set(param_value as _), + constants::PACK_SKIP_ROWS => self.texture_pack_skip_rows.set(param_value as _), + _ => self.base.PixelStorei(param_name, param_value), + } } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -955,10 +1190,128 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { height: i32, format: u32, pixel_type: u32, - pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>, + mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>, ) { - self.base - .ReadPixels(x, y, width, height, format, pixel_type, pixels) + let pixels = + handle_potential_webgl_error!(self.base, pixels.as_mut().ok_or(InvalidValue), return); + + self.read_pixels_into(x, y, width, height, format, pixel_type, pixels, 0) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.10 + fn ReadPixels_( + &self, + x: i32, + y: i32, + width: i32, + height: i32, + format: u32, + pixel_type: u32, + dst_byte_offset: i64, + ) { + handle_potential_webgl_error!(self.base, self.base.validate_framebuffer(), return); + + let dst = match self.bound_pixel_pack_buffer.get() { + Some(buffer) => buffer, + None => return self.base.webgl_error(InvalidOperation), + }; + + if dst_byte_offset < 0 { + return self.base.webgl_error(InvalidValue); + } + let dst_byte_offset = dst_byte_offset as usize; + if dst_byte_offset > dst.capacity() { + return self.base.webgl_error(InvalidOperation); + } + + let ReadPixelsAllowedFormats { + array_types: _, + channels: bytes_per_pixel, + } = match self.calc_read_pixel_formats(pixel_type, format) { + Ok(result) => result, + Err(error) => return self.base.webgl_error(error), + }; + if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE { + return self.base.webgl_error(InvalidOperation); + } + + let ReadPixelsSizes { + row_stride: _, + skipped_bytes, + size, + } = match self.calc_read_pixel_sizes(width, height, bytes_per_pixel) { + Ok(result) => result, + Err(error) => return self.base.webgl_error(error), + }; + let dst_end = dst_byte_offset + skipped_bytes + size; + if dst.capacity() < dst_end { + return self.base.webgl_error(InvalidOperation); + } + + { + let (fb_width, fb_height) = handle_potential_webgl_error!( + self.base, + self.base + .get_current_framebuffer_size() + .ok_or(InvalidOperation), + return + ); + let src_origin = Point2D::new(x, y); + let src_size = Size2D::new(width as u32, height as u32); + let fb_size = Size2D::new(fb_width as u32, fb_height as u32); + if pixels::clip(src_origin, src_size.to_u64(), fb_size.to_u64()).is_none() { + return; + } + } + let src_rect = Rect::new(Point2D::new(x, y), Size2D::new(width, height)); + + self.base.send_command(WebGLCommand::PixelStorei( + constants::PACK_ALIGNMENT, + self.base.get_texture_packing_alignment() as _, + )); + self.base.send_command(WebGLCommand::PixelStorei( + constants::PACK_ROW_LENGTH, + self.texture_pack_row_length.get() as _, + )); + self.base.send_command(WebGLCommand::PixelStorei( + constants::PACK_SKIP_ROWS, + self.texture_pack_skip_rows.get() as _, + )); + self.base.send_command(WebGLCommand::PixelStorei( + constants::PACK_SKIP_PIXELS, + self.texture_pack_skip_pixels.get() as _, + )); + self.base.send_command(WebGLCommand::ReadPixelsPP( + src_rect, + format, + pixel_type, + dst_byte_offset, + )); + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.10 + #[allow(unsafe_code)] + fn ReadPixels__( + &self, + x: i32, + y: i32, + width: i32, + height: i32, + format: u32, + pixel_type: u32, + mut dst: CustomAutoRooterGuard<ArrayBufferView>, + dst_elem_offset: u32, + ) { + self.read_pixels_into( + x, + y, + width, + height, + format, + pixel_type, + &mut dst, + dst_elem_offset, + ) } /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 74fd8068a72..85930cd3529 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -380,7 +380,7 @@ impl WebGLRenderingContext { // // The WebGL spec mentions a couple more operations that trigger // this: clear() and getParameter(IMPLEMENTATION_COLOR_READ_*). - fn validate_framebuffer(&self) -> WebGLResult<()> { + pub fn validate_framebuffer(&self) -> WebGLResult<()> { match self.bound_framebuffer.get() { Some(fb) => match fb.check_status_for_rendering() { CompleteForRendering::Complete => Ok(()), @@ -481,7 +481,7 @@ impl WebGLRenderingContext { self.send_command(WebGLCommand::VertexAttrib(indx, x, y, z, w)); } - fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { + pub fn get_current_framebuffer_size(&self) -> Option<(i32, i32)> { match self.bound_framebuffer.get() { Some(fb) => return fb.size(), @@ -490,6 +490,10 @@ impl WebGLRenderingContext { } } + pub fn get_texture_packing_alignment(&self) -> u8 { + self.texture_packing_alignment.get() + } + // LINEAR filtering may be forbidden when using WebGL extensions. // https://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/ fn validate_filterable_texture( diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl index 312c7b78211..71b5ab10034 100644 --- a/components/script/dom/webidls/WebGL2RenderingContext.webidl +++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl @@ -497,10 +497,10 @@ interface mixin WebGL2RenderingContextBase void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, /*[AllowShared]*/ ArrayBufferView? dstData); // WebGL2: - // void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - // GLintptr offset); - // void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - // [AllowShared] ArrayBufferView dstData, GLuint dstOffset); + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + GLintptr offset); + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, + /*[AllowShared]*/ ArrayBufferView dstData, GLuint dstOffset); /* Multiple Render Targets */ // void drawBuffers(sequence<GLenum> buffers); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4ae94520f1f..ef8719ab8e6 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -106,8 +106,7 @@ use script_layout_interface::{PendingImageState, TrustedNodeAddress}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use script_traits::{ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData}; use script_traits::{ - ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEvent, - TimerEventId, + ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEventId, }; use script_traits::{TimerSchedulerMsg, WindowSizeData, WindowSizeType}; use selectors::attr::CaseSensitivity; @@ -2206,7 +2205,6 @@ impl Window { constellation_chan: ScriptToConstellationChan, control_chan: IpcSender<ConstellationControlMsg>, scheduler_chan: IpcSender<TimerSchedulerMsg>, - timer_event_chan: IpcSender<TimerEvent>, layout_chan: Sender<Msg>, pipelineid: PipelineId, parent_info: Option<PipelineId>, @@ -2250,7 +2248,6 @@ impl Window { constellation_chan, scheduler_chan, resource_threads, - timer_event_chan, origin, microtask_queue, is_headless, diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 7e55cbfc046..e943b6b0ef4 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -34,6 +34,7 @@ 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::timer::TimerTaskSource; use crate::task_source::websocket::WebsocketTaskSource; use crate::timers::{IsInterval, TimerCallback}; use crossbeam_channel::Receiver; @@ -50,7 +51,6 @@ use net_traits::request::{ }; use net_traits::IpcSend; use script_traits::WorkerGlobalScopeInit; -use script_traits::{TimerEvent, TimerEventId}; use servo_url::{MutableOrigin, ServoUrl}; use std::cell::Ref; use std::default::Default; @@ -120,7 +120,6 @@ impl WorkerGlobalScope { worker_url: ServoUrl, runtime: Runtime, from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, - timer_event_chan: IpcSender<TimerEvent>, closing: Option<Arc<AtomicBool>>, ) -> Self { // Install a pipeline-namespace in the current thread. @@ -134,7 +133,6 @@ impl WorkerGlobalScope { init.script_to_constellation_chan, init.scheduler_chan, init.resource_threads, - timer_event_chan, MutableOrigin::new(init.origin), runtime.microtask_queue.clone(), init.is_headless, @@ -437,6 +435,10 @@ impl WorkerGlobalScope { PortMessageQueue(self.script_chan(), self.pipeline_id()) } + pub fn timer_task_source(&self) -> TimerTaskSource { + TimerTaskSource(self.script_chan(), self.pipeline_id()) + } + pub fn remote_event_task_source(&self) -> RemoteEventTaskSource { RemoteEventTaskSource(self.script_chan(), self.pipeline_id()) } @@ -466,10 +468,6 @@ impl WorkerGlobalScope { } } - pub fn handle_fire_timer(&self, timer_id: TimerEventId) { - self.upcast::<GlobalScope>().fire_timer(timer_id); - } - pub fn close(&self) { if let Some(ref closing) = self.closing { closing.store(true, Ordering::SeqCst); diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index 90fa5bd0115..995014cfc1a 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -15,7 +15,6 @@ use crate::script_thread::MainThreadScriptMsg; use crossbeam_channel::Sender; use devtools_traits::ScriptToDevtoolsControlMsg; use dom_struct::dom_struct; -use ipc_channel::ipc; use ipc_channel::ipc::IpcSender; use js::jsval::UndefinedValue; use js::rust::Runtime; @@ -55,8 +54,6 @@ impl WorkletGlobalScope { executor: WorkletExecutor, init: &WorkletGlobalScopeInit, ) -> Self { - // Any timer events fired on this global are ignored. - let (timer_event_chan, _) = ipc::channel().unwrap(); let script_to_constellation_chan = ScriptToConstellationChan { sender: init.to_constellation_sender.clone(), pipeline_id, @@ -70,7 +67,6 @@ impl WorkletGlobalScope { script_to_constellation_chan, init.scheduler_chan.clone(), init.resource_threads.clone(), - timer_event_chan, MutableOrigin::new(ImmutableOrigin::new_opaque()), Default::default(), init.is_headless, |