mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #26105 - servo:layout-2020-less-opaque, r=emilio
Make DOM own the style and layout data, in an UnsafeCell
This commit is contained in:
commit
d64f7d427a
21 changed files with 184 additions and 247 deletions
|
@ -8,8 +8,7 @@ use script_layout_interface::StyleData;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct StyleAndLayoutData {
|
pub struct StyleAndLayoutData {
|
||||||
/// Data accessed by script_layout_interface. This must be first to allow
|
/// The style data associated with a node.
|
||||||
/// casting between StyleAndLayoutData and StyleData.
|
|
||||||
pub style_data: StyleData,
|
pub style_data: StyleData,
|
||||||
/// The layout data associated with a node.
|
/// The layout data associated with a node.
|
||||||
pub layout_data: AtomicRefCell<LayoutData>,
|
pub layout_data: AtomicRefCell<LayoutData>,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use crate::construct::ConstructionResult;
|
use crate::construct::ConstructionResult;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
|
use crate::data::StyleAndLayoutData;
|
||||||
use crate::display_list::items::{DisplayList, OpaqueNode, ScrollOffsetMap};
|
use crate::display_list::items::{DisplayList, OpaqueNode, ScrollOffsetMap};
|
||||||
use crate::display_list::IndexableText;
|
use crate::display_list::IndexableText;
|
||||||
use crate::flow::{Flow, GetBaseFlow};
|
use crate::flow::{Flow, GetBaseFlow};
|
||||||
|
@ -26,7 +27,6 @@ use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse,
|
||||||
use script_layout_interface::wrapper_traits::{
|
use script_layout_interface::wrapper_traits::{
|
||||||
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||||
};
|
};
|
||||||
use script_layout_interface::StyleData;
|
|
||||||
use script_layout_interface::{LayoutElementType, LayoutNodeType};
|
use script_layout_interface::{LayoutElementType, LayoutNodeType};
|
||||||
use script_traits::LayoutMsg as ConstellationMsg;
|
use script_traits::LayoutMsg as ConstellationMsg;
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
|
@ -761,7 +761,7 @@ pub fn process_resolved_style_request<'dom>(
|
||||||
|
|
||||||
// We call process_resolved_style_request after performing a whole-document
|
// We call process_resolved_style_request after performing a whole-document
|
||||||
// traversal, so in the common case, the element is styled.
|
// traversal, so in the common case, the element is styled.
|
||||||
if element.get_data().is_some() {
|
if element.has_data() {
|
||||||
return process_resolved_style_request_internal(node, pseudo, property, layout_root);
|
return process_resolved_style_request_internal(node, pseudo, property, layout_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,9 +1036,14 @@ fn inner_text_collection_steps<'dom>(
|
||||||
_ => child,
|
_ => child,
|
||||||
};
|
};
|
||||||
|
|
||||||
let element_data = unsafe {
|
let element_data = {
|
||||||
node.get_style_and_layout_data()
|
&node.get_style_and_layout_data().as_ref().map(|opaque| {
|
||||||
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
|
&opaque
|
||||||
|
.downcast_ref::<StyleAndLayoutData>()
|
||||||
|
.unwrap()
|
||||||
|
.style_data
|
||||||
|
.element_data
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if element_data.is_none() {
|
if element_data.is_none() {
|
||||||
|
|
|
@ -39,23 +39,21 @@ use style::selector_parser::RestyleDamage;
|
||||||
use style::values::computed::counters::ContentItem;
|
use style::values::computed::counters::ContentItem;
|
||||||
use style::values::generics::counters::Content;
|
use style::values::generics::counters::Content;
|
||||||
|
|
||||||
pub trait LayoutNodeLayoutData {
|
pub trait LayoutNodeLayoutData<'dom> {
|
||||||
/// Similar to borrow_data*, but returns the full PersistentLayoutData rather
|
fn borrow_layout_data(self) -> Option<AtomicRef<'dom, LayoutData>>;
|
||||||
/// than only the style::data::ElementData.
|
fn mutate_layout_data(self) -> Option<AtomicRefMut<'dom, LayoutData>>;
|
||||||
fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>>;
|
|
||||||
fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>>;
|
|
||||||
fn flow_debug_id(self) -> usize;
|
fn flow_debug_id(self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, T> LayoutNodeLayoutData for T
|
impl<'dom, T> LayoutNodeLayoutData<'dom> for T
|
||||||
where
|
where
|
||||||
T: GetLayoutData<'dom>,
|
T: GetLayoutData<'dom>,
|
||||||
{
|
{
|
||||||
fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>> {
|
fn borrow_layout_data(self) -> Option<AtomicRef<'dom, LayoutData>> {
|
||||||
self.get_raw_data().map(|d| d.layout_data.borrow())
|
self.get_raw_data().map(|d| d.layout_data.borrow())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>> {
|
fn mutate_layout_data(self) -> Option<AtomicRefMut<'dom, LayoutData>> {
|
||||||
self.get_raw_data().map(|d| d.layout_data.borrow_mut())
|
self.get_raw_data().map(|d| d.layout_data.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +63,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetRawData {
|
pub trait GetRawData<'dom> {
|
||||||
fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
|
fn get_raw_data(self) -> Option<&'dom StyleAndLayoutData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, T> GetRawData for T
|
impl<'dom, T> GetRawData<'dom> for T
|
||||||
where
|
where
|
||||||
T: GetLayoutData<'dom>,
|
T: GetLayoutData<'dom>,
|
||||||
{
|
{
|
||||||
fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
|
fn get_raw_data(self) -> Option<&'dom StyleAndLayoutData> {
|
||||||
self.get_style_and_layout_data().map(|opaque| {
|
self.get_style_and_layout_data()
|
||||||
let container = opaque.ptr.as_ptr() as *mut StyleAndLayoutData;
|
.map(|opaque| opaque.downcast_ref().unwrap())
|
||||||
unsafe { &*container }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync {
|
||||||
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>;
|
fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>;
|
||||||
|
|
||||||
fn as_opaque(self) -> OpaqueNode;
|
fn as_opaque(self) -> OpaqueNode;
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
|
fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement>;
|
||||||
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
||||||
|
@ -446,7 +446,8 @@ where
|
||||||
self.opaque()
|
self.opaque()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement> {
|
#[allow(unsafe_code)]
|
||||||
|
fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement> {
|
||||||
self.get_raw_data()
|
self.get_raw_data()
|
||||||
.map(|d| d.layout_data.borrow_mut())
|
.map(|d| d.layout_data.borrow_mut())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -7,18 +7,16 @@
|
||||||
use crate::data::StyleAndLayoutData;
|
use crate::data::StyleAndLayoutData;
|
||||||
use script_layout_interface::wrapper_traits::GetLayoutData;
|
use script_layout_interface::wrapper_traits::GetLayoutData;
|
||||||
|
|
||||||
pub trait GetRawData {
|
pub trait GetRawData<'dom> {
|
||||||
fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
|
fn get_raw_data(self) -> Option<&'dom StyleAndLayoutData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, T> GetRawData for T
|
impl<'dom, T> GetRawData<'dom> for T
|
||||||
where
|
where
|
||||||
T: GetLayoutData<'dom>,
|
T: GetLayoutData<'dom>,
|
||||||
{
|
{
|
||||||
fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
|
fn get_raw_data(self) -> Option<&'dom StyleAndLayoutData> {
|
||||||
self.get_style_and_layout_data().map(|opaque| {
|
self.get_style_and_layout_data()
|
||||||
let container = opaque.ptr.as_ptr() as *mut StyleAndLayoutData;
|
.map(|opaque| opaque.downcast_ref().unwrap())
|
||||||
unsafe { &*container }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
||||||
use gfx_traits::ByteIndex;
|
use gfx_traits::ByteIndex;
|
||||||
use html5ever::{LocalName, Namespace};
|
use html5ever::{LocalName, Namespace};
|
||||||
use layout::data::StyleAndLayoutData;
|
use layout::data::StyleAndLayoutData;
|
||||||
|
@ -70,7 +70,6 @@ use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ptr::NonNull;
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc as StdArc;
|
use std::sync::Arc as StdArc;
|
||||||
use style::applicable_declarations::ApplicableDeclarationBlock;
|
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||||
|
@ -92,12 +91,6 @@ use style::str::is_whitespace;
|
||||||
use style::stylist::CascadeData;
|
use style::stylist::CascadeData;
|
||||||
use style::CaseSensitivityExt;
|
use style::CaseSensitivityExt;
|
||||||
|
|
||||||
pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) {
|
|
||||||
let ptr = data.ptr.as_ptr() as *mut StyleData;
|
|
||||||
let non_opaque: *mut StyleAndLayoutData = ptr as *mut _;
|
|
||||||
let _ = Box::from_raw(non_opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct ServoLayoutNode<'dom> {
|
pub struct ServoLayoutNode<'dom> {
|
||||||
/// The wrapped node.
|
/// The wrapped node.
|
||||||
|
@ -237,7 +230,7 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opaque(&self) -> OpaqueNode {
|
fn opaque(&self) -> OpaqueNode {
|
||||||
unsafe { self.get_jsmanaged().opaque() }
|
self.get_jsmanaged().opaque()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_id(self) -> usize {
|
fn debug_id(self) -> usize {
|
||||||
|
@ -276,10 +269,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
|
|
||||||
unsafe fn initialize_data(&self) {
|
unsafe fn initialize_data(&self) {
|
||||||
if self.get_raw_data().is_none() {
|
if self.get_raw_data().is_none() {
|
||||||
let ptr: *mut StyleAndLayoutData = Box::into_raw(Box::new(StyleAndLayoutData::new()));
|
let opaque = OpaqueStyleAndLayoutData::new(StyleAndLayoutData::new());
|
||||||
let opaque = OpaqueStyleAndLayoutData {
|
|
||||||
ptr: NonNull::new_unchecked(ptr as *mut StyleData),
|
|
||||||
};
|
|
||||||
self.init_style_and_layout_data(opaque);
|
self.init_style_and_layout_data(opaque);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -297,34 +287,33 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> GetLayoutData<'ln> for ServoLayoutNode<'ln> {
|
impl<'dom> GetLayoutData<'dom> for ServoLayoutNode<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
unsafe { self.get_jsmanaged().get_style_and_layout_data() }
|
self.get_jsmanaged().get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> GetLayoutData<'le> for ServoLayoutElement<'le> {
|
impl<'dom> GetLayoutData<'dom> for ServoLayoutElement<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.as_node().get_style_and_layout_data()
|
self.as_node().get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> GetLayoutData<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
impl<'dom> GetLayoutData<'dom> for ServoThreadSafeLayoutNode<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.node.get_style_and_layout_data()
|
self.node.get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> GetLayoutData<'le> for ServoThreadSafeLayoutElement<'le> {
|
impl<'dom> GetLayoutData<'dom> for ServoThreadSafeLayoutElement<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.element.as_node().get_style_and_layout_data()
|
self.element.as_node().get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> ServoLayoutNode<'ln> {
|
impl<'dom> ServoLayoutNode<'dom> {
|
||||||
/// Returns the interior of this node as a `LayoutDom`. This is highly unsafe for layout to
|
/// Returns the interior of this node as a `LayoutDom`.
|
||||||
/// call and as such is marked `unsafe`.
|
pub fn get_jsmanaged(self) -> LayoutDom<'dom, Node> {
|
||||||
pub unsafe fn get_jsmanaged(&self) -> LayoutDom<'ln, Node> {
|
|
||||||
self.node
|
self.node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,7 +537,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
|
|
||||||
unsafe fn clear_data(&self) {
|
unsafe fn clear_data(&self) {
|
||||||
if self.get_raw_data().is_some() {
|
if self.get_raw_data().is_some() {
|
||||||
drop_style_and_layout_data(self.as_node().take_style_and_layout_data());
|
drop(self.as_node().take_style_and_layout_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,11 +546,20 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
self.mutate_data().unwrap()
|
self.mutate_data().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
|
/// Whether there is an ElementData container.
|
||||||
unsafe {
|
fn has_data(&self) -> bool {
|
||||||
self.get_style_and_layout_data()
|
self.get_style_data().is_some()
|
||||||
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
|
}
|
||||||
}
|
|
||||||
|
/// Immutably borrows the ElementData.
|
||||||
|
fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
|
||||||
|
self.get_style_data().map(|data| data.element_data.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the ElementData.
|
||||||
|
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
|
||||||
|
self.get_style_data()
|
||||||
|
.map(|data| data.element_data.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_item_display_fixup(&self) -> bool {
|
fn skip_item_display_fixup(&self) -> bool {
|
||||||
|
@ -697,10 +695,12 @@ impl<'le> ServoLayoutElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_style_data(&self) -> Option<&StyleData> {
|
fn get_style_data(&self) -> Option<&StyleData> {
|
||||||
unsafe {
|
self.get_style_and_layout_data().map(|opaque| {
|
||||||
self.get_style_and_layout_data()
|
&opaque
|
||||||
.map(|d| &*(d.ptr.as_ptr() as *mut StyleData))
|
.downcast_ref::<StyleAndLayoutData>()
|
||||||
}
|
.unwrap()
|
||||||
|
.style_data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unset_snapshot_flags(&self) {
|
pub unsafe fn unset_snapshot_flags(&self) {
|
||||||
|
@ -1034,7 +1034,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
||||||
|
|
||||||
fn parent_style(&self) -> Arc<ComputedValues> {
|
fn parent_style(&self) -> Arc<ComputedValues> {
|
||||||
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
||||||
let parent_data = parent.get_data().unwrap().borrow();
|
let parent_data = parent.borrow_data().unwrap();
|
||||||
parent_data.styles.primary().clone()
|
parent_data.styles.primary().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,7 +1060,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'ln OpaqueStyleAndLayoutData> {
|
||||||
self.node.get_style_and_layout_data()
|
self.node.get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,10 +1319,7 @@ impl<'le> ThreadSafeLayoutElement<'le> for ServoThreadSafeLayoutElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_data(&self) -> AtomicRef<ElementData> {
|
fn style_data(&self) -> AtomicRef<ElementData> {
|
||||||
self.element
|
self.element.borrow_data().expect("Unstyled layout node?")
|
||||||
.get_data()
|
|
||||||
.expect("Unstyled layout node?")
|
|
||||||
.borrow()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_shadow_host(&self) -> bool {
|
fn is_shadow_host(&self) -> bool {
|
||||||
|
|
|
@ -23,7 +23,6 @@ extern crate profile_traits;
|
||||||
|
|
||||||
mod dom_wrapper;
|
mod dom_wrapper;
|
||||||
|
|
||||||
use crate::dom_wrapper::drop_style_and_layout_data;
|
|
||||||
use crate::dom_wrapper::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
|
use crate::dom_wrapper::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
|
@ -692,7 +691,6 @@ impl LayoutThread {
|
||||||
Msg::GetRPC(..) => LayoutHangAnnotation::GetRPC,
|
Msg::GetRPC(..) => LayoutHangAnnotation::GetRPC,
|
||||||
Msg::TickAnimations(..) => LayoutHangAnnotation::TickAnimations,
|
Msg::TickAnimations(..) => LayoutHangAnnotation::TickAnimations,
|
||||||
Msg::AdvanceClockMs(..) => LayoutHangAnnotation::AdvanceClockMs,
|
Msg::AdvanceClockMs(..) => LayoutHangAnnotation::AdvanceClockMs,
|
||||||
Msg::ReapStyleAndLayoutData(..) => LayoutHangAnnotation::ReapStyleAndLayoutData,
|
|
||||||
Msg::CollectReports(..) => LayoutHangAnnotation::CollectReports,
|
Msg::CollectReports(..) => LayoutHangAnnotation::CollectReports,
|
||||||
Msg::PrepareToExit(..) => LayoutHangAnnotation::PrepareToExit,
|
Msg::PrepareToExit(..) => LayoutHangAnnotation::PrepareToExit,
|
||||||
Msg::ExitNow => LayoutHangAnnotation::ExitNow,
|
Msg::ExitNow => LayoutHangAnnotation::ExitNow,
|
||||||
|
@ -833,9 +831,6 @@ impl LayoutThread {
|
||||||
webrender_api::ScrollClamping::ToContentBounds,
|
webrender_api::ScrollClamping::ToContentBounds,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Msg::ReapStyleAndLayoutData(dead_data) => unsafe {
|
|
||||||
drop_style_and_layout_data(dead_data)
|
|
||||||
},
|
|
||||||
Msg::CollectReports(reports_chan) => {
|
Msg::CollectReports(reports_chan) => {
|
||||||
self.collect_reports(reports_chan, possibly_locked_rw_data);
|
self.collect_reports(reports_chan, possibly_locked_rw_data);
|
||||||
},
|
},
|
||||||
|
@ -967,9 +962,6 @@ impl LayoutThread {
|
||||||
response_chan.send(()).unwrap();
|
response_chan.send(()).unwrap();
|
||||||
loop {
|
loop {
|
||||||
match self.port.recv().unwrap() {
|
match self.port.recv().unwrap() {
|
||||||
Msg::ReapStyleAndLayoutData(dead_data) => unsafe {
|
|
||||||
drop_style_and_layout_data(dead_data)
|
|
||||||
},
|
|
||||||
Msg::ExitNow => {
|
Msg::ExitNow => {
|
||||||
debug!("layout thread is exiting...");
|
debug!("layout thread is exiting...");
|
||||||
self.exit_now();
|
self.exit_now();
|
||||||
|
@ -1472,7 +1464,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
// If we haven't styled this node yet, we don't need to track a
|
// If we haven't styled this node yet, we don't need to track a
|
||||||
// restyle.
|
// restyle.
|
||||||
let style_data = match el.get_data() {
|
let mut style_data = match el.mutate_data() {
|
||||||
Some(d) => d,
|
Some(d) => d,
|
||||||
None => {
|
None => {
|
||||||
unsafe { el.unset_snapshot_flags() };
|
unsafe { el.unset_snapshot_flags() };
|
||||||
|
@ -1485,8 +1477,6 @@ impl LayoutThread {
|
||||||
map.insert(el.as_node().opaque(), s);
|
map.insert(el.as_node().opaque(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut style_data = style_data.borrow_mut();
|
|
||||||
|
|
||||||
// Stash the data on the element for processing by the style system.
|
// Stash the data on the element for processing by the style system.
|
||||||
style_data.hint.insert(restyle.hint.into());
|
style_data.hint.insert(restyle.hint.into());
|
||||||
style_data.damage = restyle.damage;
|
style_data.damage = restyle.damage;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
||||||
use gfx_traits::ByteIndex;
|
use gfx_traits::ByteIndex;
|
||||||
use html5ever::{LocalName, Namespace};
|
use html5ever::{LocalName, Namespace};
|
||||||
use layout::data::StyleAndLayoutData;
|
use layout::data::StyleAndLayoutData;
|
||||||
|
@ -70,7 +70,6 @@ use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ptr::NonNull;
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc as StdArc;
|
use std::sync::Arc as StdArc;
|
||||||
use style::applicable_declarations::ApplicableDeclarationBlock;
|
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||||
|
@ -92,12 +91,6 @@ use style::str::is_whitespace;
|
||||||
use style::stylist::CascadeData;
|
use style::stylist::CascadeData;
|
||||||
use style::CaseSensitivityExt;
|
use style::CaseSensitivityExt;
|
||||||
|
|
||||||
pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) {
|
|
||||||
let ptr = data.ptr.as_ptr() as *mut StyleData;
|
|
||||||
let non_opaque: *mut StyleAndLayoutData = ptr as *mut _;
|
|
||||||
let _ = Box::from_raw(non_opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct ServoLayoutNode<'dom> {
|
pub struct ServoLayoutNode<'dom> {
|
||||||
/// The wrapped node.
|
/// The wrapped node.
|
||||||
|
@ -283,10 +276,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
|
|
||||||
unsafe fn initialize_data(&self) {
|
unsafe fn initialize_data(&self) {
|
||||||
if self.get_raw_data().is_none() {
|
if self.get_raw_data().is_none() {
|
||||||
let ptr: *mut StyleAndLayoutData = Box::into_raw(Box::new(StyleAndLayoutData::new()));
|
let opaque = OpaqueStyleAndLayoutData::new(StyleAndLayoutData::new());
|
||||||
let opaque = OpaqueStyleAndLayoutData {
|
|
||||||
ptr: NonNull::new_unchecked(ptr as *mut StyleData),
|
|
||||||
};
|
|
||||||
self.init_style_and_layout_data(opaque);
|
self.init_style_and_layout_data(opaque);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -304,26 +294,26 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> GetLayoutData<'ln> for ServoLayoutNode<'ln> {
|
impl<'dom> GetLayoutData<'dom> for ServoLayoutNode<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
unsafe { self.get_jsmanaged().get_style_and_layout_data() }
|
unsafe { self.get_jsmanaged().get_style_and_layout_data() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> GetLayoutData<'le> for ServoLayoutElement<'le> {
|
impl<'dom> GetLayoutData<'dom> for ServoLayoutElement<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.as_node().get_style_and_layout_data()
|
self.as_node().get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> GetLayoutData<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
impl<'dom> GetLayoutData<'dom> for ServoThreadSafeLayoutNode<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.node.get_style_and_layout_data()
|
self.node.get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> GetLayoutData<'le> for ServoThreadSafeLayoutElement<'le> {
|
impl<'dom> GetLayoutData<'dom> for ServoThreadSafeLayoutElement<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
self.element.as_node().get_style_and_layout_data()
|
self.element.as_node().get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +545,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
|
|
||||||
unsafe fn clear_data(&self) {
|
unsafe fn clear_data(&self) {
|
||||||
if self.get_raw_data().is_some() {
|
if self.get_raw_data().is_some() {
|
||||||
drop_style_and_layout_data(self.as_node().take_style_and_layout_data());
|
drop(self.as_node().take_style_and_layout_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,11 +554,20 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
self.mutate_data().unwrap()
|
self.mutate_data().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
|
/// Whether there is an ElementData container.
|
||||||
unsafe {
|
fn has_data(&self) -> bool {
|
||||||
self.get_style_and_layout_data()
|
self.get_style_data().is_some()
|
||||||
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
|
}
|
||||||
}
|
|
||||||
|
/// Immutably borrows the ElementData.
|
||||||
|
fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
|
||||||
|
self.get_style_data().map(|data| data.element_data.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the ElementData.
|
||||||
|
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
|
||||||
|
self.get_style_data()
|
||||||
|
.map(|data| data.element_data.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_item_display_fixup(&self) -> bool {
|
fn skip_item_display_fixup(&self) -> bool {
|
||||||
|
@ -704,10 +703,12 @@ impl<'le> ServoLayoutElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_style_data(&self) -> Option<&StyleData> {
|
fn get_style_data(&self) -> Option<&StyleData> {
|
||||||
unsafe {
|
self.get_style_and_layout_data().map(|opaque| {
|
||||||
self.get_style_and_layout_data()
|
&opaque
|
||||||
.map(|d| &*(d.ptr.as_ptr() as *mut StyleData))
|
.downcast_ref::<StyleAndLayoutData>()
|
||||||
}
|
.unwrap()
|
||||||
|
.style_data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unset_snapshot_flags(&self) {
|
pub unsafe fn unset_snapshot_flags(&self) {
|
||||||
|
@ -1041,7 +1042,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
||||||
|
|
||||||
fn parent_style(&self) -> Arc<ComputedValues> {
|
fn parent_style(&self) -> Arc<ComputedValues> {
|
||||||
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
||||||
let parent_data = parent.get_data().unwrap().borrow();
|
let parent_data = parent.borrow_data().unwrap();
|
||||||
parent_data.styles.primary().clone()
|
parent_data.styles.primary().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,7 +1068,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'ln OpaqueStyleAndLayoutData> {
|
||||||
self.node.get_style_and_layout_data()
|
self.node.get_style_and_layout_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1326,10 +1327,7 @@ impl<'le> ThreadSafeLayoutElement<'le> for ServoThreadSafeLayoutElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_data(&self) -> AtomicRef<ElementData> {
|
fn style_data(&self) -> AtomicRef<ElementData> {
|
||||||
self.element
|
self.element.borrow_data().expect("Unstyled layout node?")
|
||||||
.get_data()
|
|
||||||
.expect("Unstyled layout node?")
|
|
||||||
.borrow()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_shadow_host(&self) -> bool {
|
fn is_shadow_host(&self) -> bool {
|
||||||
|
|
|
@ -21,7 +21,6 @@ extern crate profile_traits;
|
||||||
|
|
||||||
mod dom_wrapper;
|
mod dom_wrapper;
|
||||||
|
|
||||||
use crate::dom_wrapper::drop_style_and_layout_data;
|
|
||||||
use crate::dom_wrapper::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
|
use crate::dom_wrapper::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||||
|
@ -640,7 +639,6 @@ impl LayoutThread {
|
||||||
Msg::GetRPC(..) => LayoutHangAnnotation::GetRPC,
|
Msg::GetRPC(..) => LayoutHangAnnotation::GetRPC,
|
||||||
Msg::TickAnimations(..) => LayoutHangAnnotation::TickAnimations,
|
Msg::TickAnimations(..) => LayoutHangAnnotation::TickAnimations,
|
||||||
Msg::AdvanceClockMs(..) => LayoutHangAnnotation::AdvanceClockMs,
|
Msg::AdvanceClockMs(..) => LayoutHangAnnotation::AdvanceClockMs,
|
||||||
Msg::ReapStyleAndLayoutData(..) => LayoutHangAnnotation::ReapStyleAndLayoutData,
|
|
||||||
Msg::CollectReports(..) => LayoutHangAnnotation::CollectReports,
|
Msg::CollectReports(..) => LayoutHangAnnotation::CollectReports,
|
||||||
Msg::PrepareToExit(..) => LayoutHangAnnotation::PrepareToExit,
|
Msg::PrepareToExit(..) => LayoutHangAnnotation::PrepareToExit,
|
||||||
Msg::ExitNow => LayoutHangAnnotation::ExitNow,
|
Msg::ExitNow => LayoutHangAnnotation::ExitNow,
|
||||||
|
@ -779,9 +777,6 @@ impl LayoutThread {
|
||||||
webrender_api::ScrollClamping::ToContentBounds,
|
webrender_api::ScrollClamping::ToContentBounds,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Msg::ReapStyleAndLayoutData(dead_data) => unsafe {
|
|
||||||
drop_style_and_layout_data(dead_data)
|
|
||||||
},
|
|
||||||
Msg::CollectReports(reports_chan) => {
|
Msg::CollectReports(reports_chan) => {
|
||||||
self.collect_reports(reports_chan, possibly_locked_rw_data);
|
self.collect_reports(reports_chan, possibly_locked_rw_data);
|
||||||
},
|
},
|
||||||
|
@ -890,9 +885,6 @@ impl LayoutThread {
|
||||||
response_chan.send(()).unwrap();
|
response_chan.send(()).unwrap();
|
||||||
loop {
|
loop {
|
||||||
match self.port.recv().unwrap() {
|
match self.port.recv().unwrap() {
|
||||||
Msg::ReapStyleAndLayoutData(dead_data) => unsafe {
|
|
||||||
drop_style_and_layout_data(dead_data)
|
|
||||||
},
|
|
||||||
Msg::ExitNow => {
|
Msg::ExitNow => {
|
||||||
debug!("layout thread is exiting...");
|
debug!("layout thread is exiting...");
|
||||||
self.exit_now();
|
self.exit_now();
|
||||||
|
@ -1118,7 +1110,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
// If we haven't styled this node yet, we don't need to track a
|
// If we haven't styled this node yet, we don't need to track a
|
||||||
// restyle.
|
// restyle.
|
||||||
let style_data = match el.get_data() {
|
let mut style_data = match el.mutate_data() {
|
||||||
Some(d) => d,
|
Some(d) => d,
|
||||||
None => {
|
None => {
|
||||||
unsafe { el.unset_snapshot_flags() };
|
unsafe { el.unset_snapshot_flags() };
|
||||||
|
@ -1131,8 +1123,6 @@ impl LayoutThread {
|
||||||
map.insert(el.as_node().opaque(), s);
|
map.insert(el.as_node().opaque(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut style_data = style_data.borrow_mut();
|
|
||||||
|
|
||||||
// Stash the data on the element for processing by the style system.
|
// Stash the data on the element for processing by the style system.
|
||||||
style_data.hint.insert(restyle.hint.into());
|
style_data.hint.insert(restyle.hint.into());
|
||||||
style_data.damage = restyle.damage;
|
style_data.damage = restyle.damage;
|
||||||
|
|
|
@ -532,7 +532,6 @@ pub enum LayoutHangAnnotation {
|
||||||
GetRPC,
|
GetRPC,
|
||||||
TickAnimations,
|
TickAnimations,
|
||||||
AdvanceClockMs,
|
AdvanceClockMs,
|
||||||
ReapStyleAndLayoutData,
|
|
||||||
CollectReports,
|
CollectReports,
|
||||||
PrepareToExit,
|
PrepareToExit,
|
||||||
ExitNow,
|
ExitNow,
|
||||||
|
|
|
@ -65,7 +65,6 @@ use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use crossbeam_channel::Sender;
|
|
||||||
use devtools_traits::NodeInfo;
|
use devtools_traits::NodeInfo;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::default::{Point2D, Rect, Size2D, Vector2D};
|
use euclid::default::{Point2D, Rect, Size2D, Vector2D};
|
||||||
|
@ -76,7 +75,6 @@ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
use msg::constellation_msg::{BrowsingContextId, PipelineId};
|
||||||
use net_traits::image::base::{Image, ImageMetadata};
|
use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use ref_slice::ref_slice;
|
use ref_slice::ref_slice;
|
||||||
use script_layout_interface::message::Msg;
|
|
||||||
use script_layout_interface::{HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType};
|
use script_layout_interface::{HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType};
|
||||||
use script_layout_interface::{OpaqueStyleAndLayoutData, SVGSVGData, TrustedNodeAddress};
|
use script_layout_interface::{OpaqueStyleAndLayoutData, SVGSVGData, TrustedNodeAddress};
|
||||||
use script_traits::DocumentActivity;
|
use script_traits::DocumentActivity;
|
||||||
|
@ -99,7 +97,6 @@ use style::context::QuirksMode;
|
||||||
use style::dom::OpaqueNode;
|
use style::dom::OpaqueNode;
|
||||||
use style::selector_parser::{SelectorImpl, SelectorParser};
|
use style::selector_parser::{SelectorImpl, SelectorParser};
|
||||||
use style::stylesheets::Stylesheet;
|
use style::stylesheets::Stylesheet;
|
||||||
use style::thread_state;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -155,7 +152,8 @@ pub struct Node {
|
||||||
///
|
///
|
||||||
/// Must be sent back to the layout thread to be destroyed when this
|
/// Must be sent back to the layout thread to be destroyed when this
|
||||||
/// node is finalized.
|
/// node is finalized.
|
||||||
style_and_layout_data: Cell<Option<OpaqueStyleAndLayoutData>>,
|
#[ignore_malloc_size_of = "shrug"]
|
||||||
|
style_and_layout_data: UnsafeCell<Option<OpaqueStyleAndLayoutData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -205,15 +203,6 @@ impl NodeFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Node {
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if let Some(data) = self.style_and_layout_data.get() {
|
|
||||||
self.dispose(data, ScriptThread::get_any_layout_chan().as_ref());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// suppress observers flag
|
/// suppress observers flag
|
||||||
/// <https://dom.spec.whatwg.org/#concept-node-insert>
|
/// <https://dom.spec.whatwg.org/#concept-node-insert>
|
||||||
/// <https://dom.spec.whatwg.org/#concept-node-remove>
|
/// <https://dom.spec.whatwg.org/#concept-node-remove>
|
||||||
|
@ -224,21 +213,6 @@ enum SuppressObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
/// Sends the style and layout data, if any, back to the layout thread to be destroyed.
|
|
||||||
pub(crate) fn dispose(
|
|
||||||
&self,
|
|
||||||
data: OpaqueStyleAndLayoutData,
|
|
||||||
layout_chan: Option<&Sender<Msg>>,
|
|
||||||
) {
|
|
||||||
debug_assert!(thread_state::get().is_script());
|
|
||||||
self.style_and_layout_data.set(None);
|
|
||||||
if layout_chan.map_or(false, |chan| {
|
|
||||||
chan.send(Msg::ReapStyleAndLayoutData(data)).is_err()
|
|
||||||
}) {
|
|
||||||
warn!("layout thread unreachable - leaking layout data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a new child to the end of this node's list of children.
|
/// Adds a new child to the end of this node's list of children.
|
||||||
///
|
///
|
||||||
/// Fails unless `new_child` is disconnected from the tree.
|
/// Fails unless `new_child` is disconnected from the tree.
|
||||||
|
@ -317,16 +291,11 @@ impl Node {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let window = window_from_node(root);
|
|
||||||
let layout_chan = window.layout_chan();
|
|
||||||
for node in root.traverse_preorder(ShadowIncluding::Yes) {
|
for node in root.traverse_preorder(ShadowIncluding::Yes) {
|
||||||
// This needs to be in its own loop, because unbind_from_tree may
|
// This needs to be in its own loop, because unbind_from_tree may
|
||||||
// rely on the state of IS_IN_DOC of the context node's descendants,
|
// rely on the state of IS_IN_DOC of the context node's descendants,
|
||||||
// e.g. when removing a <form>.
|
// e.g. when removing a <form>.
|
||||||
vtable_for(&&*node).unbind_from_tree(&context);
|
vtable_for(&&*node).unbind_from_tree(&context);
|
||||||
if let Some(data) = node.style_and_layout_data.get() {
|
|
||||||
node.dispose(data, Some(layout_chan));
|
|
||||||
}
|
|
||||||
// https://dom.spec.whatwg.org/#concept-node-remove step 14
|
// https://dom.spec.whatwg.org/#concept-node-remove step 14
|
||||||
if let Some(element) = node.as_custom_element() {
|
if let Some(element) = node.as_custom_element() {
|
||||||
ScriptThread::enqueue_callback_reaction(
|
ScriptThread::enqueue_callback_reaction(
|
||||||
|
@ -507,15 +476,6 @@ impl<'a> Iterator for QuerySelectorIterator {
|
||||||
impl Node {
|
impl Node {
|
||||||
impl_rare_data!(NodeRareData);
|
impl_rare_data!(NodeRareData);
|
||||||
|
|
||||||
pub(crate) fn teardown(&self, layout_chan: &Sender<Msg>) {
|
|
||||||
if let Some(data) = self.style_and_layout_data.get() {
|
|
||||||
self.dispose(data, Some(layout_chan));
|
|
||||||
}
|
|
||||||
for kid in self.children() {
|
|
||||||
kid.teardown(layout_chan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this node is before `other` in the same connected DOM
|
/// Returns true if this node is before `other` in the same connected DOM
|
||||||
/// tree.
|
/// tree.
|
||||||
pub fn is_before(&self, other: &Node) -> bool {
|
pub fn is_before(&self, other: &Node) -> bool {
|
||||||
|
@ -1322,8 +1282,8 @@ pub trait LayoutNodeHelpers<'dom> {
|
||||||
|
|
||||||
fn children_count(self) -> u32;
|
fn children_count(self) -> u32;
|
||||||
|
|
||||||
unsafe fn get_style_and_layout_data(self) -> Option<OpaqueStyleAndLayoutData>;
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData>;
|
||||||
unsafe fn init_style_and_layout_data(self, _: OpaqueStyleAndLayoutData);
|
unsafe fn init_style_and_layout_data(self, data: OpaqueStyleAndLayoutData);
|
||||||
unsafe fn take_style_and_layout_data(self) -> OpaqueStyleAndLayoutData;
|
unsafe fn take_style_and_layout_data(self) -> OpaqueStyleAndLayoutData;
|
||||||
|
|
||||||
fn text_content(self) -> Cow<'dom, str>;
|
fn text_content(self) -> Cow<'dom, str>;
|
||||||
|
@ -1450,23 +1410,24 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_style_and_layout_data(self) -> Option<OpaqueStyleAndLayoutData> {
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData> {
|
||||||
(*self.unsafe_get()).style_and_layout_data.get()
|
unsafe { (*self.unsafe_get().style_and_layout_data.get()).as_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn init_style_and_layout_data(self, val: OpaqueStyleAndLayoutData) {
|
unsafe fn init_style_and_layout_data(self, val: OpaqueStyleAndLayoutData) {
|
||||||
debug_assert!((*self.unsafe_get()).style_and_layout_data.get().is_none());
|
let data = &mut *self.unsafe_get().style_and_layout_data.get();
|
||||||
(*self.unsafe_get()).style_and_layout_data.set(Some(val));
|
debug_assert!(data.is_none());
|
||||||
|
*data = Some(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn take_style_and_layout_data(self) -> OpaqueStyleAndLayoutData {
|
unsafe fn take_style_and_layout_data(self) -> OpaqueStyleAndLayoutData {
|
||||||
let val = (*self.unsafe_get()).style_and_layout_data.get().unwrap();
|
(*self.unsafe_get().style_and_layout_data.get())
|
||||||
(*self.unsafe_get()).style_and_layout_data.set(None);
|
.take()
|
||||||
val
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_content(self) -> Cow<'dom, str> {
|
fn text_content(self) -> Cow<'dom, str> {
|
||||||
|
@ -1781,7 +1742,7 @@ impl Node {
|
||||||
inclusive_descendants_version: Cell::new(0),
|
inclusive_descendants_version: Cell::new(0),
|
||||||
ranges: WeakRangeVec::new(),
|
ranges: WeakRangeVec::new(),
|
||||||
|
|
||||||
style_and_layout_data: Cell::new(None),
|
style_and_layout_data: UnsafeCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1399,13 +1399,6 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_js_runtime(&self) {
|
pub fn clear_js_runtime(&self) {
|
||||||
// We tear down the active document, which causes all the attached
|
|
||||||
// nodes to dispose of their layout data. This messages the layout
|
|
||||||
// thread, informing it that it can safely free the memory.
|
|
||||||
self.Document()
|
|
||||||
.upcast::<Node>()
|
|
||||||
.teardown(self.layout_chan());
|
|
||||||
|
|
||||||
// Remove the infra for managing messageports and broadcast channels.
|
// Remove the infra for managing messageports and broadcast channels.
|
||||||
self.upcast::<GlobalScope>().remove_web_messaging_infra();
|
self.upcast::<GlobalScope>().remove_web_messaging_infra();
|
||||||
|
|
||||||
|
|
|
@ -822,23 +822,6 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptThread {
|
impl ScriptThread {
|
||||||
pub(crate) fn get_any_layout_chan() -> Option<Sender<Msg>> {
|
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
|
||||||
let script_thread = match root.get() {
|
|
||||||
Some(s) => unsafe { &*s },
|
|
||||||
None => return None,
|
|
||||||
};
|
|
||||||
script_thread
|
|
||||||
.documents
|
|
||||||
.borrow()
|
|
||||||
.map
|
|
||||||
.values()
|
|
||||||
.next()
|
|
||||||
.map(|d| d.window().layout_chan())
|
|
||||||
.cloned()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn runtime_handle() -> ParentRuntime {
|
pub fn runtime_handle() -> ParentRuntime {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
let script_thread = unsafe { &*root.get().unwrap() };
|
let script_thread = unsafe { &*root.get().unwrap() };
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//! to depend on script.
|
//! to depend on script.
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
#![feature(box_into_raw_non_null)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate html5ever;
|
extern crate html5ever;
|
||||||
|
@ -24,7 +25,7 @@ use libc::c_void;
|
||||||
use net_traits::image_cache::PendingImageId;
|
use net_traits::image_cache::PendingImageId;
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use std::ptr::NonNull;
|
use std::any::Any;
|
||||||
use std::sync::atomic::AtomicIsize;
|
use std::sync::atomic::AtomicIsize;
|
||||||
use style::data::ElementData;
|
use style::data::ElementData;
|
||||||
|
|
||||||
|
@ -49,12 +50,32 @@ impl StyleData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, MallocSizeOf)]
|
#[derive(MallocSizeOf)]
|
||||||
pub struct OpaqueStyleAndLayoutData {
|
pub struct OpaqueStyleAndLayoutData {
|
||||||
// NB: We really store a `StyleAndLayoutData` here, so be careful!
|
// NB: We really store a `StyleAndLayoutData` here, so be careful!
|
||||||
#[ignore_malloc_size_of = "TODO(#6910) Box value that should be counted but \
|
#[ignore_malloc_size_of = "Trait objects are hard"]
|
||||||
the type lives in layout"]
|
ptr: Box<dyn Any + Send + Sync>,
|
||||||
pub ptr: NonNull<StyleData>,
|
}
|
||||||
|
|
||||||
|
impl OpaqueStyleAndLayoutData {
|
||||||
|
#[inline]
|
||||||
|
pub fn new<T>(value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Any + Send + Sync,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
ptr: Box::new(value) as Box<dyn Any + Send + Sync>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extremely cursed.
|
||||||
|
#[inline]
|
||||||
|
pub fn downcast_ref<T>(&self) -> Option<&T>
|
||||||
|
where
|
||||||
|
T: Any + Send + Sync,
|
||||||
|
{
|
||||||
|
self.ptr.downcast_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::rpc::LayoutRPC;
|
use crate::rpc::LayoutRPC;
|
||||||
use crate::{OpaqueStyleAndLayoutData, PendingImage, TrustedNodeAddress};
|
use crate::{PendingImage, TrustedNodeAddress};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use euclid::default::{Point2D, Rect};
|
use euclid::default::{Point2D, Rect};
|
||||||
|
@ -56,11 +56,6 @@ pub enum Msg {
|
||||||
/// field is whether animations should be force-ticked.
|
/// field is whether animations should be force-ticked.
|
||||||
AdvanceClockMs(i32, bool, ImmutableOrigin),
|
AdvanceClockMs(i32, bool, ImmutableOrigin),
|
||||||
|
|
||||||
/// Destroys layout data associated with a DOM node.
|
|
||||||
///
|
|
||||||
/// TODO(pcwalton): Maybe think about batching to avoid message traffic.
|
|
||||||
ReapStyleAndLayoutData(OpaqueStyleAndLayoutData),
|
|
||||||
|
|
||||||
/// Requests that the layout thread measure its memory usage. The resulting reports are sent back
|
/// Requests that the layout thread measure its memory usage. The resulting reports are sent back
|
||||||
/// via the supplied channel.
|
/// via the supplied channel.
|
||||||
CollectReports(ReportsChan),
|
CollectReports(ReportsChan),
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl PseudoElementType {
|
||||||
|
|
||||||
/// Trait to abstract access to layout data across various data structures.
|
/// Trait to abstract access to layout data across various data structures.
|
||||||
pub trait GetLayoutData<'dom> {
|
pub trait GetLayoutData<'dom> {
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
|
||||||
|
@ -224,7 +224,7 @@ pub trait ThreadSafeLayoutNode<'dom>:
|
||||||
.map_or(PseudoElementType::Normal, |el| el.get_pseudo_element_type())
|
.map_or(PseudoElementType::Normal, |el| el.get_pseudo_element_type())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
|
fn get_style_and_layout_data(self) -> Option<&'dom OpaqueStyleAndLayoutData>;
|
||||||
|
|
||||||
fn style(&self, context: &SharedStyleContext) -> Arc<ComputedValues> {
|
fn style(&self, context: &SharedStyleContext) -> Arc<ComputedValues> {
|
||||||
if let Some(el) = self.as_element() {
|
if let Some(el) = self.as_element() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::shared_lock::Locked;
|
||||||
use crate::stylist::CascadeData;
|
use crate::stylist::CascadeData;
|
||||||
use crate::traversal_flags::TraversalFlags;
|
use crate::traversal_flags::TraversalFlags;
|
||||||
use crate::{Atom, LocalName, Namespace, WeakAtom};
|
use crate::{Atom, LocalName, Namespace, WeakAtom};
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
||||||
use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
|
use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
|
||||||
use selectors::sink::Push;
|
use selectors::sink::Push;
|
||||||
use selectors::Element as SelectorsElement;
|
use selectors::Element as SelectorsElement;
|
||||||
|
@ -689,18 +689,14 @@ pub trait TElement:
|
||||||
/// Unsafe following the same reasoning as ensure_data.
|
/// Unsafe following the same reasoning as ensure_data.
|
||||||
unsafe fn clear_data(&self);
|
unsafe fn clear_data(&self);
|
||||||
|
|
||||||
/// Gets a reference to the ElementData container.
|
/// Whether there is an ElementData container.
|
||||||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>>;
|
fn has_data(&self) -> bool;
|
||||||
|
|
||||||
/// Immutably borrows the ElementData.
|
/// Immutably borrows the ElementData.
|
||||||
fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
|
fn borrow_data(&self) -> Option<AtomicRef<ElementData>>;
|
||||||
self.get_data().map(|x| x.borrow())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably borrows the ElementData.
|
/// Mutably borrows the ElementData.
|
||||||
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
|
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>>;
|
||||||
self.get_data().map(|x| x.borrow_mut())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether we should skip any root- or item-based display property
|
/// Whether we should skip any root- or item-based display property
|
||||||
/// blockification on this element. (This function exists so that Gecko
|
/// blockification on this element. (This function exists so that Gecko
|
||||||
|
|
|
@ -557,6 +557,11 @@ impl<'le> fmt::Debug for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> GeckoElement<'le> {
|
impl<'le> GeckoElement<'le> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
|
||||||
|
unsafe { self.0.mServoData.get().as_ref() }
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
|
fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1299,7 +1304,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_handled_snapshot(&self) {
|
unsafe fn set_handled_snapshot(&self) {
|
||||||
debug_assert!(self.get_data().is_some());
|
debug_assert!(self.has_data());
|
||||||
self.set_flags(ELEMENT_HANDLED_SNAPSHOT as u32)
|
self.set_flags(ELEMENT_HANDLED_SNAPSHOT as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1309,7 +1314,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_dirty_descendants(&self) {
|
unsafe fn set_dirty_descendants(&self) {
|
||||||
debug_assert!(self.get_data().is_some());
|
debug_assert!(self.has_data());
|
||||||
debug!("Setting dirty descendants: {:?}", self);
|
debug!("Setting dirty descendants: {:?}", self);
|
||||||
self.set_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
self.set_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
|
||||||
}
|
}
|
||||||
|
@ -1378,13 +1383,23 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
panic!("Atomic child count not implemented in Gecko");
|
panic!("Atomic child count not implemented in Gecko");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
/// Whether there is an ElementData container.
|
||||||
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
|
fn has_data(&self) -> bool {
|
||||||
unsafe { self.0.mServoData.get().as_ref() }
|
self.get_data().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Immutably borrows the ElementData.
|
||||||
|
fn borrow_data(&self) -> Option<AtomicRef<ElementData>> {
|
||||||
|
self.get_data().map(|x| x.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the ElementData.
|
||||||
|
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
|
||||||
|
self.get_data().map(|x| x.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData> {
|
unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData> {
|
||||||
if self.get_data().is_none() {
|
if !self.has_data() {
|
||||||
debug!("Creating ElementData for {:?}", self);
|
debug!("Creating ElementData for {:?}", self);
|
||||||
let ptr = Box::into_raw(Box::new(AtomicRefCell::new(ElementData::default())));
|
let ptr = Box::into_raw(Box::new(AtomicRefCell::new(ElementData::default())));
|
||||||
self.0.mServoData.set(ptr);
|
self.0.mServoData.set(ptr);
|
||||||
|
|
|
@ -90,7 +90,7 @@ pub fn invalidated_descendants<E>(element: E, child: E)
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
if child.get_data().is_none() {
|
if !child.has_data() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -845,7 +845,7 @@ where
|
||||||
//
|
//
|
||||||
// By consequence, any element without data has no descendants with
|
// By consequence, any element without data has no descendants with
|
||||||
// data.
|
// data.
|
||||||
if kid.get_data().is_some() {
|
if kid.has_data() {
|
||||||
kid.clear_data();
|
kid.clear_data();
|
||||||
parents.push(kid);
|
parents.push(kid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@ macro_rules! sizeof_checker (
|
||||||
|
|
||||||
// Update the sizes here
|
// Update the sizes here
|
||||||
sizeof_checker!(size_event_target, EventTarget, 56);
|
sizeof_checker!(size_event_target, EventTarget, 56);
|
||||||
sizeof_checker!(size_node, Node, 176);
|
sizeof_checker!(size_node, Node, 184);
|
||||||
sizeof_checker!(size_element, Element, 352);
|
sizeof_checker!(size_element, Element, 360);
|
||||||
sizeof_checker!(size_htmlelement, HTMLElement, 368);
|
sizeof_checker!(size_htmlelement, HTMLElement, 376);
|
||||||
sizeof_checker!(size_div, HTMLDivElement, 368);
|
sizeof_checker!(size_div, HTMLDivElement, 376);
|
||||||
sizeof_checker!(size_span, HTMLSpanElement, 368);
|
sizeof_checker!(size_span, HTMLSpanElement, 376);
|
||||||
sizeof_checker!(size_text, Text, 208);
|
sizeof_checker!(size_text, Text, 216);
|
||||||
sizeof_checker!(size_characterdata, CharacterData, 208);
|
sizeof_checker!(size_characterdata, CharacterData, 216);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue