diff options
Diffstat (limited to 'components/script/script_thread.rs')
-rw-r--r-- | components/script/script_thread.rs | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 008274ded47..9754aa65ede 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -17,6 +17,9 @@ //! a page runs its course and the script thread returns to processing events in the main event //! loop. +use crate::animations::{ + AnimationsUpdate, TransitionOrAnimationEvent, TransitionOrAnimationEventType, +}; use crate::devtools; use crate::document_loader::DocumentLoader; use crate::dom::animationevent::AnimationEvent; @@ -141,8 +144,8 @@ use script_traits::{ LayoutMsg, LoadData, LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType, NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptMsg, ScriptThreadFactory, ScriptToConstellationChan, StructuredSerializedData, TimerSchedulerMsg, TouchEventType, - TouchId, TransitionOrAnimationEvent, TransitionOrAnimationEventType, UntrustedNodeAddress, - UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta, WindowSizeData, WindowSizeType, + TouchId, UntrustedNodeAddress, UpdatePipelineIdReason, WebrenderIpcSender, WheelDelta, + WindowSizeData, WindowSizeType, }; use servo_atoms::Atom; use servo_config::opts; @@ -510,10 +513,8 @@ impl<'a> Iterator for DocumentsIter<'a> { // thread during parsing. For this reason, we don't trace the // incomplete parser contexts during GC. type IncompleteParserContexts = Vec<(PipelineId, ParserContext)>; -unsafe_no_jsmanaged_fields!(RefCell<IncompleteParserContexts>); unsafe_no_jsmanaged_fields!(TaskQueue<MainThreadScriptMsg>); - unsafe_no_jsmanaged_fields!(dyn BackgroundHangMonitorRegister); unsafe_no_jsmanaged_fields!(dyn BackgroundHangMonitor); @@ -644,6 +645,9 @@ pub struct ScriptThread { /// of the transition. animating_nodes: DomRefCell<HashMap<PipelineId, Vec<Dom<Node>>>>, + /// Animations events that are pending to be sent. + animation_events: RefCell<Vec<TransitionOrAnimationEvent>>, + /// <https://html.spec.whatwg.org/multipage/#custom-element-reactions-stack> custom_element_reaction_stack: CustomElementReactionStack, @@ -826,20 +830,35 @@ impl ScriptThread { }) } - pub unsafe fn note_newly_animating_nodes( - pipeline_id: PipelineId, - nodes: Vec<UntrustedNodeAddress>, - ) { + /// Consume the list of pointer addresses corresponding to DOM nodes that are animating + /// and root them in a per-pipeline list of nodes. + /// + /// Unsafety: any pointer to invalid memory (ie. a GCed node) will trigger a crash. + /// TODO: ensure caller uses rooted nodes instead of unsafe node addresses. + pub(crate) unsafe fn process_animations_update(mut update: AnimationsUpdate) { + if update.is_empty() { + return; + } + SCRIPT_THREAD_ROOT.with(|root| { let script_thread = &*root.get().unwrap(); + + if !update.events.is_empty() { + script_thread + .animation_events + .borrow_mut() + .append(&mut update.events); + } + let js_runtime = script_thread.js_runtime.rt(); - let new_nodes = nodes + let new_nodes = update + .newly_animating_nodes .into_iter() .map(|n| Dom::from_ref(&*from_untrusted_node_address(js_runtime, n))); script_thread .animating_nodes .borrow_mut() - .entry(pipeline_id) + .entry(update.pipeline_id) .or_insert_with(Vec::new) .extend(new_nodes); }) @@ -1354,6 +1373,7 @@ impl ScriptThread { docs_with_no_blocking_loads: Default::default(), animating_nodes: Default::default(), + animation_events: Default::default(), custom_element_reaction_stack: CustomElementReactionStack::new(), @@ -1620,9 +1640,8 @@ impl ScriptThread { } // Perform step 11.10 from https://html.spec.whatwg.org/multipage/#event-loops. - // TODO(mrobinson): This should also update the current animations and send events - // to conform to the HTML specification. This might mean having events for rooting - // DOM nodes and ultimately all animations living in script. + // TODO(mrobinson): This should also update the current animations to conform to + // the HTML specification. fn update_animations_and_send_events(&self) { for (_, document) in self.documents.borrow().iter() { // Only update the time if it isn't being managed by a test. @@ -1630,6 +1649,13 @@ impl ScriptThread { document.update_animation_timeline(); } } + + // We remove the events because handling these events might trigger + // a reflow which might want to add more events to the queue. + let events = self.animation_events.replace(Vec::new()); + for event in events.into_iter() { + self.handle_transition_or_animation_event(&event); + } } fn categorize_msg(&self, msg: &MixedMessage) -> ScriptThreadEventCategory { @@ -1720,7 +1746,6 @@ impl ScriptThread { FocusIFrame(id, ..) => Some(id), WebDriverScriptCommand(id, ..) => Some(id), TickAllAnimations(id, ..) => Some(id), - TransitionOrAnimationEvent { .. } => None, WebFontLoaded(id) => Some(id), DispatchIFrameLoadEvent { target: _, @@ -1921,9 +1946,6 @@ impl ScriptThread { ConstellationControlMsg::TickAllAnimations(pipeline_id, tick_type) => { self.handle_tick_all_animations(pipeline_id, tick_type) }, - ConstellationControlMsg::TransitionOrAnimationEvent(ref event) => { - self.handle_transition_or_animation_event(event); - }, ConstellationControlMsg::WebFontLoaded(pipeline_id) => { self.handle_web_font_loaded(pipeline_id) }, |