aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/compositor.rs81
-rw-r--r--components/compositing/webview_renderer.rs82
-rw-r--r--components/constellation/constellation.rs42
-rw-r--r--components/constellation/event_loop.rs21
-rw-r--r--components/devtools/actors/source.rs50
-rw-r--r--components/devtools/actors/thread.rs39
-rw-r--r--components/devtools/actors/watcher.rs2
-rw-r--r--components/devtools/lib.rs9
-rw-r--r--components/layout/dom.rs25
-rw-r--r--components/layout/table/mod.rs1
-rw-r--r--components/malloc_size_of/lib.rs1
-rw-r--r--components/script/dom/document.rs30
-rw-r--r--components/script/dom/node.rs1
-rw-r--r--components/script/layout_image.rs5
-rw-r--r--components/script/messaging.rs2
-rw-r--r--components/script/script_thread.rs28
-rw-r--r--components/shared/constellation/lib.rs17
-rw-r--r--components/shared/script/lib.rs4
-rw-r--r--components/shared/script_layout/lib.rs9
-rw-r--r--components/shared/script_layout/wrapper_traits.rs6
20 files changed, 232 insertions, 223 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 4550188a7fa..41286a2760a 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -21,12 +21,12 @@ use compositing_traits::rendering_context::RenderingContext;
use compositing_traits::{
CompositionPipeline, CompositorMsg, ImageUpdate, SendableFrameTree, WebViewTrait,
};
-use constellation_traits::{AnimationTickType, EmbedderToConstellationMessage, PaintMetricEvent};
+use constellation_traits::{EmbedderToConstellationMessage, PaintMetricEvent};
use crossbeam_channel::{Receiver, Sender};
use dpi::PhysicalSize;
use embedder_traits::{
- AnimationState, CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent,
- ShutdownState, TouchEventType, UntrustedNodeAddress, ViewportDetails,
+ CompositorHitTestResult, Cursor, InputEvent, MouseButtonEvent, MouseMoveEvent, ShutdownState,
+ TouchEventType, UntrustedNodeAddress, ViewportDetails,
};
use euclid::{Point2D, Rect, Scale, Size2D, Transform3D};
use fnv::FnvHashMap;
@@ -197,9 +197,6 @@ pub(crate) struct PipelineDetails {
/// The pipeline associated with this PipelineDetails object.
pub pipeline: Option<CompositionPipeline>,
- /// The [`PipelineId`] of this pipeline.
- pub id: PipelineId,
-
/// The id of the parent pipeline, if any.
pub parent_pipeline_id: Option<PipelineId>,
@@ -243,32 +240,12 @@ impl PipelineDetails {
pub(crate) fn animating(&self) -> bool {
!self.throttled && (self.animation_callbacks_running || self.animations_running)
}
-
- pub(crate) fn tick_animations(&self, compositor: &IOCompositor) {
- if !self.animating() {
- return;
- }
-
- let mut tick_type = AnimationTickType::empty();
- if self.animations_running {
- tick_type.insert(AnimationTickType::CSS_ANIMATIONS_AND_TRANSITIONS);
- }
- if self.animation_callbacks_running {
- tick_type.insert(AnimationTickType::REQUEST_ANIMATION_FRAME);
- }
-
- let msg = EmbedderToConstellationMessage::TickAnimation(self.id, tick_type);
- if let Err(e) = compositor.global.borrow().constellation_sender.send(msg) {
- warn!("Sending tick to constellation failed ({:?}).", e);
- }
- }
}
impl PipelineDetails {
- pub(crate) fn new(id: PipelineId) -> PipelineDetails {
+ pub(crate) fn new() -> PipelineDetails {
PipelineDetails {
pipeline: None,
- id,
parent_pipeline_id: None,
most_recent_display_list_epoch: None,
animations_running: false,
@@ -543,22 +520,14 @@ impl IOCompositor {
pipeline_id,
animation_state,
) => {
- let mut throttled = true;
if let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) {
- throttled = webview_renderer
- .change_running_animations_state(pipeline_id, animation_state);
- }
-
- // These operations should eventually happen per-WebView, but they are global now as rendering
- // is still global to all WebViews.
- if !throttled && animation_state == AnimationState::AnimationsPresent {
- self.set_needs_repaint(RepaintReason::ChangedAnimationState);
- }
-
- if !throttled && animation_state == AnimationState::AnimationCallbacksPresent {
- // We need to fetch the WebView again in order to avoid a double borrow.
- if let Some(webview_renderer) = self.webview_renderers.get(webview_id) {
- webview_renderer.tick_animations_for_pipeline(pipeline_id, self);
+ if webview_renderer
+ .change_pipeline_running_animations_state(pipeline_id, animation_state) &&
+ webview_renderer.animating()
+ {
+ // These operations should eventually happen per-WebView, but they are
+ // global now as rendering is still global to all WebViews.
+ self.process_animations(true);
}
}
},
@@ -605,8 +574,13 @@ impl IOCompositor {
CompositorMsg::SetThrottled(webview_id, pipeline_id, throttled) => {
if let Some(webview_renderer) = self.webview_renderers.get_mut(webview_id) {
- webview_renderer.set_throttled(pipeline_id, throttled);
- self.process_animations(true);
+ if webview_renderer.set_throttled(pipeline_id, throttled) &&
+ webview_renderer.animating()
+ {
+ // These operations should eventually happen per-WebView, but they are
+ // global now as rendering is still global to all WebViews.
+ self.process_animations(true);
+ }
}
},
@@ -1283,8 +1257,23 @@ impl IOCompositor {
}
self.last_animation_tick = Instant::now();
- for webview_renderer in self.webview_renderers.iter() {
- webview_renderer.tick_all_animations(self);
+ let animating_webviews: Vec<_> = self
+ .webview_renderers
+ .iter()
+ .filter_map(|webview_renderer| {
+ if webview_renderer.animating() {
+ Some(webview_renderer.id)
+ } else {
+ None
+ }
+ })
+ .collect();
+ if !animating_webviews.is_empty() {
+ if let Err(error) = self.global.borrow().constellation_sender.send(
+ EmbedderToConstellationMessage::TickAnimation(animating_webviews),
+ ) {
+ warn!("Sending tick to constellation failed ({error:?}).");
+ }
}
}
diff --git a/components/compositing/webview_renderer.rs b/components/compositing/webview_renderer.rs
index 6ad77d46043..614ef0ff4c3 100644
--- a/components/compositing/webview_renderer.rs
+++ b/components/compositing/webview_renderer.rs
@@ -86,6 +86,9 @@ pub(crate) struct WebViewRenderer {
/// The HiDPI scale factor for the `WebView` associated with this renderer. This is controlled
/// by the embedding layer.
hidpi_scale_factor: Scale<f32, DeviceIndependentPixel, DevicePixel>,
+ /// Whether or not this [`WebViewRenderer`] isn't throttled and has a pipeline with
+ /// active animations or animation frame callbacks.
+ animating: bool,
}
impl Drop for WebViewRenderer {
@@ -119,6 +122,7 @@ impl WebViewRenderer {
min_viewport_zoom: Some(PinchZoomFactor::new(1.0)),
max_viewport_zoom: None,
hidpi_scale_factor: Scale::new(hidpi_scale_factor.0),
+ animating: false,
}
}
@@ -138,6 +142,10 @@ impl WebViewRenderer {
self.pipelines.keys()
}
+ pub(crate) fn animating(&self) -> bool {
+ self.animating
+ }
+
/// Returns the [`PipelineDetails`] for the given [`PipelineId`], creating it if needed.
pub(crate) fn ensure_pipeline_details(
&mut self,
@@ -148,14 +156,10 @@ impl WebViewRenderer {
.borrow_mut()
.pipeline_to_webview_map
.insert(pipeline_id, self.id);
- PipelineDetails::new(pipeline_id)
+ PipelineDetails::new()
})
}
- pub(crate) fn set_throttled(&mut self, pipeline_id: PipelineId, throttled: bool) {
- self.ensure_pipeline_details(pipeline_id).throttled = throttled;
- }
-
pub(crate) fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
self.global
.borrow_mut()
@@ -245,51 +249,45 @@ impl WebViewRenderer {
})
}
- /// Sets or unsets the animations-running flag for the given pipeline. Returns true if
- /// the pipeline is throttled.
- pub(crate) fn change_running_animations_state(
+ /// Sets or unsets the animations-running flag for the given pipeline. Returns
+ /// true if the [`WebViewRenderer`]'s overall animating state changed.
+ pub(crate) fn change_pipeline_running_animations_state(
&mut self,
pipeline_id: PipelineId,
animation_state: AnimationState,
) -> bool {
- let throttled = {
- let pipeline_details = self.ensure_pipeline_details(pipeline_id);
- match animation_state {
- AnimationState::AnimationsPresent => {
- pipeline_details.animations_running = true;
- },
- AnimationState::AnimationCallbacksPresent => {
- pipeline_details.animation_callbacks_running = true;
- },
- AnimationState::NoAnimationsPresent => {
- pipeline_details.animations_running = false;
- },
- AnimationState::NoAnimationCallbacksPresent => {
- pipeline_details.animation_callbacks_running = false;
- },
- }
- pipeline_details.throttled
- };
-
- let animating = self.pipelines.values().any(PipelineDetails::animating);
- self.webview.set_animating(animating);
- throttled
+ let pipeline_details = self.ensure_pipeline_details(pipeline_id);
+ match animation_state {
+ AnimationState::AnimationsPresent => {
+ pipeline_details.animations_running = true;
+ },
+ AnimationState::AnimationCallbacksPresent => {
+ pipeline_details.animation_callbacks_running = true;
+ },
+ AnimationState::NoAnimationsPresent => {
+ pipeline_details.animations_running = false;
+ },
+ AnimationState::NoAnimationCallbacksPresent => {
+ pipeline_details.animation_callbacks_running = false;
+ },
+ }
+ self.update_animation_state()
}
- pub(crate) fn tick_all_animations(&self, compositor: &IOCompositor) {
- for pipeline_details in self.pipelines.values() {
- pipeline_details.tick_animations(compositor)
- }
+ /// Sets or unsets the throttled flag for the given pipeline. Returns
+ /// true if the [`WebViewRenderer`]'s overall animating state changed.
+ pub(crate) fn set_throttled(&mut self, pipeline_id: PipelineId, throttled: bool) -> bool {
+ self.ensure_pipeline_details(pipeline_id).throttled = throttled;
+
+ // Throttling a pipeline can cause it to be taken into the "not-animating" state.
+ self.update_animation_state()
}
- pub(crate) fn tick_animations_for_pipeline(
- &self,
- pipeline_id: PipelineId,
- compositor: &IOCompositor,
- ) {
- if let Some(pipeline_details) = self.pipelines.get(&pipeline_id) {
- pipeline_details.tick_animations(compositor);
- }
+ pub(crate) fn update_animation_state(&mut self) -> bool {
+ let animating = self.pipelines.values().any(PipelineDetails::animating);
+ let old_animating = std::mem::replace(&mut self.animating, animating);
+ self.webview.set_animating(self.animating);
+ old_animating != self.animating
}
/// On a Window refresh tick (e.g. vsync)
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 3f70b0abb89..05081fe0ba7 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -112,13 +112,12 @@ use compositing_traits::{
CompositorMsg, CompositorProxy, SendableFrameTree, WebrenderExternalImageRegistry,
};
use constellation_traits::{
- AnimationTickType, AuxiliaryWebViewCreationRequest, AuxiliaryWebViewCreationResponse,
- BroadcastMsg, DocumentState, EmbedderToConstellationMessage, IFrameLoadInfo,
- IFrameLoadInfoWithData, IFrameSandboxState, IFrameSizeMsg, Job, LoadData, LoadOrigin, LogEntry,
- MessagePortMsg, NavigationHistoryBehavior, PaintMetricEvent, PortMessageTask, SWManagerMsg,
- SWManagerSenders, ScriptToConstellationChan, ScriptToConstellationMessage, ScrollState,
- ServiceWorkerManagerFactory, ServiceWorkerMsg, StructuredSerializedData, TraversalDirection,
- WindowSizeType,
+ AuxiliaryWebViewCreationRequest, AuxiliaryWebViewCreationResponse, BroadcastMsg, DocumentState,
+ EmbedderToConstellationMessage, IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState,
+ IFrameSizeMsg, Job, LoadData, LoadOrigin, LogEntry, MessagePortMsg, NavigationHistoryBehavior,
+ PaintMetricEvent, PortMessageTask, SWManagerMsg, SWManagerSenders, ScriptToConstellationChan,
+ ScriptToConstellationMessage, ScrollState, ServiceWorkerManagerFactory, ServiceWorkerMsg,
+ StructuredSerializedData, TraversalDirection, WindowSizeType,
};
use crossbeam_channel::{Receiver, Select, Sender, unbounded};
use devtools_traits::{
@@ -1398,8 +1397,8 @@ where
EmbedderToConstellationMessage::ThemeChange(theme) => {
self.handle_theme_change(theme);
},
- EmbedderToConstellationMessage::TickAnimation(pipeline_id, tick_type) => {
- self.handle_tick_animation(pipeline_id, tick_type)
+ EmbedderToConstellationMessage::TickAnimation(webview_ids) => {
+ self.handle_tick_animation(webview_ids)
},
EmbedderToConstellationMessage::WebDriverCommand(command) => {
self.handle_webdriver_msg(command);
@@ -3528,15 +3527,24 @@ where
feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)]
- fn handle_tick_animation(&mut self, pipeline_id: PipelineId, tick_type: AnimationTickType) {
- let pipeline = match self.pipelines.get(&pipeline_id) {
- Some(pipeline) => pipeline,
- None => return warn!("{}: Got script tick after closure", pipeline_id),
- };
+ fn handle_tick_animation(&mut self, webview_ids: Vec<WebViewId>) {
+ let mut animating_event_loops = HashSet::new();
- let message = ScriptThreadMessage::TickAllAnimations(pipeline_id, tick_type);
- if let Err(e) = pipeline.event_loop.send(message) {
- self.handle_send_error(pipeline_id, e);
+ for webview_id in webview_ids.iter() {
+ for browsing_context in self.fully_active_browsing_contexts_iter(*webview_id) {
+ let Some(pipeline) = self.pipelines.get(&browsing_context.pipeline_id) else {
+ continue;
+ };
+ animating_event_loops.insert(pipeline.event_loop.clone());
+ }
+ }
+
+ for event_loop in animating_event_loops {
+ // No error handling here. It's unclear what to do when this fails as the error isn't associated
+ // with a particular pipeline. In addition, the danger of not progressing animations is pretty
+ // low, so it's probably safe to ignore this error and handle the crashed ScriptThread on
+ // some other message.
+ let _ = event_loop.send(ScriptThreadMessage::TickAllAnimations(webview_ids.clone()));
}
}
diff --git a/components/constellation/event_loop.rs b/components/constellation/event_loop.rs
index 362960eba64..46542e7212f 100644
--- a/components/constellation/event_loop.rs
+++ b/components/constellation/event_loop.rs
@@ -6,17 +6,36 @@
//! view of a script thread. When an `EventLoop` is dropped, an `ExitScriptThread`
//! message is sent to the script thread, asking it to shut down.
+use std::hash::Hash;
use std::marker::PhantomData;
use std::rc::Rc;
+use std::sync::atomic::{AtomicUsize, Ordering};
use ipc_channel::Error;
use ipc_channel::ipc::IpcSender;
use script_traits::ScriptThreadMessage;
+static CURRENT_EVENT_LOOP_ID: AtomicUsize = AtomicUsize::new(0);
+
/// <https://html.spec.whatwg.org/multipage/#event-loop>
pub struct EventLoop {
script_chan: IpcSender<ScriptThreadMessage>,
dont_send_or_sync: PhantomData<Rc<()>>,
+ id: usize,
+}
+
+impl PartialEq for EventLoop {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
+ }
+}
+
+impl Eq for EventLoop {}
+
+impl Hash for EventLoop {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.id.hash(state);
+ }
}
impl Drop for EventLoop {
@@ -28,9 +47,11 @@ impl Drop for EventLoop {
impl EventLoop {
/// Create a new event loop from the channel to its script thread.
pub fn new(script_chan: IpcSender<ScriptThreadMessage>) -> Rc<EventLoop> {
+ let id = CURRENT_EVENT_LOOP_ID.fetch_add(1, Ordering::Relaxed);
Rc::new(EventLoop {
script_chan,
dont_send_or_sync: PhantomData,
+ id,
})
}
diff --git a/components/devtools/actors/source.rs b/components/devtools/actors/source.rs
new file mode 100644
index 00000000000..9d29bc1d3ef
--- /dev/null
+++ b/components/devtools/actors/source.rs
@@ -0,0 +1,50 @@
+/* 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::{Ref, RefCell};
+use std::collections::BTreeSet;
+
+use serde::Serialize;
+use servo_url::ServoUrl;
+
+#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct SourceData {
+ pub actor: String,
+ /// URL of the script, or URL of the page for inline scripts.
+ pub url: String,
+ pub is_black_boxed: bool,
+}
+
+#[derive(Serialize)]
+pub(crate) struct SourcesReply {
+ pub from: String,
+ pub sources: Vec<SourceData>,
+}
+
+pub(crate) struct Source {
+ actor_name: String,
+ source_urls: RefCell<BTreeSet<SourceData>>,
+}
+
+impl Source {
+ pub fn new(actor_name: String) -> Self {
+ Self {
+ actor_name,
+ source_urls: RefCell::new(BTreeSet::default()),
+ }
+ }
+
+ pub fn add_source(&self, url: ServoUrl) {
+ self.source_urls.borrow_mut().insert(SourceData {
+ actor: self.actor_name.clone(),
+ url: url.to_string(),
+ is_black_boxed: false,
+ });
+ }
+
+ pub fn sources(&self) -> Ref<BTreeSet<SourceData>> {
+ self.source_urls.borrow()
+ }
+}
diff --git a/components/devtools/actors/thread.rs b/components/devtools/actors/thread.rs
index 85ff2b732eb..7ff11dff675 100644
--- a/components/devtools/actors/thread.rs
+++ b/components/devtools/actors/thread.rs
@@ -2,14 +2,12 @@
* 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::{Ref, RefCell};
-use std::collections::BTreeSet;
use std::net::TcpStream;
use serde::Serialize;
use serde_json::{Map, Value};
-use servo_url::ServoUrl;
+use super::source::{Source, SourcesReply};
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use crate::{EmptyReplyMsg, StreamId};
@@ -52,45 +50,18 @@ struct ThreadInterruptedReply {
type_: String,
}
-#[derive(Serialize)]
-struct SourcesReply {
- from: String,
- sources: Vec<Source>,
-}
-
-#[derive(Eq, Ord, PartialEq, PartialOrd, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Source {
- pub actor: String,
- /// URL of the script, or URL of the page for inline scripts.
- pub url: String,
- pub is_black_boxed: bool,
-}
-
pub struct ThreadActor {
- name: String,
- source_urls: RefCell<BTreeSet<Source>>,
+ pub name: String,
+ pub source_manager: Source,
}
impl ThreadActor {
pub fn new(name: String) -> ThreadActor {
ThreadActor {
- name,
- source_urls: RefCell::new(BTreeSet::default()),
+ name: name.clone(),
+ source_manager: Source::new(name),
}
}
-
- pub fn add_source(&self, url: ServoUrl) {
- self.source_urls.borrow_mut().insert(Source {
- actor: self.name.clone(),
- url: url.to_string(),
- is_black_boxed: false,
- });
- }
-
- pub fn sources(&self) -> Ref<BTreeSet<Source>> {
- self.source_urls.borrow()
- }
}
impl Actor for ThreadActor {
diff --git a/components/devtools/actors/watcher.rs b/components/devtools/actors/watcher.rs
index d48374fc523..6a84499b6dd 100644
--- a/components/devtools/actors/watcher.rs
+++ b/components/devtools/actors/watcher.rs
@@ -265,7 +265,7 @@ impl Actor for WatcherActor {
},
"source" => {
let thread_actor = registry.find::<ThreadActor>(&target.thread);
- let sources = thread_actor.sources();
+ let sources = thread_actor.source_manager.sources();
target.resources_available(sources.iter().collect(), "source".into());
},
"console-message" | "error-message" => {},
diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs
index d4c3095b025..4d1e0222177 100644
--- a/components/devtools/lib.rs
+++ b/components/devtools/lib.rs
@@ -19,7 +19,7 @@ use std::net::{Shutdown, TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
-use actors::thread::Source;
+use actors::source::SourceData;
use base::id::{BrowsingContextId, PipelineId, WebViewId};
use crossbeam_channel::{Receiver, Sender, unbounded};
use devtools_traits::{
@@ -66,6 +66,7 @@ mod actors {
pub mod process;
pub mod reflow;
pub mod root;
+ pub mod source;
pub mod stylesheets;
pub mod tab;
pub mod thread;
@@ -525,9 +526,11 @@ impl DevtoolsInstance {
.clone();
let thread_actor = actors.find_mut::<ThreadActor>(&thread_actor_name);
- thread_actor.add_source(source_info.url.clone());
+ thread_actor
+ .source_manager
+ .add_source(source_info.url.clone());
- let source = Source {
+ let source = SourceData {
actor: thread_actor_name.clone(),
url: source_info.url.to_string(),
is_black_boxed: false,
diff --git a/components/layout/dom.rs b/components/layout/dom.rs
index 6db4dbccd41..a81a6eec545 100644
--- a/components/layout/dom.rs
+++ b/components/layout/dom.rs
@@ -2,18 +2,21 @@
* 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::any::Any;
use std::marker::PhantomData;
use std::sync::Arc;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use base::id::{BrowsingContextId, PipelineId};
use html5ever::{local_name, ns};
+use malloc_size_of_derive::MallocSizeOf;
use pixels::Image;
use script_layout_interface::wrapper_traits::{
LayoutDataTrait, LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
use script_layout_interface::{
- HTMLCanvasDataSource, LayoutElementType, LayoutNodeType as ScriptLayoutNodeType,
+ GenericLayoutDataTrait, HTMLCanvasDataSource, LayoutElementType,
+ LayoutNodeType as ScriptLayoutNodeType,
};
use servo_arc::Arc as ServoArc;
use style::properties::ComputedValues;
@@ -31,7 +34,7 @@ use crate::table::TableLevelBox;
use crate::taffy::TaffyItemBox;
/// The data that is stored in each DOM node that is used by layout.
-#[derive(Default)]
+#[derive(Default, MallocSizeOf)]
pub struct InnerDOMLayoutData {
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
@@ -54,6 +57,7 @@ impl InnerDOMLayoutData {
}
/// A box that is stored in one of the `DOMLayoutData` slots.
+#[derive(MallocSizeOf)]
pub(super) enum LayoutBox {
DisplayContents,
BlockLevel(ArcRefCell<BlockLevelBox>),
@@ -98,11 +102,16 @@ impl LayoutBox {
/// A wrapper for [`InnerDOMLayoutData`]. This is necessary to give the entire data
/// structure interior mutability, as we will need to mutate the layout data of
/// non-mutable DOM nodes.
-#[derive(Default)]
+#[derive(Default, MallocSizeOf)]
pub struct DOMLayoutData(AtomicRefCell<InnerDOMLayoutData>);
// The implementation of this trait allows the data to be stored in the DOM.
impl LayoutDataTrait for DOMLayoutData {}
+impl GenericLayoutDataTrait for DOMLayoutData {
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
pub struct BoxSlot<'dom> {
pub(crate) slot: Option<ArcRefCell<Option<LayoutBox>>>,
@@ -255,6 +264,7 @@ where
}
LayoutNode::layout_data(&self)
.unwrap()
+ .as_any()
.downcast_ref::<DOMLayoutData>()
.unwrap()
.0
@@ -262,8 +272,13 @@ where
}
fn layout_data(self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
- LayoutNode::layout_data(&self)
- .map(|data| data.downcast_ref::<DOMLayoutData>().unwrap().0.borrow())
+ LayoutNode::layout_data(&self).map(|data| {
+ data.as_any()
+ .downcast_ref::<DOMLayoutData>()
+ .unwrap()
+ .0
+ .borrow()
+ })
}
fn element_box_slot(&self) -> BoxSlot<'dom> {
diff --git a/components/layout/table/mod.rs b/components/layout/table/mod.rs
index 120270fc7cf..fe7f90437b8 100644
--- a/components/layout/table/mod.rs
+++ b/components/layout/table/mod.rs
@@ -346,6 +346,7 @@ pub(crate) struct TableLayoutStyle<'a> {
/// Table parts that are stored in the DOM. This is used in order to map from
/// the DOM to the box tree and will eventually be important for incremental
/// layout.
+#[derive(MallocSizeOf)]
pub(crate) enum TableLevelBox {
Caption(ArcRefCell<TableCaption>),
Cell(ArcRefCell<TableSlotCell>),
diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs
index b7f677f8044..52523af7cb1 100644
--- a/components/malloc_size_of/lib.rs
+++ b/components/malloc_size_of/lib.rs
@@ -746,6 +746,7 @@ malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
malloc_size_of_is_0!(std::time::Duration);
malloc_size_of_is_0!(std::time::Instant);
malloc_size_of_is_0!(std::time::SystemTime);
+malloc_size_of_is_0!(style::data::ElementData);
malloc_size_of_is_0!(style::font_face::SourceList);
malloc_size_of_is_0!(style::properties::ComputedValues);
malloc_size_of_is_0!(style::queries::values::PrefersColorScheme);
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 852a12fc7c5..02bdd343d89 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -21,9 +21,7 @@ use base::id::WebViewId;
use canvas_traits::canvas::CanvasId;
use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
use chrono::Local;
-use constellation_traits::{
- AnimationTickType, NavigationHistoryBehavior, ScriptToConstellationMessage,
-};
+use constellation_traits::{NavigationHistoryBehavior, ScriptToConstellationMessage};
use content_security_policy::{self as csp, CspList, PolicyDisposition};
use cookie::Cookie;
use cssparser::match_ignore_ascii_case;
@@ -516,10 +514,6 @@ pub(crate) struct Document {
pending_input_events: DomRefCell<Vec<ConstellationInputEvent>>,
/// The index of the last mouse move event in the pending compositor events queue.
mouse_move_event_index: DomRefCell<Option<usize>>,
- /// Pending animation ticks, to be handled at the next rendering opportunity.
- #[no_trace]
- #[ignore_malloc_size_of = "AnimationTickType contains data from an outside crate"]
- pending_animation_ticks: DomRefCell<AnimationTickType>,
/// <https://drafts.csswg.org/resize-observer/#dom-document-resizeobservers-slot>
///
/// Note: we are storing, but never removing, resize observers.
@@ -2397,10 +2391,6 @@ impl Document {
pub(crate) fn run_the_animation_frame_callbacks(&self, can_gc: CanGc) {
let _realm = enter_realm(self);
- self.pending_animation_ticks
- .borrow_mut()
- .remove(AnimationTickType::REQUEST_ANIMATION_FRAME);
-
self.running_animation_callbacks.set(true);
let was_faking_animation_frames = self.is_faking_animation_frames();
let timing = self.global().performance().Now();
@@ -3916,7 +3906,6 @@ impl Document {
image_animation_manager: DomRefCell::new(ImageAnimationManager::new()),
dirty_root: Default::default(),
declarative_refresh: Default::default(),
- pending_animation_ticks: Default::default(),
pending_input_events: Default::default(),
mouse_move_event_index: Default::default(),
resize_observers: Default::default(),
@@ -4689,18 +4678,6 @@ impl Document {
.collect()
}
- /// Note a pending animation tick, to be processed at the next `update_the_rendering` task.
- pub(crate) fn note_pending_animation_tick(&self, tick_type: AnimationTickType) {
- self.pending_animation_ticks.borrow_mut().extend(tick_type);
- }
-
- /// Whether this document has received an animation tick for rafs.
- pub(crate) fn has_received_raf_tick(&self) -> bool {
- self.pending_animation_ticks
- .borrow()
- .contains(AnimationTickType::REQUEST_ANIMATION_FRAME)
- }
-
pub(crate) fn advance_animation_timeline_for_testing(&self, delta: f64) {
self.animation_timeline.borrow_mut().advance_specific(delta);
let current_timeline_value = self.current_animation_timeline_value();
@@ -6437,10 +6414,7 @@ impl FakeRequestAnimationFrameCallback {
pub(crate) fn invoke(self, can_gc: CanGc) {
// TODO: Once there is a more generic mechanism to trigger `update_the_rendering` when
// not driven by the compositor, it should be used here.
- self.document
- .root()
- .note_pending_animation_tick(AnimationTickType::REQUEST_ANIMATION_FRAME);
- with_script_thread(|script_thread| script_thread.update_the_rendering(false, can_gc))
+ with_script_thread(|script_thread| script_thread.update_the_rendering(true, can_gc))
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 2a01370085a..45a107ae673 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -167,7 +167,6 @@ pub struct Node {
/// Layout data for this node. This is populated during layout and can
/// be used for incremental relayout and script queries.
- #[ignore_malloc_size_of = "trait object"]
#[no_trace]
layout_data: DomRefCell<Option<Box<GenericLayoutData>>>,
}
diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs
index 7fd23804ffd..df542b4b759 100644
--- a/components/script/layout_image.rs
+++ b/components/script/layout_image.rs
@@ -119,7 +119,10 @@ pub(crate) fn fetch_image_for_layout(
)
.origin(document.origin().immutable().clone())
.destination(Destination::Image)
- .pipeline_id(Some(document.global().pipeline_id()));
+ .pipeline_id(Some(document.global().pipeline_id()))
+ .insecure_requests_policy(document.insecure_requests_policy())
+ .has_trustworthy_ancestor_origin(document.has_trustworthy_ancestor_origin())
+ .policy_container(document.policy_container().to_owned());
// Layout image loads do not delay the document load event.
document.fetch_background(request, context);
diff --git a/components/script/messaging.rs b/components/script/messaging.rs
index 808b338e709..7d0b7aabe05 100644
--- a/components/script/messaging.rs
+++ b/components/script/messaging.rs
@@ -73,7 +73,7 @@ impl MixedMessage {
ScriptThreadMessage::RemoveHistoryStates(id, ..) => Some(*id),
ScriptThreadMessage::FocusIFrame(id, ..) => Some(*id),
ScriptThreadMessage::WebDriverScriptCommand(id, ..) => Some(*id),
- ScriptThreadMessage::TickAllAnimations(id, ..) => Some(*id),
+ ScriptThreadMessage::TickAllAnimations(..) => None,
ScriptThreadMessage::WebFontLoaded(id, ..) => Some(*id),
ScriptThreadMessage::DispatchIFrameLoadEvent {
target: _,
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index c9b27bb6c56..07310073949 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -1147,14 +1147,6 @@ impl ScriptThread {
return;
}
- // Run rafs for all pipeline, if a raf tick was received for any.
- // This ensures relative ordering of rafs between parent doc and iframes.
- let should_run_rafs = self
- .documents
- .borrow()
- .iter()
- .any(|(_, doc)| doc.is_fully_active() && doc.has_received_raf_tick());
-
let any_animations_running = self.documents.borrow().iter().any(|(_, document)| {
document.is_fully_active() && document.animations().running_animation_count() != 0
});
@@ -1242,7 +1234,7 @@ impl ScriptThread {
// > 14. For each doc of docs, run the animation frame callbacks for doc, passing
// > in the relative high resolution time given frameTimestamp and doc's
// > relevant global object as the timestamp.
- if should_run_rafs {
+ if requested_by_compositor {
document.run_the_animation_frame_callbacks(can_gc);
}
@@ -1421,18 +1413,9 @@ impl ScriptThread {
self.handle_viewport(id, rect);
}),
MixedMessage::FromConstellation(ScriptThreadMessage::TickAllAnimations(
- pipeline_id,
- tick_type,
+ _webviews,
)) => {
- if let Some(document) = self.documents.borrow().find_document(pipeline_id) {
- document.note_pending_animation_tick(tick_type);
- compositor_requested_update_the_rendering = true;
- } else {
- warn!(
- "Trying to note pending animation tick for closed pipeline {}.",
- pipeline_id
- )
- }
+ compositor_requested_update_the_rendering = true;
},
MixedMessage::FromConstellation(ScriptThreadMessage::SendInputEvent(id, event)) => {
self.handle_input_event(id, event)
@@ -2439,8 +2422,6 @@ impl ScriptThread {
let mut reports = vec![];
perform_memory_report(|ops| {
- let prefix = format!("url({urls})");
- reports.extend(self.get_cx().get_reports(prefix.clone(), ops));
for (_, document) in documents.iter() {
document
.window()
@@ -2448,6 +2429,9 @@ impl ScriptThread {
.collect_reports(&mut reports, ops);
}
+ let prefix = format!("url({urls})");
+ reports.extend(self.get_cx().get_reports(prefix.clone(), ops));
+
reports.push(self.image_cache.memory_report(&prefix, ops));
});
diff --git a/components/shared/constellation/lib.rs b/components/shared/constellation/lib.rs
index 548e17b532c..b3d4fe525a1 100644
--- a/components/shared/constellation/lib.rs
+++ b/components/shared/constellation/lib.rs
@@ -18,7 +18,6 @@ use std::time::Duration;
use base::Epoch;
use base::cross_process_instant::CrossProcessInstant;
use base::id::{MessagePortId, PipelineId, WebViewId};
-use bitflags::bitflags;
use embedder_traits::{
CompositorHitTestResult, Cursor, InputEvent, MediaSessionActionType, Theme, ViewportDetails,
WebDriverCommandMsg,
@@ -57,8 +56,9 @@ pub enum EmbedderToConstellationMessage {
ChangeViewportDetails(WebViewId, ViewportDetails, WindowSizeType),
/// Inform the constellation of a theme change.
ThemeChange(Theme),
- /// Requests that the constellation instruct layout to begin a new tick of the animation.
- TickAnimation(PipelineId, AnimationTickType),
+ /// Requests that the constellation instruct script/layout to try to layout again and tick
+ /// animations.
+ TickAnimation(Vec<WebViewId>),
/// Dispatch a webdriver command
WebDriverCommand(WebDriverCommandMsg),
/// Reload a top-level browsing context.
@@ -130,17 +130,6 @@ pub enum WindowSizeType {
Resize,
}
-bitflags! {
- #[derive(Debug, Default, Deserialize, Serialize)]
- /// Specifies if rAF should be triggered and/or CSS Animations and Transitions.
- pub struct AnimationTickType: u8 {
- /// Trigger a call to requestAnimationFrame.
- const REQUEST_ANIMATION_FRAME = 0b001;
- /// Trigger restyles for CSS Animations and Transitions.
- const CSS_ANIMATIONS_AND_TRANSITIONS = 0b010;
- }
-}
-
/// The scroll state of a stacking context.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ScrollState {
diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs
index a39be739fd5..7323907cba3 100644
--- a/components/shared/script/lib.rs
+++ b/components/shared/script/lib.rs
@@ -20,7 +20,7 @@ use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline;
use compositing_traits::CrossProcessCompositorApi;
use constellation_traits::{
- AnimationTickType, LoadData, NavigationHistoryBehavior, ScriptToConstellationChan, ScrollState,
+ LoadData, NavigationHistoryBehavior, ScriptToConstellationChan, ScrollState,
StructuredSerializedData, WindowSizeType,
};
use crossbeam_channel::{RecvTimeoutError, Sender};
@@ -195,7 +195,7 @@ pub enum ScriptThreadMessage {
/// Passes a webdriver command to the script thread for execution
WebDriverScriptCommand(PipelineId, WebDriverScriptCommand),
/// Notifies script thread that all animations are done
- TickAllAnimations(PipelineId, AnimationTickType),
+ TickAllAnimations(Vec<WebViewId>),
/// Notifies the script thread that a new Web font has been loaded, and thus the page should be
/// reflowed.
WebFontLoaded(PipelineId, bool /* success */),
diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs
index 69e577e139d..233d02dfd47 100644
--- a/components/shared/script_layout/lib.rs
+++ b/components/shared/script_layout/lib.rs
@@ -27,7 +27,7 @@ use fonts::{FontContext, SystemFontServiceProxy};
use fxhash::FxHashMap;
use ipc_channel::ipc::IpcSender;
use libc::c_void;
-use malloc_size_of::MallocSizeOfOps;
+use malloc_size_of::{MallocSizeOf as MallocSizeOfTrait, MallocSizeOfOps};
use malloc_size_of_derive::MallocSizeOf;
use net_traits::image_cache::{ImageCache, PendingImageId};
use pixels::Image;
@@ -51,7 +51,11 @@ use style::selector_parser::{PseudoElement, RestyleDamage, Snapshot};
use style::stylesheets::Stylesheet;
use webrender_api::ImageKey;
-pub type GenericLayoutData = dyn Any + Send + Sync;
+pub trait GenericLayoutDataTrait: Any + MallocSizeOfTrait {
+ fn as_any(&self) -> &dyn Any;
+}
+
+pub type GenericLayoutData = dyn GenericLayoutDataTrait + Send + Sync;
#[derive(MallocSizeOf)]
pub struct StyleData {
@@ -59,7 +63,6 @@ pub struct StyleData {
/// style system is being used standalone, this is all that hangs
/// off the node. This must be first to permit the various
/// transmutations between ElementData and PersistentLayoutData.
- #[ignore_malloc_size_of = "This probably should not be ignored"]
pub element_data: AtomicRefCell<ElementData>,
/// Information needed during parallel traversals.
diff --git a/components/shared/script_layout/wrapper_traits.rs b/components/shared/script_layout/wrapper_traits.rs
index be27050a42f..6c4de339c1b 100644
--- a/components/shared/script_layout/wrapper_traits.rs
+++ b/components/shared/script_layout/wrapper_traits.rs
@@ -25,11 +25,11 @@ use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorIm
use style::stylist::RuleInclusion;
use crate::{
- FragmentType, GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGSVGData,
- StyleData,
+ FragmentType, GenericLayoutData, GenericLayoutDataTrait, HTMLCanvasData, HTMLMediaData,
+ LayoutNodeType, SVGSVGData, StyleData,
};
-pub trait LayoutDataTrait: Default + Send + Sync + 'static {}
+pub trait LayoutDataTrait: GenericLayoutDataTrait + Default + Send + Sync + 'static {}
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
/// only ever see these and must never see instances of `LayoutDom`.