diff options
24 files changed, 288 insertions, 386 deletions
diff --git a/components/layout/context.rs b/components/layout/context.rs index a17bc1db4ee..d8d0c8b47a1 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -5,7 +5,6 @@ //! Data needed by the layout thread. use crate::display_list::items::{OpaqueNode, WebRenderImageInfo}; -use crate::opaque_node::OpaqueNodeMethods; use fnv::FnvHasher; use gfx::font_cache_thread::FontCacheThread; use gfx::font_context::FontContext; @@ -121,7 +120,7 @@ impl<'a> LayoutContext<'a> { ImageCacheResult::Pending(id) => { let image = PendingImage { state: PendingImageState::PendingResponse, - node: node.to_untrusted_node_address(), + node: node.into(), id, origin: self.origin.clone(), }; @@ -132,7 +131,7 @@ impl<'a> LayoutContext<'a> { ImageCacheResult::ReadyForRequest(id) => { let image = PendingImage { state: PendingImageState::Unrequested(url), - node: node.to_untrusted_node_address(), + node: node.into(), id, origin: self.origin.clone(), }; diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 98e04f7d93e..3f41157c1cd 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -38,7 +38,6 @@ mod linked_list; mod list_item; mod model; mod multicol; -pub mod opaque_node; pub mod parallel; mod persistent_list; pub mod query; diff --git a/components/layout/opaque_node.rs b/components/layout/opaque_node.rs deleted file mode 100644 index b48820052e9..00000000000 --- a/components/layout/opaque_node.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* 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 crate::display_list::items::OpaqueNode; -use libc::c_void; -use script_traits::UntrustedNodeAddress; - -pub trait OpaqueNodeMethods { - /// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type - /// of node that script expects to receive in a hit test. - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress; -} - -impl OpaqueNodeMethods for OpaqueNode { - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress { - UntrustedNodeAddress(self.0 as *const c_void) - } -} diff --git a/components/layout/query.rs b/components/layout/query.rs index 98a3ec662fb..175ddb2679f 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -11,7 +11,6 @@ use crate::display_list::IndexableText; use crate::flow::{Flow, GetBaseFlow}; use crate::fragment::{Fragment, FragmentBorderBoxIterator, FragmentFlags, SpecificFragmentInfo}; use crate::inline::InlineFragmentNodeFlags; -use crate::opaque_node::OpaqueNodeMethods; use crate::sequential; use crate::wrapper::LayoutNodeLayoutData; use app_units::Au; @@ -1099,7 +1098,7 @@ pub fn process_offset_parent_query( let origin = node_offset_box.offset - parent_info.origin.to_vector(); let size = node_offset_box.rectangle.size; OffsetParentResponse { - node_address: Some(parent_info.node_address.to_untrusted_node_address()), + node_address: Some(parent_info.node_address.into()), rect: Rect::new(origin, size), } }, diff --git a/components/layout_2020/context.rs b/components/layout_2020/context.rs index 1c9a0f7162e..64e51bc3854 100644 --- a/components/layout_2020/context.rs +++ b/components/layout_2020/context.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::display_list::WebRenderImageInfo; -use crate::opaque_node::OpaqueNodeMethods; use fnv::FnvHashMap; use gfx::font_cache_thread::FontCacheThread; use gfx::font_context::FontContext; @@ -75,7 +74,7 @@ impl<'a> LayoutContext<'a> { ImageCacheResult::Pending(id) => { let image = PendingImage { state: PendingImageState::PendingResponse, - node: node.to_untrusted_node_address(), + node: node.into(), id, origin: self.origin.clone(), }; @@ -86,7 +85,7 @@ impl<'a> LayoutContext<'a> { ImageCacheResult::ReadyForRequest(id) => { let image = PendingImage { state: PendingImageState::Unrequested(url), - node: node.to_untrusted_node_address(), + node: node.into(), id, origin: self.origin.clone(), }; diff --git a/components/layout_2020/data.rs b/components/layout_2020/data.rs deleted file mode 100644 index 6df89c80533..00000000000 --- a/components/layout_2020/data.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* 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 crate::element_data::LayoutDataForElement; -use atomic_refcell::AtomicRefCell; -use script_layout_interface::StyleData; - -pub struct StyleAndLayoutData<'dom> { - pub style_data: &'dom StyleData, - pub(super) layout_data: &'dom AtomicRefCell<LayoutDataForElement>, -} diff --git a/components/layout_2020/dom.rs b/components/layout_2020/dom.rs new file mode 100644 index 00000000000..527d2c6c31d --- /dev/null +++ b/components/layout_2020/dom.rs @@ -0,0 +1,203 @@ +/* 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 crate::cell::ArcRefCell; +use crate::context::LayoutContext; +use crate::dom_traversal::WhichPseudoElement; +use crate::flexbox::FlexLevelBox; +use crate::flow::inline::InlineLevelBox; +use crate::flow::BlockLevelBox; +use crate::geom::PhysicalSize; +use crate::replaced::{CanvasInfo, CanvasSource}; +use atomic_refcell::{AtomicRefCell, AtomicRefMut}; +use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use net_traits::image::base::Image as NetImage; +use script_layout_interface::wrapper_traits::{LayoutDataTrait, LayoutNode, ThreadSafeLayoutNode}; +use script_layout_interface::{HTMLCanvasDataSource, StyleData}; +use servo_arc::Arc as ServoArc; +use std::marker::PhantomData; +use std::sync::{Arc, Mutex}; +use style::properties::ComputedValues; + +/// The data that is stored in each DOM node that is used by layout. +#[derive(Default)] +pub struct DOMLayoutData { + pub(super) self_box: ArcRefCell<Option<LayoutBox>>, + pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>, + pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>, +} + +/// A box that is stored in one of the `DOMLayoutData` slots. +pub(super) enum LayoutBox { + DisplayContents, + BlockLevel(ArcRefCell<BlockLevelBox>), + InlineLevel(ArcRefCell<InlineLevelBox>), + FlexLevel(ArcRefCell<FlexLevelBox>), +} + +// The implementation of this trait allows the data to be stored in the DOM. +impl LayoutDataTrait for DOMLayoutData {} + +pub struct StyleAndLayoutData<'dom> { + pub style_data: &'dom StyleData, + pub(super) layout_data: &'dom AtomicRefCell<DOMLayoutData>, +} + +pub struct BoxSlot<'dom> { + pub(crate) slot: Option<ArcRefCell<Option<LayoutBox>>>, + pub(crate) marker: PhantomData<&'dom ()>, +} + +/// A mutable reference to a `LayoutBox` stored in a DOM element. +impl BoxSlot<'_> { + pub(crate) fn new(slot: ArcRefCell<Option<LayoutBox>>) -> Self { + *slot.borrow_mut() = None; + let slot = Some(slot); + Self { + slot, + marker: PhantomData, + } + } + + pub(crate) fn dummy() -> Self { + let slot = None; + Self { + slot, + marker: PhantomData, + } + } + + pub(crate) fn set(mut self, box_: LayoutBox) { + if let Some(slot) = &mut self.slot { + *slot.borrow_mut() = Some(box_); + } + } +} + +impl Drop for BoxSlot<'_> { + fn drop(&mut self) { + if !std::thread::panicking() { + if let Some(slot) = &mut self.slot { + assert!(slot.borrow().is_some(), "failed to set a layout box"); + } + } + } +} + +pub(crate) trait NodeExt<'dom>: 'dom + LayoutNode<'dom> { + /// Returns the image if it’s loaded, and its size in image pixels + /// adjusted for `image_density`. + fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>; + fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>; + fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>; + fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>; + + fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>>; + fn layout_data_mut(self) -> AtomicRefMut<'dom, DOMLayoutData>; + fn element_box_slot(&self) -> BoxSlot<'dom>; + fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>; + fn unset_pseudo_element_box(self, which: WhichPseudoElement); + + /// Remove boxes for the element itself, and its `:before` and `:after` if any. + fn unset_all_boxes(self); +} + +impl<'dom, LayoutNodeType> NodeExt<'dom> for LayoutNodeType +where + LayoutNodeType: 'dom + LayoutNode<'dom>, +{ + fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)> { + let node = self.to_threadsafe(); + let (resource, metadata) = node.image_data()?; + let (width, height) = resource + .as_ref() + .map(|image| (image.width, image.height)) + .or_else(|| metadata.map(|metadata| (metadata.width, metadata.height))) + .unwrap_or((0, 0)); + let (mut width, mut height) = (width as f64, height as f64); + if let Some(density) = node.image_density().filter(|density| *density != 1.) { + width = width / density; + height = height / density; + } + Some((resource, PhysicalSize::new(width, height))) + } + + fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> { + let node = self.to_threadsafe(); + let canvas_data = node.canvas_data()?; + let source = match canvas_data.source { + HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id), + HTMLCanvasDataSource::Image(ipc_sender) => { + CanvasSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer)))) + }, + HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key), + }; + Some(( + CanvasInfo { + source, + canvas_id: canvas_data.canvas_id, + }, + PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()), + )) + } + + fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> { + let node = self.to_threadsafe(); + match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) { + (Some(pipeline_id), Some(browsing_context_id)) => { + Some((pipeline_id, browsing_context_id)) + }, + _ => None, + } + } + + fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues> { + self.to_threadsafe().style(context.shared_context()) + } + + fn layout_data_mut(self) -> AtomicRefMut<'dom, DOMLayoutData> { + self.get_style_and_layout_data() + .map(|d| d.layout_data.borrow_mut()) + .unwrap() + } + + fn element_box_slot(&self) -> BoxSlot<'dom> { + BoxSlot::new(self.layout_data_mut().self_box.clone()) + } + + fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> { + let data = self.layout_data_mut(); + let cell = match which { + WhichPseudoElement::Before => &data.pseudo_before_box, + WhichPseudoElement::After => &data.pseudo_after_box, + }; + BoxSlot::new(cell.clone()) + } + + fn unset_pseudo_element_box(self, which: WhichPseudoElement) { + let data = self.layout_data_mut(); + let cell = match which { + WhichPseudoElement::Before => &data.pseudo_before_box, + WhichPseudoElement::After => &data.pseudo_after_box, + }; + *cell.borrow_mut() = None; + } + + fn unset_all_boxes(self) { + let data = self.layout_data_mut(); + *data.self_box.borrow_mut() = None; + *data.pseudo_before_box.borrow_mut() = None; + *data.pseudo_after_box.borrow_mut() = None; + // Stylo already takes care of removing all layout data + // for DOM descendants of elements with `display: none`. + } + + fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>> { + self.get_style_and_opaque_layout_data() + .map(|data| StyleAndLayoutData { + style_data: &data.style_data, + layout_data: data.generic_data.downcast_ref().unwrap(), + }) + } +} diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index a41bead9d0f..ab20c88c721 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -2,27 +2,15 @@ * 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 crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::element_data::{LayoutBox, LayoutDataForElement}; +use crate::dom::{BoxSlot, LayoutBox, NodeExt}; use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags, Tag}; -use crate::geom::PhysicalSize; -use crate::replaced::{CanvasInfo, CanvasSource, ReplacedContent}; +use crate::replaced::ReplacedContent; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside}; -use crate::wrapper::GetStyleAndLayoutData; -use atomic_refcell::AtomicRefMut; use html5ever::LocalName; -use msg::constellation_msg::{BrowsingContextId, PipelineId}; -use net_traits::image::base::Image as NetImage; -use script_layout_interface::wrapper_traits::{ - LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode, -}; -use script_layout_interface::HTMLCanvasDataSource; +use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode}; use servo_arc::Arc as ServoArc; use std::borrow::Cow; -use std::marker::PhantomData as marker; -use std::sync::{Arc, Mutex}; -use style::dom::{OpaqueNode, TNode}; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; use style::values::generics::counters::Content; @@ -149,9 +137,9 @@ fn traverse_children_of<'dom, Node>( traverse_pseudo_element(WhichPseudoElement::Before, parent_element, context, handler); for child in iter_child_nodes(parent_element) { - if let Some(contents) = child.as_text() { + if child.is_text_node() { let info = NodeAndStyleInfo::new(child, child.style(context)); - handler.handle_text(&info, contents); + handler.handle_text(&info, child.to_threadsafe().node_text_content()); } else if child.is_element() { traverse_element(child, context, handler); } @@ -381,184 +369,6 @@ where } } -pub struct BoxSlot<'dom> { - slot: Option<ArcRefCell<Option<LayoutBox>>>, - marker: marker<&'dom ()>, -} - -impl BoxSlot<'_> { - pub(crate) fn new(slot: ArcRefCell<Option<LayoutBox>>) -> Self { - *slot.borrow_mut() = None; - let slot = Some(slot); - Self { slot, marker } - } - - pub(crate) fn dummy() -> Self { - let slot = None; - Self { slot, marker } - } - - pub(crate) fn set(mut self, box_: LayoutBox) { - if let Some(slot) = &mut self.slot { - *slot.borrow_mut() = Some(box_); - } - } -} - -impl Drop for BoxSlot<'_> { - fn drop(&mut self) { - if !std::thread::panicking() { - if let Some(slot) = &mut self.slot { - assert!(slot.borrow().is_some(), "failed to set a layout box"); - } - } - } -} - -pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync { - fn is_element(self) -> bool; - fn as_text(self) -> Option<Cow<'dom, str>>; - - /// Returns the image if it’s loaded, and its size in image pixels - /// adjusted for `image_density`. - fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)>; - fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)>; - fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)>; - fn first_child(self) -> Option<Self>; - fn next_sibling(self) -> Option<Self>; - fn parent_node(self) -> Option<Self>; - fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues>; - - fn as_opaque(self) -> OpaqueNode; - fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement>; - fn element_box_slot(&self) -> BoxSlot<'dom>; - fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>; - fn unset_pseudo_element_box(self, which: WhichPseudoElement); - - /// Remove boxes for the element itself, and its `:before` and `:after` if any. - fn unset_all_boxes(self); -} - -impl<'dom, T> NodeExt<'dom> for T -where - T: 'dom + Copy + LayoutNode<'dom> + Send + Sync, -{ - fn is_element(self) -> bool { - self.to_threadsafe().as_element().is_some() - } - - fn as_text(self) -> Option<Cow<'dom, str>> { - if self.is_text_node() { - Some(self.to_threadsafe().node_text_content()) - } else { - None - } - } - - fn as_image(self) -> Option<(Option<Arc<NetImage>>, PhysicalSize<f64>)> { - let node = self.to_threadsafe(); - let (resource, metadata) = node.image_data()?; - let (width, height) = resource - .as_ref() - .map(|image| (image.width, image.height)) - .or_else(|| metadata.map(|metadata| (metadata.width, metadata.height))) - .unwrap_or((0, 0)); - let (mut width, mut height) = (width as f64, height as f64); - if let Some(density) = node.image_density().filter(|density| *density != 1.) { - width = width / density; - height = height / density; - } - Some((resource, PhysicalSize::new(width, height))) - } - - fn as_canvas(self) -> Option<(CanvasInfo, PhysicalSize<f64>)> { - let node = self.to_threadsafe(); - let canvas_data = node.canvas_data()?; - let source = match canvas_data.source { - HTMLCanvasDataSource::WebGL(texture_id) => CanvasSource::WebGL(texture_id), - HTMLCanvasDataSource::Image(ipc_sender) => { - CanvasSource::Image(ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer)))) - }, - HTMLCanvasDataSource::WebGPU(image_key) => CanvasSource::WebGPU(image_key), - }; - Some(( - CanvasInfo { - source, - canvas_id: canvas_data.canvas_id, - }, - PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()), - )) - } - - fn as_iframe(self) -> Option<(PipelineId, BrowsingContextId)> { - let node = self.to_threadsafe(); - match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) { - (Some(pipeline_id), Some(browsing_context_id)) => { - Some((pipeline_id, browsing_context_id)) - }, - _ => None, - } - } - - fn first_child(self) -> Option<Self> { - TNode::first_child(&self) - } - - fn next_sibling(self) -> Option<Self> { - TNode::next_sibling(&self) - } - - fn parent_node(self) -> Option<Self> { - TNode::parent_node(&self) - } - - fn style(self, context: &LayoutContext) -> ServoArc<ComputedValues> { - self.to_threadsafe().style(context.shared_context()) - } - - fn as_opaque(self) -> OpaqueNode { - self.opaque() - } - - #[allow(unsafe_code)] - fn layout_data_mut(self) -> AtomicRefMut<'dom, LayoutDataForElement> { - self.get_style_and_layout_data() - .map(|d| d.layout_data.borrow_mut()) - .unwrap() - } - - fn element_box_slot(&self) -> BoxSlot<'dom> { - BoxSlot::new(self.layout_data_mut().self_box.clone()) - } - - fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> { - let data = self.layout_data_mut(); - let cell = match which { - WhichPseudoElement::Before => &data.pseudo_before_box, - WhichPseudoElement::After => &data.pseudo_after_box, - }; - BoxSlot::new(cell.clone()) - } - - fn unset_pseudo_element_box(self, which: WhichPseudoElement) { - let data = self.layout_data_mut(); - let cell = match which { - WhichPseudoElement::Before => &data.pseudo_before_box, - WhichPseudoElement::After => &data.pseudo_after_box, - }; - *cell.borrow_mut() = None; - } - - fn unset_all_boxes(self) { - let data = self.layout_data_mut(); - *data.self_box.borrow_mut() = None; - *data.pseudo_before_box.borrow_mut() = None; - *data.pseudo_after_box.borrow_mut() = None; - // Stylo already takes care of removing all layout data - // for DOM descendants of elements with `display: none`. - } -} - pub(crate) fn iter_child_nodes<'dom, Node>(parent: Node) -> impl Iterator<Item = Node> where Node: NodeExt<'dom>, diff --git a/components/layout_2020/element_data.rs b/components/layout_2020/element_data.rs deleted file mode 100644 index 8963f191d6f..00000000000 --- a/components/layout_2020/element_data.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* 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 crate::cell::ArcRefCell; -use crate::flexbox::FlexLevelBox; -use crate::flow::inline::InlineLevelBox; -use crate::flow::BlockLevelBox; -use script_layout_interface::wrapper_traits::LayoutDataTrait; - -#[derive(Default)] -pub struct LayoutDataForElement { - pub(super) self_box: ArcRefCell<Option<LayoutBox>>, - pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>, - pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>, -} - -pub(super) enum LayoutBox { - DisplayContents, - BlockLevel(ArcRefCell<BlockLevelBox>), - InlineLevel(ArcRefCell<InlineLevelBox>), - FlexLevel(ArcRefCell<FlexLevelBox>), -} - -impl LayoutDataTrait for LayoutDataForElement {} diff --git a/components/layout_2020/flexbox/construct.rs b/components/layout_2020/flexbox/construct.rs index e8848c1dc39..cd21ca85db6 100644 --- a/components/layout_2020/flexbox/construct.rs +++ b/components/layout_2020/flexbox/construct.rs @@ -5,10 +5,8 @@ use super::{FlexContainer, FlexLevelBox}; use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::dom_traversal::{ - BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler, -}; -use crate::element_data::LayoutBox; +use crate::dom::{BoxSlot, LayoutBox, NodeExt}; +use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler}; use crate::formatting_contexts::IndependentFormattingContext; use crate::positioned::AbsolutelyPositionedBox; use crate::style_ext::DisplayGeneratingBox; diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 14b92cafa67..c45965df6e6 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -4,10 +4,8 @@ use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::dom_traversal::{ - BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler, -}; -use crate::element_data::LayoutBox; +use crate::dom::{BoxSlot, LayoutBox, NodeExt}; +use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler}; use crate::flow::float::FloatBox; use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index d7269cbfc4c..eeae46cba61 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -7,7 +7,8 @@ //! See CSS 2.1 § 9.5.1: https://www.w3.org/TR/CSS2/visuren.html#float-position use crate::context::LayoutContext; -use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt}; +use crate::dom::NodeExt; +use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::formatting_contexts::IndependentFormattingContext; use crate::geom::flow_relative::{Rect, Vec2}; use crate::style_ext::DisplayInside; diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index f6eae6ea478..f44b0c88159 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -7,8 +7,8 @@ use crate::context::LayoutContext; use crate::display_list::stacking_context::{ ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode, }; -use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo, NodeExt}; -use crate::element_data::LayoutBox; +use crate::dom::{LayoutBox, NodeExt}; +use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo}; use crate::flexbox::FlexLevelBox; use crate::flow::construct::ContainsFloats; use crate::flow::float::FloatBox; @@ -24,7 +24,6 @@ use crate::positioned::PositioningContext; use crate::replaced::ReplacedContent; use crate::style_ext::ComputedValuesExt; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; -use crate::wrapper::GetStyleAndLayoutData; use crate::DefiniteContainingBlock; use app_units::Au; use atomic_refcell::AtomicRef; diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 98326692b27..d00689c162c 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -3,7 +3,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::context::LayoutContext; -use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt}; +use crate::dom::NodeExt; +use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::flexbox::FlexContainer; use crate::flow::BlockFormattingContext; use crate::fragment_tree::BaseFragmentInfo; diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index a2ceea5fc36..ce737c89258 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -11,10 +11,9 @@ extern crate serde; mod cell; pub mod context; -pub mod data; pub mod display_list; +pub mod dom; mod dom_traversal; -pub mod element_data; mod flexbox; pub mod flow; mod formatting_contexts; @@ -24,14 +23,12 @@ pub mod geom; #[macro_use] pub mod layout_debug; mod lists; -mod opaque_node; mod positioned; pub mod query; mod replaced; mod sizing; mod style_ext; pub mod traversal; -pub mod wrapper; pub use flow::{BoxTree, FragmentTree}; diff --git a/components/layout_2020/lists.rs b/components/layout_2020/lists.rs index 99074747599..e24bc9d542d 100644 --- a/components/layout_2020/lists.rs +++ b/components/layout_2020/lists.rs @@ -3,7 +3,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::context::LayoutContext; -use crate::dom_traversal::{NodeAndStyleInfo, NodeExt, PseudoElementContentItem}; +use crate::dom::NodeExt; +use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem}; use crate::replaced::ReplacedContent; use style::properties::longhands::list_style_type::computed_value::T as ListStyleType; use style::properties::style_structs; diff --git a/components/layout_2020/opaque_node.rs b/components/layout_2020/opaque_node.rs deleted file mode 100644 index 36df7c640f4..00000000000 --- a/components/layout_2020/opaque_node.rs +++ /dev/null @@ -1,17 +0,0 @@ -/* 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 libc::c_void; -use script_traits::UntrustedNodeAddress; -use style::dom::OpaqueNode; - -pub trait OpaqueNodeMethods { - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress; -} - -impl OpaqueNodeMethods for OpaqueNode { - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress { - UntrustedNodeAddress(self.0 as *const c_void) - } -} diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 0a7dd28e945..37f2a0fb321 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -4,7 +4,8 @@ use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt}; +use crate::dom::NodeExt; +use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index 0bea12eaf2d..50722dab917 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::context::LayoutContext; -use crate::dom_traversal::NodeExt; +use crate::dom::NodeExt; use crate::fragment_tree::BaseFragmentInfo; use crate::fragments::{Fragment, IFrameFragment, ImageFragment}; use crate::geom::flow_relative::{Rect, Vec2}; @@ -142,7 +142,7 @@ impl ReplacedContent { }, ); - let base_fragment_info = BaseFragmentInfo::new_for_node(element.as_opaque()); + let base_fragment_info = BaseFragmentInfo::new_for_node(element.opaque()); return Some(Self { kind, intrinsic, @@ -157,7 +157,7 @@ impl ReplacedContent { ) -> Option<Self> { if let ComputedUrl::Valid(image_url) = image_url { let (image, width, height) = match context.get_or_request_image_or_meta( - element.as_opaque(), + element.opaque(), image_url.clone(), UsePlaceholder::No, ) { @@ -178,7 +178,7 @@ impl ReplacedContent { // FIXME https://github.com/w3c/csswg-drafts/issues/4572 ratio: Some(width / height), }, - base_fragment_info: BaseFragmentInfo::new_for_node(element.as_opaque()), + base_fragment_info: BaseFragmentInfo::new_for_node(element.opaque()), }); } None diff --git a/components/layout_2020/traversal.rs b/components/layout_2020/traversal.rs index 7ddb0e85ed4..3063319fec6 100644 --- a/components/layout_2020/traversal.rs +++ b/components/layout_2020/traversal.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::context::LayoutContext; -use crate::wrapper::GetStyleAndLayoutData; +use crate::dom::NodeExt; use script_layout_interface::wrapper_traits::LayoutNode; use style::context::{SharedStyleContext, StyleContext}; use style::data::ElementData; @@ -33,7 +33,7 @@ impl<'a> RecalcStyle<'a> { impl<'a, 'dom, E> DomTraversal<E> for RecalcStyle<'a> where E: TElement, - E::ConcreteNode: LayoutNode<'dom>, + E::ConcreteNode: 'dom + LayoutNode<'dom>, { fn process_preorder<F>( &self, diff --git a/components/layout_2020/wrapper.rs b/components/layout_2020/wrapper.rs deleted file mode 100644 index 635889dc92e..00000000000 --- a/components/layout_2020/wrapper.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* 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/. */ - -#![allow(unsafe_code)] - -use crate::data::StyleAndLayoutData; -use script_layout_interface::wrapper_traits::GetStyleAndOpaqueLayoutData; - -pub trait GetStyleAndLayoutData<'dom> { - fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>>; -} - -impl<'dom, T> GetStyleAndLayoutData<'dom> for T -where - T: GetStyleAndOpaqueLayoutData<'dom>, -{ - fn get_style_and_layout_data(self) -> Option<StyleAndLayoutData<'dom>> { - self.get_style_and_opaque_layout_data() - .map(|data| StyleAndLayoutData { - style_data: &data.style_data, - layout_data: data.generic_data.downcast_ref().unwrap(), - }) - } -} diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index ddfbc69222f..90c6f4da952 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -30,7 +30,7 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use layout::context::LayoutContext; use layout::display_list::{DisplayListBuilder, WebRenderImageInfo}; -use layout::element_data::LayoutDataForElement; +use layout::dom::DOMLayoutData; use layout::layout_debug; use layout::query::{ process_content_box_request, process_content_boxes_request, process_resolved_font_style_query, @@ -801,7 +801,7 @@ impl LayoutThread { data: &mut ScriptReflowResult, possibly_locked_rw_data: &mut RwData<'a, 'b>, ) { - let document = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&data.document) }; + let document = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&data.document) }; let document = document.as_document().unwrap(); let mut rw_data = possibly_locked_rw_data.lock(); @@ -957,7 +957,7 @@ impl LayoutThread { .iter() .filter(|r| r.1.snapshot.is_some()) .map(|r| unsafe { - ServoLayoutNode::<LayoutDataForElement>::new(&r.0) + ServoLayoutNode::<DOMLayoutData>::new(&r.0) .as_element() .unwrap() }) @@ -965,7 +965,7 @@ impl LayoutThread { for (el, restyle) in restyles { let el = unsafe { - ServoLayoutNode::<LayoutDataForElement>::new(&el) + ServoLayoutNode::<DOMLayoutData>::new(&el) .as_element() .unwrap() }; @@ -1004,16 +1004,15 @@ impl LayoutThread { ); let dirty_root = unsafe { - ServoLayoutNode::<LayoutDataForElement>::new(&data.dirty_root.unwrap()) + ServoLayoutNode::<DOMLayoutData>::new(&data.dirty_root.unwrap()) .as_element() .unwrap() }; let traversal = RecalcStyle::new(layout_context); let token = { - let shared = DomTraversal::<ServoLayoutElement<LayoutDataForElement>>::shared_context( - &traversal, - ); + let shared = + DomTraversal::<ServoLayoutElement<DOMLayoutData>>::shared_context(&traversal); RecalcStyle::pre_traverse(dirty_root, shared) }; @@ -1021,7 +1020,7 @@ impl LayoutThread { let rayon_pool = rayon_pool.as_ref(); if token.should_traverse() { - let dirty_root: ServoLayoutNode<LayoutDataForElement> = + let dirty_root: ServoLayoutNode<DOMLayoutData> = driver::traverse_dom(&traversal, token, rayon_pool).as_node(); let root_node = root_element.as_node(); @@ -1134,12 +1133,12 @@ impl LayoutThread { process_node_scroll_area_request(node, self.fragment_tree.borrow().clone()); }, &QueryMsg::NodeScrollIdQuery(node) => { - let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) }; + let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) }; rw_data.scroll_id_response = Some(process_node_scroll_id_request(self.id, node)); }, &QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => { - let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) }; + let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) }; let fragment_tree = self.fragment_tree.borrow().clone(); rw_data.resolved_style_response = process_resolved_style_request( context, @@ -1150,7 +1149,7 @@ impl LayoutThread { ); }, &QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => { - let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) }; + let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) }; rw_data.resolved_font_style_response = process_resolved_font_style_query(node, property, value); }, @@ -1180,7 +1179,7 @@ impl LayoutThread { results.iter().map(|result| result.node).collect() }, &QueryMsg::ElementInnerTextQuery(node) => { - let node = unsafe { ServoLayoutNode::<LayoutDataForElement>::new(&node) }; + let node = unsafe { ServoLayoutNode::<DOMLayoutData>::new(&node) }; rw_data.element_inner_text_response = process_element_inner_text_query(node); }, &QueryMsg::InnerWindowDimensionsQuery(_browsing_context_id) => { @@ -1240,7 +1239,7 @@ impl LayoutThread { &self, fragment_tree: Arc<FragmentTree>, reflow_goal: &ReflowGoal, - document: Option<&ServoLayoutDocument<LayoutDataForElement>>, + document: Option<&ServoLayoutDocument<DOMLayoutData>>, context: &mut LayoutContext, ) { Self::cancel_animations_for_nodes_not_in_fragment_tree( diff --git a/components/script/layout_dom/node.rs b/components/script/layout_dom/node.rs index 6d5eaecd5f1..22d28b9e165 100644 --- a/components/script/layout_dom/node.rs +++ b/components/script/layout_dom/node.rs @@ -21,8 +21,8 @@ use msg::constellation_msg::{BrowsingContextId, PipelineId}; use net_traits::image::base::{Image, ImageMetadata}; use range::Range; use script_layout_interface::wrapper_traits::{ - DangerousThreadSafeLayoutNode, GetStyleAndOpaqueLayoutData, LayoutDataTrait, LayoutNode, - PseudoElementType, ThreadSafeLayoutNode, + GetStyleAndOpaqueLayoutData, LayoutDataTrait, LayoutNode, PseudoElementType, + ThreadSafeLayoutNode, }; use script_layout_interface::{ HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGSVGData, StyleAndOpaqueLayoutData, StyleData, @@ -280,23 +280,6 @@ impl<'lr, LayoutDataType: LayoutDataTrait> fmt::Debug } } -impl<'dom, LayoutDataType: LayoutDataTrait> DangerousThreadSafeLayoutNode<'dom> - for ServoThreadSafeLayoutNode<'dom, LayoutDataType> -{ - unsafe fn dangerous_first_child(&self) -> Option<Self> { - self.get_jsmanaged() - .first_child_ref() - .map(ServoLayoutNode::from_layout_js) - .map(Self::new) - } - unsafe fn dangerous_next_sibling(&self) -> Option<Self> { - self.get_jsmanaged() - .next_sibling_ref() - .map(ServoLayoutNode::from_layout_js) - .map(Self::new) - } -} - impl<'dom, LayoutDataType: LayoutDataTrait> ServoThreadSafeLayoutNode<'dom, LayoutDataType> { /// Creates a new `ServoThreadSafeLayoutNode` from the given `ServoLayoutNode`. pub fn new(node: ServoLayoutNode<'dom, LayoutDataType>) -> Self { @@ -311,6 +294,24 @@ impl<'dom, LayoutDataType: LayoutDataTrait> ServoThreadSafeLayoutNode<'dom, Layo unsafe fn get_jsmanaged(&self) -> LayoutDom<'dom, Node> { self.node.get_jsmanaged() } + + /// Get the first child of this node. Important: this is not safe for + /// layout to call, so it should *never* be made public. + unsafe fn dangerous_first_child(&self) -> Option<Self> { + self.get_jsmanaged() + .first_child_ref() + .map(ServoLayoutNode::from_layout_js) + .map(Self::new) + } + + /// Get the next sibling of this node. Important: this is not safe for + /// layout to call, so it should *never* be made public. + unsafe fn dangerous_next_sibling(&self) -> Option<Self> { + self.get_jsmanaged() + .next_sibling_ref() + .map(ServoLayoutNode::from_layout_js) + .map(Self::new) + } } impl<'dom, LayoutDataType: LayoutDataTrait> style::dom::NodeInfo @@ -331,7 +332,7 @@ impl<'dom, LayoutDataType: LayoutDataTrait> ThreadSafeLayoutNode<'dom> type ConcreteNode = ServoLayoutNode<'dom, LayoutDataType>; type ConcreteThreadSafeLayoutElement = ServoThreadSafeLayoutElement<'dom, LayoutDataType>; type ConcreteElement = ServoLayoutElement<'dom, LayoutDataType>; - type ChildrenIterator = ThreadSafeLayoutNodeChildrenIterator<Self>; + type ChildrenIterator = ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType>; fn opaque(&self) -> style::dom::OpaqueNode { unsafe { self.get_jsmanaged().opaque() } @@ -357,11 +358,11 @@ impl<'dom, LayoutDataType: LayoutDataTrait> ThreadSafeLayoutNode<'dom> fn children(&self) -> style::dom::LayoutIterator<Self::ChildrenIterator> { if let Some(shadow) = self.node.as_element().and_then(|e| e.shadow_root()) { - return style::dom::LayoutIterator(ThreadSafeLayoutNodeChildrenIterator::new( + return style::dom::LayoutIterator(ServoThreadSafeLayoutNodeChildrenIterator::new( shadow.as_node().to_threadsafe(), )); } - style::dom::LayoutIterator(ThreadSafeLayoutNodeChildrenIterator::new(*self)) + style::dom::LayoutIterator(ServoThreadSafeLayoutNodeChildrenIterator::new(*self)) } fn as_element(&self) -> Option<ServoThreadSafeLayoutElement<'dom, LayoutDataType>> { @@ -482,17 +483,16 @@ impl<'dom, LayoutDataType: LayoutDataTrait> ThreadSafeLayoutNode<'dom> } } -pub struct ThreadSafeLayoutNodeChildrenIterator<ConcreteNode> { - current_node: Option<ConcreteNode>, - parent_node: ConcreteNode, +pub struct ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType: LayoutDataTrait> { + current_node: Option<ServoThreadSafeLayoutNode<'dom, LayoutDataType>>, + parent_node: ServoThreadSafeLayoutNode<'dom, LayoutDataType>, } -impl<'dom, ConcreteNode> ThreadSafeLayoutNodeChildrenIterator<ConcreteNode> -where - ConcreteNode: DangerousThreadSafeLayoutNode<'dom>, +impl<'dom, LayoutDataType: LayoutDataTrait> + ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType> { - pub fn new(parent: ConcreteNode) -> Self { - let first_child: Option<ConcreteNode> = match parent.get_pseudo_element_type() { + pub fn new(parent: ServoThreadSafeLayoutNode<'dom, LayoutDataType>) -> Self { + let first_child = match parent.get_pseudo_element_type() { PseudoElementType::Normal => parent .get_before_pseudo() .or_else(|| parent.get_details_summary_pseudo()) @@ -502,19 +502,18 @@ where }, _ => None, }; - ThreadSafeLayoutNodeChildrenIterator { + ServoThreadSafeLayoutNodeChildrenIterator { current_node: first_child, parent_node: parent, } } } -impl<'dom, ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNode> -where - ConcreteNode: DangerousThreadSafeLayoutNode<'dom>, +impl<'dom, LayoutDataType: LayoutDataTrait> Iterator + for ServoThreadSafeLayoutNodeChildrenIterator<'dom, LayoutDataType> { - type Item = ConcreteNode; - fn next(&mut self) -> Option<ConcreteNode> { + type Item = ServoThreadSafeLayoutNode<'dom, LayoutDataType>; + fn next(&mut self) -> Option<ServoThreadSafeLayoutNode<'dom, LayoutDataType>> { use selectors::Element; match self.parent_node.get_pseudo_element_type() { PseudoElementType::Before | PseudoElementType::After => None, diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 8ba009a7a47..0901653b762 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -86,7 +86,12 @@ pub trait GetStyleAndOpaqueLayoutData<'dom> { /// 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`. -pub trait LayoutNode<'dom>: Debug + GetStyleAndOpaqueLayoutData<'dom> + TNode { +/// FIXME(mrobinson): `Send + Sync` is required here for Layout 2020, but eventually it +/// should stop sending LayoutNodes to other threads and rely on ThreadSafeLayoutNode +/// or some other mechanism to ensure thread safety. +pub trait LayoutNode<'dom>: + Copy + Debug + GetStyleAndOpaqueLayoutData<'dom> + TNode + Send + Sync +{ type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'dom>; fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode; @@ -306,14 +311,6 @@ pub trait ThreadSafeLayoutNode<'dom>: } } -// This trait is only public so that it can be implemented by the gecko wrapper. -// It can be used to violate thread-safety, so don't use it elsewhere in layout! -#[allow(unsafe_code)] -pub trait DangerousThreadSafeLayoutNode<'dom>: ThreadSafeLayoutNode<'dom> { - unsafe fn dangerous_first_child(&self) -> Option<Self>; - unsafe fn dangerous_next_sibling(&self) -> Option<Self>; -} - pub trait ThreadSafeLayoutElement<'dom>: Clone + Copy |