script: Have Document own Layout (#32316)

Have `Document` own `Layout`. This makes it impossible to have a
`Document` without `Layout`, which was true, but now the compiler checks
it. In addition, `Layout` is now released when the `Document` is,
avoiding leaking the entire `Layout`.
This commit is contained in:
Martin Robinson 2024-05-20 15:04:32 +02:00 committed by GitHub
parent 2af6fe0b30
commit 53c0726ef4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 88 additions and 133 deletions

View file

@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::borrow::{Cow, ToOwned};
use std::cell::Cell;
use std::cell::{Cell, RefCell, RefMut};
use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet};
use std::default::Default;
@ -193,6 +193,9 @@ pub struct Window {
#[ignore_malloc_size_of = "trait objects are hard"]
script_chan: MainThreadScriptChan,
task_manager: TaskManager,
#[no_trace]
#[ignore_malloc_size_of = "TODO: Add MallocSizeOf support to layout"]
layout: RefCell<Box<dyn Layout>>,
navigator: MutNullableDom<Navigator>,
#[ignore_malloc_size_of = "Arc"]
#[no_trace]
@ -365,6 +368,14 @@ impl Window {
&self.task_manager
}
pub fn layout(&self) -> Ref<Box<dyn Layout>> {
self.layout.borrow()
}
pub fn layout_mut(&self) -> RefMut<Box<dyn Layout>> {
self.layout.borrow_mut()
}
pub fn get_exists_mut_observer(&self) -> bool {
self.exists_mut_observer.get()
}
@ -1877,7 +1888,7 @@ impl Window {
animations: document.animations().sets.clone(),
};
let _ = self.with_layout(move |layout| layout.reflow(reflow));
self.layout.borrow_mut().reflow(reflow);
let complete = match join_port.try_recv() {
Err(TryRecvError::Empty) => {
@ -1988,10 +1999,7 @@ impl Window {
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive)
});
let pending_web_fonts = self
.with_layout(move |layout| layout.waiting_for_web_fonts_to_load())
.unwrap();
let pending_web_fonts = self.layout.borrow().waiting_for_web_fonts_to_load();
let has_sent_idle_message = self.has_sent_idle_message.get();
let is_ready_state_complete = document.ReadyState() == DocumentReadyState::Complete;
let pending_images = !self.pending_layout_images.borrow().is_empty();
@ -2022,10 +2030,7 @@ impl Window {
return;
}
let epoch = self
.with_layout(move |layout| layout.current_epoch())
.unwrap();
let epoch = self.layout.borrow().current_epoch();
debug!(
"{:?}: Updating constellation epoch: {epoch:?}",
self.pipeline_id()
@ -2049,39 +2054,34 @@ impl Window {
}
let document = self.Document();
self.with_layout(|layout| {
layout.query_resolved_font_style(
node.to_trusted_node_address(),
&value,
document.animations().sets.clone(),
document.current_animation_timeline_value(),
)
})
.unwrap()
let animations = document.animations().sets.clone();
self.layout.borrow().query_resolved_font_style(
node.to_trusted_node_address(),
&value,
animations,
document.current_animation_timeline_value(),
)
}
pub fn content_box_query(&self, node: &Node) -> Option<UntypedRect<Au>> {
if !self.layout_reflow(QueryMsg::ContentBox) {
return None;
}
self.with_layout(|layout| layout.query_content_box(node.to_opaque()))
.unwrap_or(None)
self.layout.borrow().query_content_box(node.to_opaque())
}
pub fn content_boxes_query(&self, node: &Node) -> Vec<UntypedRect<Au>> {
if !self.layout_reflow(QueryMsg::ContentBoxes) {
return vec![];
}
self.with_layout(|layout| layout.query_content_boxes(node.to_opaque()))
.unwrap_or_default()
self.layout.borrow().query_content_boxes(node.to_opaque())
}
pub fn client_rect_query(&self, node: &Node) -> UntypedRect<i32> {
if !self.layout_reflow(QueryMsg::ClientRectQuery) {
return Rect::zero();
}
self.with_layout(|layout| layout.query_client_rect(node.to_opaque()))
.unwrap_or_default()
self.layout.borrow().query_client_rect(node.to_opaque())
}
/// Find the scroll area of the given node, if it is not None. If the node
@ -2091,8 +2091,7 @@ impl Window {
if !self.layout_reflow(QueryMsg::ScrollingAreaQuery) {
return Rect::zero();
}
self.with_layout(|layout| layout.query_scrolling_area(opaque))
.unwrap_or_default()
self.layout.borrow().query_scrolling_area(opaque)
}
pub fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
@ -2136,18 +2135,14 @@ impl Window {
}
let document = self.Document();
DOMString::from(
self.with_layout(|layout| {
layout.query_resolved_style(
element,
pseudo,
property,
document.animations().sets.clone(),
document.current_animation_timeline_value(),
)
})
.unwrap(),
)
let animations = document.animations().sets.clone();
DOMString::from(self.layout.borrow().query_resolved_style(
element,
pseudo,
property,
animations,
document.current_animation_timeline_value(),
))
}
pub fn inner_window_dimensions_query(
@ -2157,8 +2152,9 @@ impl Window {
if !self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery) {
return None;
}
self.with_layout(|layout| layout.query_inner_window_dimension(browsing_context))
.unwrap()
self.layout
.borrow()
.query_inner_window_dimension(browsing_context)
}
#[allow(unsafe_code)]
@ -2167,9 +2163,7 @@ impl Window {
return (None, Rect::zero());
}
let response = self
.with_layout(|layout| layout.query_offset_parent(node.to_opaque()))
.unwrap();
let response = self.layout.borrow().query_offset_parent(node.to_opaque());
let element = response.node_address.and_then(|parent_node_address| {
let node = unsafe { from_untrusted_node_address(parent_node_address) };
DomRoot::downcast(node)
@ -2185,8 +2179,9 @@ impl Window {
if !self.layout_reflow(QueryMsg::TextIndexQuery) {
return None;
}
self.with_layout(|layout| layout.query_text_indext(node.to_opaque(), point_in_node))
.unwrap()
self.layout
.borrow()
.query_text_indext(node.to_opaque(), point_in_node)
}
#[allow(unsafe_code)]
@ -2309,10 +2304,6 @@ impl Window {
self.Document().url()
}
pub fn with_layout<T>(&self, call: impl FnOnce(&mut dyn Layout) -> T) -> Result<T, ()> {
ScriptThread::with_layout(self.pipeline_id(), call)
}
pub fn windowproxy_handler(&self) -> WindowProxyHandler {
WindowProxyHandler(self.dom_static.windowproxy_handler.0)
}
@ -2517,6 +2508,7 @@ impl Window {
runtime: Rc<Runtime>,
script_chan: MainThreadScriptChan,
task_manager: TaskManager,
layout: Box<dyn Layout>,
image_cache_chan: Sender<ImageCacheMsg>,
image_cache: Arc<dyn ImageCache>,
resource_threads: ResourceThreads,
@ -2580,6 +2572,7 @@ impl Window {
),
script_chan,
task_manager,
layout: RefCell::new(layout),
image_cache_chan,
image_cache,
navigator: Default::default(),