mirror of
https://github.com/servo/servo.git
synced 2025-10-02 01:29:15 +01:00
layout: Use ServoThreadSafeLayoutNode
in more places (#38626)
Use `ServoThreadSafeLayoutNode` in more places in layout rather than `ServoLayoutNode`. The former is meant to be used during layout, but layout 2020 was written against the latter. In general, this reduces the amount of conversion to the thread-safe version in many places in layout. In addition, an unused iterator from the `script` crate `ServoThreadSafeLayoutNodeChildrenIterator` is replaced with the child iterator from `layout`. The `layout` version must be directly in `script` now as it uses the dangerous variants of `next_sibling` and `first_child`, which allow encapsulating the unsafe bits into one module. This will ultimately be useful for storing the layout data of pseudo-element children of pseudo-elements properly. Testing: This should not change any behavior and thus is covered by existing tests. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
20ad1ce84e
commit
ee7c1d9109
20 changed files with 258 additions and 321 deletions
|
@ -9,6 +9,7 @@ use euclid::Size2D;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use fonts::FontContext;
|
use fonts::FontContext;
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
|
use layout_api::wrapper_traits::ThreadSafeLayoutNode;
|
||||||
use layout_api::{
|
use layout_api::{
|
||||||
IFrameSizes, ImageAnimationState, PendingImage, PendingImageState, PendingRasterizationImage,
|
IFrameSizes, ImageAnimationState, PendingImage, PendingImageState, PendingRasterizationImage,
|
||||||
};
|
};
|
||||||
|
@ -18,9 +19,10 @@ use net_traits::image_cache::{
|
||||||
};
|
};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use pixels::RasterImage;
|
use pixels::RasterImage;
|
||||||
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::dom::{OpaqueNode, TNode};
|
use style::dom::OpaqueNode;
|
||||||
use style::values::computed::image::{Gradient, Image};
|
use style::values::computed::image::{Gradient, Image};
|
||||||
use webrender_api::units::{DeviceIntSize, DeviceSize};
|
use webrender_api::units::{DeviceIntSize, DeviceSize};
|
||||||
|
|
||||||
|
@ -247,7 +249,7 @@ impl ImageResolver {
|
||||||
|
|
||||||
pub(crate) fn queue_svg_element_for_serialization(
|
pub(crate) fn queue_svg_element_for_serialization(
|
||||||
&self,
|
&self,
|
||||||
element: script::layout_dom::ServoLayoutNode<'_>,
|
element: ServoThreadSafeLayoutNode<'_>,
|
||||||
) {
|
) {
|
||||||
self.pending_svg_elements_for_serialization
|
self.pending_svg_elements_for_serialization
|
||||||
.lock()
|
.lock()
|
||||||
|
|
|
@ -2,22 +2,19 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::any::Any;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
use base::id::{BrowsingContextId, PipelineId};
|
use base::id::{BrowsingContextId, PipelineId};
|
||||||
use html5ever::{local_name, ns};
|
use html5ever::{local_name, ns};
|
||||||
use layout_api::wrapper_traits::{
|
use layout_api::wrapper_traits::{LayoutDataTrait, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||||
LayoutDataTrait, LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
|
||||||
};
|
|
||||||
use layout_api::{
|
use layout_api::{
|
||||||
GenericLayoutDataTrait, LayoutDamage, LayoutElementType,
|
GenericLayoutDataTrait, LayoutDamage, LayoutElementType,
|
||||||
LayoutNodeType as ScriptLayoutNodeType, SVGElementData,
|
LayoutNodeType as ScriptLayoutNodeType, SVGElementData,
|
||||||
};
|
};
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use net_traits::image_cache::Image;
|
use net_traits::image_cache::Image;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
|
@ -116,13 +113,13 @@ impl LayoutBox {
|
||||||
fn repair_style(
|
fn repair_style(
|
||||||
&self,
|
&self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &ServoArc<ComputedValues>,
|
new_style: &ServoArc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
LayoutBox::DisplayContents(inline_shared_styles) => {
|
LayoutBox::DisplayContents(inline_shared_styles) => {
|
||||||
*inline_shared_styles.style.borrow_mut() = new_style.clone();
|
*inline_shared_styles.style.borrow_mut() = new_style.clone();
|
||||||
*inline_shared_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
|
*inline_shared_styles.selected.borrow_mut() = node.selected_style();
|
||||||
},
|
},
|
||||||
LayoutBox::BlockLevel(block_level_box) => {
|
LayoutBox::BlockLevel(block_level_box) => {
|
||||||
block_level_box
|
block_level_box
|
||||||
|
@ -172,7 +169,7 @@ pub struct DOMLayoutData(AtomicRefCell<InnerDOMLayoutData>);
|
||||||
// The implementation of this trait allows the data to be stored in the DOM.
|
// The implementation of this trait allows the data to be stored in the DOM.
|
||||||
impl LayoutDataTrait for DOMLayoutData {}
|
impl LayoutDataTrait for DOMLayoutData {}
|
||||||
impl GenericLayoutDataTrait for DOMLayoutData {
|
impl GenericLayoutDataTrait for DOMLayoutData {
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn std::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +232,6 @@ pub(crate) trait NodeExt<'dom> {
|
||||||
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>;
|
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)>;
|
||||||
fn as_svg(&self) -> Option<SVGElementData>;
|
fn as_svg(&self) -> Option<SVGElementData>;
|
||||||
fn as_typeless_object_with_data_attribute(&self) -> Option<String>;
|
fn as_typeless_object_with_data_attribute(&self) -> Option<String>;
|
||||||
fn style(&self, context: &SharedStyleContext) -> ServoArc<ComputedValues>;
|
|
||||||
|
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
|
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
|
||||||
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
|
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
|
||||||
|
@ -255,10 +251,9 @@ pub(crate) trait NodeExt<'dom> {
|
||||||
fn take_restyle_damage(&self) -> LayoutDamage;
|
fn take_restyle_damage(&self) -> LayoutDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
impl<'dom> NodeExt<'dom> for ServoThreadSafeLayoutNode<'dom> {
|
||||||
fn as_image(&self) -> Option<(Option<Image>, PhysicalSize<f64>)> {
|
fn as_image(&self) -> Option<(Option<Image>, PhysicalSize<f64>)> {
|
||||||
let node = self.to_threadsafe();
|
let (resource, metadata) = self.image_data()?;
|
||||||
let (resource, metadata) = node.image_data()?;
|
|
||||||
let (width, height) = resource
|
let (width, height) = resource
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|image| {
|
.map(|image| {
|
||||||
|
@ -268,7 +263,7 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
.or_else(|| metadata.map(|metadata| (metadata.width, metadata.height)))
|
.or_else(|| metadata.map(|metadata| (metadata.width, metadata.height)))
|
||||||
.unwrap_or((0, 0));
|
.unwrap_or((0, 0));
|
||||||
let (mut width, mut height) = (width as f64, height as f64);
|
let (mut width, mut height) = (width as f64, height as f64);
|
||||||
if let Some(density) = node.image_density().filter(|density| *density != 1.) {
|
if let Some(density) = self.image_density().filter(|density| *density != 1.) {
|
||||||
width /= density;
|
width /= density;
|
||||||
height /= density;
|
height /= density;
|
||||||
}
|
}
|
||||||
|
@ -276,12 +271,11 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_svg(&self) -> Option<SVGElementData> {
|
fn as_svg(&self) -> Option<SVGElementData> {
|
||||||
self.to_threadsafe().svg_data()
|
self.svg_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)> {
|
fn as_video(&self) -> Option<(Option<webrender_api::ImageKey>, Option<PhysicalSize<f64>>)> {
|
||||||
let node = self.to_threadsafe();
|
let data = self.media_data()?;
|
||||||
let data = node.media_data()?;
|
|
||||||
let natural_size = if let Some(frame) = data.current_frame {
|
let natural_size = if let Some(frame) = data.current_frame {
|
||||||
Some(PhysicalSize::new(frame.width.into(), frame.height.into()))
|
Some(PhysicalSize::new(frame.width.into(), frame.height.into()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -295,8 +289,7 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
|
fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
|
||||||
let node = self.to_threadsafe();
|
let canvas_data = self.canvas_data()?;
|
||||||
let canvas_data = node.canvas_data()?;
|
|
||||||
let source = canvas_data.source;
|
let source = canvas_data.source;
|
||||||
Some((
|
Some((
|
||||||
CanvasInfo { source },
|
CanvasInfo { source },
|
||||||
|
@ -305,8 +298,7 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_iframe(&self) -> Option<(PipelineId, BrowsingContextId)> {
|
fn as_iframe(&self) -> Option<(PipelineId, BrowsingContextId)> {
|
||||||
let node = self.to_threadsafe();
|
match (self.iframe_pipeline_id(), self.iframe_browsing_context_id()) {
|
||||||
match (node.iframe_pipeline_id(), node.iframe_browsing_context_id()) {
|
|
||||||
(Some(pipeline_id), Some(browsing_context_id)) => {
|
(Some(pipeline_id), Some(browsing_context_id)) => {
|
||||||
Some((pipeline_id, browsing_context_id))
|
Some((pipeline_id, browsing_context_id))
|
||||||
},
|
},
|
||||||
|
@ -315,8 +307,10 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_typeless_object_with_data_attribute(&self) -> Option<String> {
|
fn as_typeless_object_with_data_attribute(&self) -> Option<String> {
|
||||||
if LayoutNode::type_id(self) !=
|
if self.type_id() !=
|
||||||
ScriptLayoutNodeType::Element(LayoutElementType::HTMLObjectElement)
|
Some(ScriptLayoutNodeType::Element(
|
||||||
|
LayoutElementType::HTMLObjectElement,
|
||||||
|
))
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -324,7 +318,7 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
// TODO: This is the what the legacy layout system did, but really if Servo
|
// TODO: This is the what the legacy layout system did, but really if Servo
|
||||||
// supports any `<object>` that's an image, it should support those with URLs
|
// supports any `<object>` that's an image, it should support those with URLs
|
||||||
// and `type` attributes with image mime types.
|
// and `type` attributes with image mime types.
|
||||||
let element = self.to_threadsafe().as_element()?;
|
let element = self.as_element()?;
|
||||||
if element.get_attr(&ns!(), &local_name!("type")).is_some() {
|
if element.get_attr(&ns!(), &local_name!("type")).is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -333,15 +327,11 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
.map(|string| string.to_owned())
|
.map(|string| string.to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self, context: &SharedStyleContext) -> ServoArc<ComputedValues> {
|
|
||||||
self.to_threadsafe().style(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
|
fn layout_data_mut(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
|
||||||
if LayoutNode::layout_data(self).is_none() {
|
if ThreadSafeLayoutNode::layout_data(self).is_none() {
|
||||||
self.initialize_layout_data::<DOMLayoutData>();
|
self.initialize_layout_data::<DOMLayoutData>();
|
||||||
}
|
}
|
||||||
LayoutNode::layout_data(self)
|
ThreadSafeLayoutNode::layout_data(self)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<DOMLayoutData>()
|
.downcast_ref::<DOMLayoutData>()
|
||||||
|
@ -351,7 +341,7 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
|
fn layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
|
||||||
LayoutNode::layout_data(self).map(|data| {
|
ThreadSafeLayoutNode::layout_data(self).map(|data| {
|
||||||
data.as_any()
|
data.as_any()
|
||||||
.downcast_ref::<DOMLayoutData>()
|
.downcast_ref::<DOMLayoutData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -416,13 +406,13 @@ impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
|
||||||
fn repair_style(&self, context: &SharedStyleContext) {
|
fn repair_style(&self, context: &SharedStyleContext) {
|
||||||
let data = self.layout_data_mut();
|
let data = self.layout_data_mut();
|
||||||
if let Some(layout_object) = &*data.self_box.borrow() {
|
if let Some(layout_object) = &*data.self_box.borrow() {
|
||||||
let style = self.to_threadsafe().style(context);
|
let style = self.style(context);
|
||||||
layout_object.repair_style(context, self, &style);
|
layout_object.repair_style(context, self, &style);
|
||||||
}
|
}
|
||||||
|
|
||||||
for pseudo_layout_data in data.pseudo_boxes.iter() {
|
for pseudo_layout_data in data.pseudo_boxes.iter() {
|
||||||
if let Some(layout_box) = pseudo_layout_data.box_slot.borrow().as_ref() {
|
if let Some(layout_box) = pseudo_layout_data.box_slot.borrow().as_ref() {
|
||||||
if let Some(node) = self.to_threadsafe().with_pseudo(pseudo_layout_data.pseudo) {
|
if let Some(node) = self.with_pseudo(pseudo_layout_data.pseudo) {
|
||||||
layout_box.repair_style(context, self, &node.style(context));
|
layout_box.repair_style(context, self, &node.style(context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
* 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 std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter::FusedIterator;
|
|
||||||
|
|
||||||
use fonts::ByteIndex;
|
use fonts::ByteIndex;
|
||||||
use html5ever::{LocalName, local_name};
|
use html5ever::{LocalName, local_name};
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
use layout_api::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||||
use layout_api::{LayoutDamage, LayoutElementType, LayoutNodeType};
|
use layout_api::{LayoutDamage, LayoutElementType, LayoutNodeType};
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use selectors::Element as SelectorsElement;
|
use selectors::Element as SelectorsElement;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use style::dom::{NodeInfo, TElement, TNode, TShadowRoot};
|
use style::dom::NodeInfo;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::selector_parser::PseudoElement;
|
use style::selector_parser::PseudoElement;
|
||||||
use style::values::generics::counters::{Content, ContentItem};
|
use style::values::generics::counters::{Content, ContentItem};
|
||||||
|
@ -31,7 +30,7 @@ use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOuts
|
||||||
/// avoid having to repeat the same arguments in argument lists.
|
/// avoid having to repeat the same arguments in argument lists.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct NodeAndStyleInfo<'dom> {
|
pub(crate) struct NodeAndStyleInfo<'dom> {
|
||||||
pub node: ServoLayoutNode<'dom>,
|
pub node: ServoThreadSafeLayoutNode<'dom>,
|
||||||
pub pseudo_element_type: Option<PseudoElement>,
|
pub pseudo_element_type: Option<PseudoElement>,
|
||||||
pub style: ServoArc<ComputedValues>,
|
pub style: ServoArc<ComputedValues>,
|
||||||
pub damage: LayoutDamage,
|
pub damage: LayoutDamage,
|
||||||
|
@ -39,7 +38,7 @@ pub(crate) struct NodeAndStyleInfo<'dom> {
|
||||||
|
|
||||||
impl<'dom> NodeAndStyleInfo<'dom> {
|
impl<'dom> NodeAndStyleInfo<'dom> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
node: ServoLayoutNode<'dom>,
|
node: ServoThreadSafeLayoutNode<'dom>,
|
||||||
style: ServoArc<ComputedValues>,
|
style: ServoArc<ComputedValues>,
|
||||||
damage: LayoutDamage,
|
damage: LayoutDamage,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -59,7 +58,7 @@ impl<'dom> NodeAndStyleInfo<'dom> {
|
||||||
// workaround for past version of input element where we are
|
// workaround for past version of input element where we are
|
||||||
// rendering it as a bare html element.
|
// rendering it as a bare html element.
|
||||||
pub(crate) fn is_single_line_text_input(&self) -> bool {
|
pub(crate) fn is_single_line_text_input(&self) -> bool {
|
||||||
self.node.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLInputElement) ||
|
self.node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) ||
|
||||||
self.node.is_text_container_of_single_line_input()
|
self.node.is_text_container_of_single_line_input()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +69,6 @@ impl<'dom> NodeAndStyleInfo<'dom> {
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
let style = self
|
let style = self
|
||||||
.node
|
.node
|
||||||
.to_threadsafe()
|
|
||||||
.as_element()?
|
.as_element()?
|
||||||
.with_pseudo(pseudo_element_type)?
|
.with_pseudo(pseudo_element_type)?
|
||||||
.style(&context.style_context);
|
.style(&context.style_context);
|
||||||
|
@ -82,31 +80,15 @@ impl<'dom> NodeAndStyleInfo<'dom> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_selected_style(&self) -> ServoArc<ComputedValues> {
|
|
||||||
// This is a workaround for handling the `::selection` pseudos where it would not
|
|
||||||
// propagate to the children and Shadow DOM elements. For this case, UA widget
|
|
||||||
// inner elements should follow the originating element in terms of selection.
|
|
||||||
if self.node.is_in_ua_widget() {
|
|
||||||
self.node
|
|
||||||
.containing_shadow_host()
|
|
||||||
.expect("Ua widget inner editor is not contained")
|
|
||||||
.to_threadsafe()
|
|
||||||
.selected_style()
|
|
||||||
} else {
|
|
||||||
self.node.to_threadsafe().selected_style()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_selection_range(&self) -> Option<Range<ByteIndex>> {
|
pub(crate) fn get_selection_range(&self) -> Option<Range<ByteIndex>> {
|
||||||
self.node.to_threadsafe().selection()
|
self.node.selection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> From<&NodeAndStyleInfo<'dom>> for BaseFragmentInfo {
|
impl<'dom> From<&NodeAndStyleInfo<'dom>> for BaseFragmentInfo {
|
||||||
fn from(info: &NodeAndStyleInfo<'dom>) -> Self {
|
fn from(info: &NodeAndStyleInfo<'dom>) -> Self {
|
||||||
let node = info.node;
|
let threadsafe_node = info.node;
|
||||||
let pseudo = info.pseudo_element_type;
|
let pseudo = info.pseudo_element_type;
|
||||||
let threadsafe_node = node.to_threadsafe();
|
|
||||||
let mut flags = FragmentFlags::empty();
|
let mut flags = FragmentFlags::empty();
|
||||||
|
|
||||||
// Anonymous boxes should not have a tag, because they should not take part in hit testing.
|
// Anonymous boxes should not have a tag, because they should not take part in hit testing.
|
||||||
|
@ -218,21 +200,21 @@ fn traverse_children_of<'dom>(
|
||||||
// special case after the implementation of UA Shadow DOM for
|
// special case after the implementation of UA Shadow DOM for
|
||||||
// all affected input elements.
|
// all affected input elements.
|
||||||
if parent_element_info.node.is_text_input() {
|
if parent_element_info.node.is_text_input() {
|
||||||
let node_text_content = parent_element_info.node.to_threadsafe().node_text_content();
|
let node_text_content = parent_element_info.node.node_text_content();
|
||||||
if node_text_content.is_empty() {
|
if node_text_content.is_empty() {
|
||||||
handler.handle_text(parent_element_info, "\u{200B}".into());
|
handler.handle_text(parent_element_info, "\u{200B}".into());
|
||||||
} else {
|
} else {
|
||||||
handler.handle_text(parent_element_info, node_text_content);
|
handler.handle_text(parent_element_info, node_text_content);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for child in iter_child_nodes(parent_element_info.node) {
|
for child in parent_element_info.node.children() {
|
||||||
if child.is_text_node() {
|
if child.is_text_node() {
|
||||||
let info = NodeAndStyleInfo::new(
|
let info = NodeAndStyleInfo::new(
|
||||||
child,
|
child,
|
||||||
child.style(&context.style_context),
|
child.style(&context.style_context),
|
||||||
child.take_restyle_damage(),
|
child.take_restyle_damage(),
|
||||||
);
|
);
|
||||||
handler.handle_text(&info, child.to_threadsafe().node_text_content());
|
handler.handle_text(&info, child.node_text_content());
|
||||||
} else if child.is_element() {
|
} else if child.is_element() {
|
||||||
traverse_element(child, context, handler);
|
traverse_element(child, context, handler);
|
||||||
}
|
}
|
||||||
|
@ -243,7 +225,7 @@ fn traverse_children_of<'dom>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_element<'dom>(
|
fn traverse_element<'dom>(
|
||||||
element: ServoLayoutNode<'dom>,
|
element: ServoThreadSafeLayoutNode<'dom>,
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
handler: &mut impl TraversalHandler<'dom>,
|
handler: &mut impl TraversalHandler<'dom>,
|
||||||
) {
|
) {
|
||||||
|
@ -277,9 +259,9 @@ fn traverse_element<'dom>(
|
||||||
Contents::Replaced(replaced)
|
Contents::Replaced(replaced)
|
||||||
} else if matches!(
|
} else if matches!(
|
||||||
element.type_id(),
|
element.type_id(),
|
||||||
LayoutNodeType::Element(
|
Some(LayoutNodeType::Element(
|
||||||
LayoutElementType::HTMLInputElement | LayoutElementType::HTMLTextAreaElement
|
LayoutElementType::HTMLInputElement | LayoutElementType::HTMLTextAreaElement
|
||||||
)
|
))
|
||||||
) {
|
) {
|
||||||
NonReplacedContents::OfTextControl.into()
|
NonReplacedContents::OfTextControl.into()
|
||||||
} else {
|
} else {
|
||||||
|
@ -430,7 +412,6 @@ fn generate_pseudo_element_content(
|
||||||
ContentItem::Attr(attr) => {
|
ContentItem::Attr(attr) => {
|
||||||
let element = pseudo_element_info
|
let element = pseudo_element_info
|
||||||
.node
|
.node
|
||||||
.to_threadsafe()
|
|
||||||
.as_element()
|
.as_element()
|
||||||
.expect("Expected an element");
|
.expect("Expected an element");
|
||||||
|
|
||||||
|
@ -501,44 +482,3 @@ fn generate_pseudo_element_content(
|
||||||
Content::Normal | Content::None => unreachable!(),
|
Content::Normal | Content::None => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ChildNodeIterator<'dom> {
|
|
||||||
/// Iterating over the children of a node
|
|
||||||
Node(Option<ServoLayoutNode<'dom>>),
|
|
||||||
/// Iterating over the assigned nodes of a `HTMLSlotElement`
|
|
||||||
Slottables(<Vec<ServoLayoutNode<'dom>> as IntoIterator>::IntoIter),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn iter_child_nodes(parent: ServoLayoutNode<'_>) -> ChildNodeIterator<'_> {
|
|
||||||
if let Some(element) = parent.as_element() {
|
|
||||||
if let Some(shadow) = element.shadow_root() {
|
|
||||||
return iter_child_nodes(shadow.as_node());
|
|
||||||
};
|
|
||||||
|
|
||||||
let slotted_nodes = element.slotted_nodes();
|
|
||||||
if !slotted_nodes.is_empty() {
|
|
||||||
#[allow(clippy::unnecessary_to_owned)] // Clippy is wrong.
|
|
||||||
return ChildNodeIterator::Slottables(slotted_nodes.to_owned().into_iter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let first = parent.first_child();
|
|
||||||
ChildNodeIterator::Node(first)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'dom> Iterator for ChildNodeIterator<'dom> {
|
|
||||||
type Item = ServoLayoutNode<'dom>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
match self {
|
|
||||||
Self::Node(node) => {
|
|
||||||
let old = *node;
|
|
||||||
*node = old?.next_sibling();
|
|
||||||
old
|
|
||||||
},
|
|
||||||
Self::Slottables(slots) => slots.next(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FusedIterator for ChildNodeIterator<'_> {}
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use geom::{FlexAxis, MainStartCrossStart};
|
use geom::{FlexAxis, MainStartCrossStart};
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::logical_geometry::WritingMode;
|
use style::logical_geometry::WritingMode;
|
||||||
|
@ -161,7 +161,7 @@ impl FlexLevelBox {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &ServoArc<ComputedValues>,
|
new_style: &ServoArc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -6,9 +6,8 @@ use std::vec::IntoIter;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use fonts::FontMetrics;
|
use fonts::FontMetrics;
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
|
||||||
|
@ -73,12 +72,12 @@ impl InlineBox {
|
||||||
|
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &ServoArc<ComputedValues>,
|
new_style: &ServoArc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
self.base.repair_style(new_style);
|
self.base.repair_style(new_style);
|
||||||
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
|
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
|
||||||
*self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
|
*self.shared_inline_styles.selected.borrow_mut() = node.selected_style();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ use bitflags::bitflags;
|
||||||
use construct::InlineFormattingContextBuilder;
|
use construct::InlineFormattingContextBuilder;
|
||||||
use fonts::{ByteIndex, FontMetrics, GlyphStore};
|
use fonts::{ByteIndex, FontMetrics, GlyphStore};
|
||||||
use inline_box::{InlineBox, InlineBoxContainerState, InlineBoxIdentifier, InlineBoxes};
|
use inline_box::{InlineBox, InlineBoxContainerState, InlineBoxIdentifier, InlineBoxes};
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
|
||||||
use line::{
|
use line::{
|
||||||
AbsolutelyPositionedLineItem, AtomicLineItem, FloatLineItem, LineItem, LineItemLayout,
|
AbsolutelyPositionedLineItem, AtomicLineItem, FloatLineItem, LineItem, LineItemLayout,
|
||||||
TextRunLineItem,
|
TextRunLineItem,
|
||||||
|
@ -91,7 +90,7 @@ use line::{
|
||||||
use line_breaker::LineBreaker;
|
use line_breaker::LineBreaker;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
||||||
|
@ -188,7 +187,7 @@ impl From<&NodeAndStyleInfo<'_>> for SharedInlineStyles {
|
||||||
fn from(info: &NodeAndStyleInfo) -> Self {
|
fn from(info: &NodeAndStyleInfo) -> Self {
|
||||||
Self {
|
Self {
|
||||||
style: SharedStyle::new(info.style.clone()),
|
style: SharedStyle::new(info.style.clone()),
|
||||||
selected: SharedStyle::new(info.get_selected_style()),
|
selected: SharedStyle::new(info.node.selected_style()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +221,7 @@ impl InlineItem {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&self,
|
&self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1696,9 +1695,13 @@ impl InlineFormattingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn repair_style(&self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
pub(crate) fn repair_style(
|
||||||
|
&self,
|
||||||
|
node: &ServoThreadSafeLayoutNode,
|
||||||
|
new_style: &Arc<ComputedValues>,
|
||||||
|
) {
|
||||||
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
|
*self.shared_inline_styles.style.borrow_mut() = new_style.clone();
|
||||||
*self.shared_inline_styles.selected.borrow_mut() = node.to_threadsafe().selected_style();
|
*self.shared_inline_styles.selected.borrow_mut() = node.selected_style();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn layout(
|
pub(super) fn layout(
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
|
|
||||||
use app_units::{Au, MAX_AU};
|
use app_units::{Au, MAX_AU};
|
||||||
use inline::InlineFormattingContext;
|
use inline::InlineFormattingContext;
|
||||||
|
use layout_api::wrapper_traits::ThreadSafeLayoutNode;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use style::computed_values::clear::T as StyleClear;
|
use style::computed_values::clear::T as StyleClear;
|
||||||
|
@ -23,7 +24,6 @@ use style::values::specified::{Display, TextAlignKeyword};
|
||||||
|
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
|
||||||
use crate::flow::float::{
|
use crate::flow::float::{
|
||||||
Clear, ContainingBlockPositionInfo, FloatBox, FloatSide, PlacementAmongFloats,
|
Clear, ContainingBlockPositionInfo, FloatBox, FloatSide, PlacementAmongFloats,
|
||||||
SequentialLayoutState,
|
SequentialLayoutState,
|
||||||
|
@ -76,7 +76,11 @@ impl BlockContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
pub(crate) fn repair_style(
|
||||||
|
&mut self,
|
||||||
|
node: &ServoThreadSafeLayoutNode,
|
||||||
|
new_style: &Arc<ComputedValues>,
|
||||||
|
) {
|
||||||
match self {
|
match self {
|
||||||
BlockContainer::BlockLevelBoxes(..) => {},
|
BlockContainer::BlockLevelBoxes(..) => {},
|
||||||
BlockContainer::InlineFormattingContext(inline_formatting_context) => {
|
BlockContainer::InlineFormattingContext(inline_formatting_context) => {
|
||||||
|
@ -103,7 +107,7 @@ impl BlockLevelBox {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
self.with_base_mut(|base| {
|
self.with_base_mut(|base| {
|
||||||
|
@ -412,7 +416,7 @@ impl OutsideMarker {
|
||||||
fn repair_style(
|
fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
self.list_item_style = node.style(context);
|
self.list_item_style = node.style(context);
|
||||||
|
@ -477,7 +481,11 @@ impl BlockFormattingContext {
|
||||||
LayoutStyle::Default(&base.style)
|
LayoutStyle::Default(&base.style)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn repair_style(&mut self, node: &ServoLayoutNode, new_style: &Arc<ComputedValues>) {
|
pub(crate) fn repair_style(
|
||||||
|
&mut self,
|
||||||
|
node: &ServoThreadSafeLayoutNode,
|
||||||
|
new_style: &Arc<ComputedValues>,
|
||||||
|
) {
|
||||||
self.contents.repair_style(node, new_style);
|
self.contents.repair_style(node, new_style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use euclid::default::Size2D as UntypedSize2D;
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||||
use layout_api::{LayoutElementType, LayoutNodeType};
|
use layout_api::{LayoutElementType, LayoutNodeType};
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::{ServoLayoutNode, ServoThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::dom::{NodeInfo, TNode};
|
use style::dom::{NodeInfo, TNode};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -20,7 +20,7 @@ use style_traits::CSSPixel;
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom::{LayoutBox, NodeExt};
|
use crate::dom::{LayoutBox, NodeExt};
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, iter_child_nodes};
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents};
|
||||||
use crate::flexbox::FlexLevelBox;
|
use crate::flexbox::FlexLevelBox;
|
||||||
use crate::flow::float::FloatBox;
|
use crate::flow::float::FloatBox;
|
||||||
use crate::flow::inline::InlineItem;
|
use crate::flow::inline::InlineItem;
|
||||||
|
@ -47,6 +47,7 @@ pub struct BoxTree {
|
||||||
impl BoxTree {
|
impl BoxTree {
|
||||||
#[servo_tracing::instrument(name = "Box Tree Construction", skip_all)]
|
#[servo_tracing::instrument(name = "Box Tree Construction", skip_all)]
|
||||||
pub(crate) fn construct(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
|
pub(crate) fn construct(context: &LayoutContext, root_element: ServoLayoutNode<'_>) -> Self {
|
||||||
|
let root_element = root_element.to_threadsafe();
|
||||||
let boxes = construct_for_root_element(context, root_element);
|
let boxes = construct_for_root_element(context, root_element);
|
||||||
|
|
||||||
// Zero box for `:root { display: none }`, one for the root element otherwise.
|
// Zero box for `:root { display: none }`, one for the root element otherwise.
|
||||||
|
@ -68,9 +69,8 @@ impl BoxTree {
|
||||||
viewport_overflow_y == Overflow::Visible &&
|
viewport_overflow_y == Overflow::Visible &&
|
||||||
!root_style.get_box().display.is_none()
|
!root_style.get_box().display.is_none()
|
||||||
{
|
{
|
||||||
for child in iter_child_nodes(root_element) {
|
for child in root_element.children() {
|
||||||
if !child
|
if !child
|
||||||
.to_threadsafe()
|
|
||||||
.as_element()
|
.as_element()
|
||||||
.is_some_and(|element| element.is_body_element_of_html_element_root())
|
.is_some_and(|element| element.is_body_element_of_html_element_root())
|
||||||
{
|
{
|
||||||
|
@ -138,7 +138,7 @@ impl BoxTree {
|
||||||
|
|
||||||
fn construct_for_root_element(
|
fn construct_for_root_element(
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
root_element: ServoLayoutNode<'_>,
|
root_element: ServoThreadSafeLayoutNode<'_>,
|
||||||
) -> Vec<ArcRefCell<BlockLevelBox>> {
|
) -> Vec<ArcRefCell<BlockLevelBox>> {
|
||||||
let info = NodeAndStyleInfo::new(
|
let info = NodeAndStyleInfo::new(
|
||||||
root_element,
|
root_element,
|
||||||
|
@ -292,7 +292,8 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't update unstyled nodes or nodes that have pseudo-elements.
|
// Don't update unstyled nodes or nodes that have pseudo-elements.
|
||||||
let element_data = potential_dirty_root_node
|
let potential_thread_safe_dirty_root_node = potential_dirty_root_node.to_threadsafe();
|
||||||
|
let element_data = potential_thread_safe_dirty_root_node
|
||||||
.style_data()?
|
.style_data()?
|
||||||
.element_data
|
.element_data
|
||||||
.borrow();
|
.borrow();
|
||||||
|
@ -300,7 +301,7 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout_data = NodeExt::layout_data(&potential_dirty_root_node)?;
|
let layout_data = NodeExt::layout_data(&potential_thread_safe_dirty_root_node)?;
|
||||||
if !layout_data.pseudo_boxes.is_empty() {
|
if !layout_data.pseudo_boxes.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -377,14 +378,12 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
|
||||||
|
|
||||||
#[servo_tracing::instrument(name = "Box Tree Update From Dirty Root", skip_all)]
|
#[servo_tracing::instrument(name = "Box Tree Update From Dirty Root", skip_all)]
|
||||||
fn update_from_dirty_root(&self, context: &LayoutContext) {
|
fn update_from_dirty_root(&self, context: &LayoutContext) {
|
||||||
let contents = ReplacedContents::for_element(self.node, context)
|
let node = self.node.to_threadsafe();
|
||||||
|
let contents = ReplacedContents::for_element(node, context)
|
||||||
.map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced);
|
.map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced);
|
||||||
|
|
||||||
let info = NodeAndStyleInfo::new(
|
let info =
|
||||||
self.node,
|
NodeAndStyleInfo::new(node, self.primary_style.clone(), node.take_restyle_damage());
|
||||||
self.primary_style.clone(),
|
|
||||||
self.node.take_restyle_damage(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
|
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
|
||||||
AbsolutelyPositionedBox::construct(context, &info, self.display_inside, contents),
|
AbsolutelyPositionedBox::construct(context, &info, self.display_inside, contents),
|
||||||
|
@ -424,7 +423,7 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
|
||||||
//
|
//
|
||||||
// TODO: This isn't going to be good enough for incremental fragment tree
|
// TODO: This isn't going to be good enough for incremental fragment tree
|
||||||
// reconstruction, as fragment tree damage might extend further up the tree.
|
// reconstruction, as fragment tree damage might extend further up the tree.
|
||||||
parent_node.take_restyle_damage();
|
parent_node.to_threadsafe().take_restyle_damage();
|
||||||
|
|
||||||
invalidate_start_point = parent_node;
|
invalidate_start_point = parent_node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::{ServoLayoutElement, ServoLayoutNode};
|
use script::layout_dom::{ServoLayoutElement, ServoThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::logical_geometry::Direction;
|
use style::logical_geometry::Direction;
|
||||||
|
@ -217,7 +217,7 @@ impl IndependentFormattingContext {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
self.base.repair_style(new_style);
|
self.base.repair_style(new_style);
|
||||||
|
|
|
@ -25,6 +25,7 @@ use fonts::{FontContext, FontContextWebFontMethods};
|
||||||
use fonts_traits::StylesheetWebFontLoadFinishedCallback;
|
use fonts_traits::StylesheetWebFontLoadFinishedCallback;
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
use layout_api::wrapper_traits::LayoutNode;
|
||||||
use layout_api::{
|
use layout_api::{
|
||||||
IFrameSizes, Layout, LayoutConfig, LayoutDamage, LayoutFactory, OffsetParentResponse, QueryMsg,
|
IFrameSizes, Layout, LayoutConfig, LayoutDamage, LayoutFactory, OffsetParentResponse, QueryMsg,
|
||||||
ReflowGoal, ReflowPhasesRun, ReflowRequest, ReflowRequestRestyle, ReflowResult,
|
ReflowGoal, ReflowPhasesRun, ReflowRequest, ReflowRequestRestyle, ReflowResult,
|
||||||
|
@ -272,7 +273,7 @@ impl Layout for LayoutThread {
|
||||||
let stacking_context_tree = stacking_context_tree
|
let stacking_context_tree = stacking_context_tree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Should always have a StackingContextTree for content box queries");
|
.expect("Should always have a StackingContextTree for content box queries");
|
||||||
process_content_box_request(stacking_context_tree, node)
|
process_content_box_request(stacking_context_tree, node.to_threadsafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `Vec` of bounding boxes of this node's `Fragement`s in the coordinate space of the
|
/// Get a `Vec` of bounding boxes of this node's `Fragement`s in the coordinate space of the
|
||||||
|
@ -292,13 +293,13 @@ impl Layout for LayoutThread {
|
||||||
let stacking_context_tree = stacking_context_tree
|
let stacking_context_tree = stacking_context_tree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Should always have a StackingContextTree for content box queries");
|
.expect("Should always have a StackingContextTree for content box queries");
|
||||||
process_content_boxes_request(stacking_context_tree, node)
|
process_content_boxes_request(stacking_context_tree, node.to_threadsafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[servo_tracing::instrument(skip_all)]
|
#[servo_tracing::instrument(skip_all)]
|
||||||
fn query_client_rect(&self, node: TrustedNodeAddress) -> UntypedRect<i32> {
|
fn query_client_rect(&self, node: TrustedNodeAddress) -> UntypedRect<i32> {
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
process_client_rect_request(node)
|
process_client_rect_request(node.to_threadsafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[servo_tracing::instrument(skip_all)]
|
#[servo_tracing::instrument(skip_all)]
|
||||||
|
@ -376,7 +377,7 @@ impl Layout for LayoutThread {
|
||||||
|
|
||||||
#[servo_tracing::instrument(skip_all)]
|
#[servo_tracing::instrument(skip_all)]
|
||||||
fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> UntypedRect<i32> {
|
fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> UntypedRect<i32> {
|
||||||
let node = node.map(|node| unsafe { ServoLayoutNode::new(&node) });
|
let node = node.map(|node| unsafe { ServoLayoutNode::new(&node).to_threadsafe() });
|
||||||
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone())
|
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,7 +908,7 @@ impl LayoutThread {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let damage = compute_damage_and_repair_style(
|
let damage = compute_damage_and_repair_style(
|
||||||
&layout_context.style_context,
|
&layout_context.style_context,
|
||||||
root_node,
|
root_node.to_threadsafe(),
|
||||||
damage_from_environment,
|
damage_from_environment,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use euclid::{SideOffsets2D, Size2D};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||||
use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse};
|
use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse};
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::{ServoLayoutNode, ServoThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use servo_geometry::{FastLayoutTransform, au_rect_to_f32_rect, f32_rect_to_au_rect};
|
use servo_geometry::{FastLayoutTransform, au_rect_to_f32_rect, f32_rect_to_au_rect};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -53,7 +53,7 @@ use crate::taffy::SpecificTaffyGridInfo;
|
||||||
/// calculate its cumlative transform from its root scroll node to the scroll node.
|
/// calculate its cumlative transform from its root scroll node to the scroll node.
|
||||||
fn root_transform_for_layout_node(
|
fn root_transform_for_layout_node(
|
||||||
scroll_tree: &ScrollTree,
|
scroll_tree: &ScrollTree,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoThreadSafeLayoutNode<'_>,
|
||||||
) -> Option<FastLayoutTransform> {
|
) -> Option<FastLayoutTransform> {
|
||||||
let fragments = node.fragments_for_pseudo(None);
|
let fragments = node.fragments_for_pseudo(None);
|
||||||
let box_fragment = fragments
|
let box_fragment = fragments
|
||||||
|
@ -69,7 +69,7 @@ fn root_transform_for_layout_node(
|
||||||
|
|
||||||
pub(crate) fn process_content_box_request(
|
pub(crate) fn process_content_box_request(
|
||||||
stacking_context_tree: &StackingContextTree,
|
stacking_context_tree: &StackingContextTree,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoThreadSafeLayoutNode<'_>,
|
||||||
) -> Option<Rect<Au>> {
|
) -> Option<Rect<Au>> {
|
||||||
let rects: Vec<_> = node
|
let rects: Vec<_> = node
|
||||||
.fragments_for_pseudo(None)
|
.fragments_for_pseudo(None)
|
||||||
|
@ -94,7 +94,7 @@ pub(crate) fn process_content_box_request(
|
||||||
|
|
||||||
pub(crate) fn process_content_boxes_request(
|
pub(crate) fn process_content_boxes_request(
|
||||||
stacking_context_tree: &StackingContextTree,
|
stacking_context_tree: &StackingContextTree,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoThreadSafeLayoutNode<'_>,
|
||||||
) -> Vec<Rect<Au>> {
|
) -> Vec<Rect<Au>> {
|
||||||
let fragments = node.fragments_for_pseudo(None);
|
let fragments = node.fragments_for_pseudo(None);
|
||||||
let content_boxes = fragments
|
let content_boxes = fragments
|
||||||
|
@ -113,7 +113,7 @@ pub(crate) fn process_content_boxes_request(
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_client_rect_request(node: ServoLayoutNode<'_>) -> Rect<i32> {
|
pub fn process_client_rect_request(node: ServoThreadSafeLayoutNode<'_>) -> Rect<i32> {
|
||||||
node.fragments_for_pseudo(None)
|
node.fragments_for_pseudo(None)
|
||||||
.first()
|
.first()
|
||||||
.map(Fragment::client_rect)
|
.map(Fragment::client_rect)
|
||||||
|
@ -122,7 +122,7 @@ pub fn process_client_rect_request(node: ServoLayoutNode<'_>) -> Rect<i32> {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
|
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
|
||||||
pub fn process_node_scroll_area_request(
|
pub fn process_node_scroll_area_request(
|
||||||
requested_node: Option<ServoLayoutNode<'_>>,
|
requested_node: Option<ServoThreadSafeLayoutNode<'_>>,
|
||||||
fragment_tree: Option<Rc<FragmentTree>>,
|
fragment_tree: Option<Rc<FragmentTree>>,
|
||||||
) -> Rect<i32> {
|
) -> Rect<i32> {
|
||||||
let Some(tree) = fragment_tree else {
|
let Some(tree) = fragment_tree else {
|
||||||
|
@ -311,7 +311,8 @@ pub fn process_resolved_style_request(
|
||||||
.to_css_string()
|
.to_css_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
node.fragments_for_pseudo(*pseudo)
|
node.to_threadsafe()
|
||||||
|
.fragments_for_pseudo(*pseudo)
|
||||||
.first()
|
.first()
|
||||||
.map(resolve_for_fragment)
|
.map(resolve_for_fragment)
|
||||||
.unwrap_or_else(|| computed_style(None))
|
.unwrap_or_else(|| computed_style(None))
|
||||||
|
@ -484,7 +485,11 @@ fn offset_parent_fragments(node: ServoLayoutNode<'_>) -> Option<OffsetParentFrag
|
||||||
// * The element is the root element.
|
// * The element is the root element.
|
||||||
// * The element is the HTML body element.
|
// * The element is the HTML body element.
|
||||||
// * The element’s computed value of the position property is fixed.
|
// * The element’s computed value of the position property is fixed.
|
||||||
let fragment = node.fragments_for_pseudo(None).first().cloned()?;
|
let fragment = node
|
||||||
|
.to_threadsafe()
|
||||||
|
.fragments_for_pseudo(None)
|
||||||
|
.first()
|
||||||
|
.cloned()?;
|
||||||
let flags = fragment.base()?.flags;
|
let flags = fragment.base()?.flags;
|
||||||
if flags.intersects(
|
if flags.intersects(
|
||||||
FragmentFlags::IS_ROOT_ELEMENT | FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT,
|
FragmentFlags::IS_ROOT_ELEMENT | FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT,
|
||||||
|
@ -507,14 +512,22 @@ fn offset_parent_fragments(node: ServoLayoutNode<'_>) -> Option<OffsetParentFrag
|
||||||
while let Some(parent_node) = maybe_parent_node {
|
while let Some(parent_node) = maybe_parent_node {
|
||||||
maybe_parent_node = parent_node.parent_node();
|
maybe_parent_node = parent_node.parent_node();
|
||||||
|
|
||||||
if let Some(parent_fragment) = parent_node.fragments_for_pseudo(None).first() {
|
if let Some(parent_fragment) = parent_node
|
||||||
|
.to_threadsafe()
|
||||||
|
.fragments_for_pseudo(None)
|
||||||
|
.first()
|
||||||
|
{
|
||||||
let parent_fragment = match parent_fragment {
|
let parent_fragment = match parent_fragment {
|
||||||
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => box_fragment,
|
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => box_fragment,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let grandparent_fragment =
|
let grandparent_fragment = maybe_parent_node.and_then(|node| {
|
||||||
maybe_parent_node.and_then(|node| node.fragments_for_pseudo(None).first().cloned());
|
node.to_threadsafe()
|
||||||
|
.fragments_for_pseudo(None)
|
||||||
|
.first()
|
||||||
|
.cloned()
|
||||||
|
});
|
||||||
|
|
||||||
if parent_fragment.borrow().style.get_box().position != Position::Static {
|
if parent_fragment.borrow().style.get_box().position != Position::Static {
|
||||||
return Some(OffsetParentFragments {
|
return Some(OffsetParentFragments {
|
||||||
|
@ -557,7 +570,11 @@ pub fn process_offset_parent_query(node: ServoLayoutNode<'_>) -> Option<OffsetPa
|
||||||
// [1]: https://github.com/w3c/csswg-drafts/issues/4541
|
// [1]: https://github.com/w3c/csswg-drafts/issues/4541
|
||||||
// > 1. If the element is the HTML body element or does not have any associated CSS
|
// > 1. If the element is the HTML body element or does not have any associated CSS
|
||||||
// layout box return zero and terminate this algorithm.
|
// layout box return zero and terminate this algorithm.
|
||||||
let fragment = node.fragments_for_pseudo(None).first().cloned()?;
|
let fragment = node
|
||||||
|
.to_threadsafe()
|
||||||
|
.fragments_for_pseudo(None)
|
||||||
|
.first()
|
||||||
|
.cloned()?;
|
||||||
let mut border_box = fragment.cumulative_border_box_rect()?;
|
let mut border_box = fragment.cumulative_border_box_rect()?;
|
||||||
|
|
||||||
// 2. If the offsetParent of the element is null return the x-coordinate of the left
|
// 2. If the offsetParent of the element is null return the x-coordinate of the left
|
||||||
|
|
|
@ -8,13 +8,13 @@ use data_url::DataUrl;
|
||||||
use embedder_traits::ViewportDetails;
|
use embedder_traits::ViewportDetails;
|
||||||
use euclid::{Scale, Size2D};
|
use euclid::{Scale, Size2D};
|
||||||
use layout_api::IFrameSize;
|
use layout_api::IFrameSize;
|
||||||
|
use layout_api::wrapper_traits::ThreadSafeLayoutNode;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use net_traits::image_cache::{Image, ImageOrMetadataAvailable, UsePlaceholder, VectorImage};
|
use net_traits::image_cache::{Image, ImageOrMetadataAvailable, UsePlaceholder, VectorImage};
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use style::computed_values::object_fit::T as ObjectFit;
|
use style::computed_values::object_fit::T as ObjectFit;
|
||||||
use style::dom::TNode;
|
|
||||||
use style::logical_geometry::{Direction, WritingMode};
|
use style::logical_geometry::{Direction, WritingMode};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::servo::url::ComputedUrl;
|
use style::servo::url::ComputedUrl;
|
||||||
|
@ -131,7 +131,10 @@ pub(crate) enum ReplacedContentKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReplacedContents {
|
impl ReplacedContents {
|
||||||
pub fn for_element(element: ServoLayoutNode<'_>, context: &LayoutContext) -> Option<Self> {
|
pub fn for_element(
|
||||||
|
element: ServoThreadSafeLayoutNode<'_>,
|
||||||
|
context: &LayoutContext,
|
||||||
|
) -> Option<Self> {
|
||||||
if let Some(ref data_attribute_string) = element.as_typeless_object_with_data_attribute() {
|
if let Some(ref data_attribute_string) = element.as_typeless_object_with_data_attribute() {
|
||||||
if let Some(url) = try_to_parse_image_data_url(data_attribute_string) {
|
if let Some(url) = try_to_parse_image_data_url(data_attribute_string) {
|
||||||
return Self::from_image_url(
|
return Self::from_image_url(
|
||||||
|
@ -219,7 +222,7 @@ impl ReplacedContents {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_image_url(
|
pub fn from_image_url(
|
||||||
element: ServoLayoutNode<'_>,
|
element: ServoThreadSafeLayoutNode<'_>,
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
image_url: &ComputedUrl,
|
image_url: &ComputedUrl,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
|
@ -255,7 +258,7 @@ impl ReplacedContents {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_image(
|
pub fn from_image(
|
||||||
element: ServoLayoutNode<'_>,
|
element: ServoThreadSafeLayoutNode<'_>,
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
image: &ComputedImage,
|
image: &ComputedImage,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::borrow::Cow;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
|
||||||
use atomic_refcell::AtomicRef;
|
use atomic_refcell::AtomicRef;
|
||||||
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
use layout_api::wrapper_traits::ThreadSafeLayoutNode;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -1028,9 +1028,8 @@ impl<'dom> TraversalHandler<'dom> for TableRowBuilder<'_, '_, 'dom, '_> {
|
||||||
// This value will already have filtered out rowspan=0
|
// This value will already have filtered out rowspan=0
|
||||||
// in quirks mode, so we don't have to worry about that.
|
// in quirks mode, so we don't have to worry about that.
|
||||||
let (rowspan, colspan) = if info.pseudo_element_type.is_none() {
|
let (rowspan, colspan) = if info.pseudo_element_type.is_none() {
|
||||||
let node = info.node.to_threadsafe();
|
let rowspan = info.node.get_rowspan().unwrap_or(1) as usize;
|
||||||
let rowspan = node.get_rowspan().unwrap_or(1) as usize;
|
let colspan = info.node.get_colspan().unwrap_or(1) as usize;
|
||||||
let colspan = node.get_colspan().unwrap_or(1) as usize;
|
|
||||||
|
|
||||||
// The HTML specification clamps value of `rowspan` to [0, 65534] and
|
// The HTML specification clamps value of `rowspan` to [0, 65534] and
|
||||||
// `colspan` to [1, 1000].
|
// `colspan` to [1, 1000].
|
||||||
|
@ -1150,7 +1149,7 @@ fn add_column(
|
||||||
old_column: Option<ArcRefCell<TableTrack>>,
|
old_column: Option<ArcRefCell<TableTrack>>,
|
||||||
) -> ArcRefCell<TableTrack> {
|
) -> ArcRefCell<TableTrack> {
|
||||||
let span = if column_info.pseudo_element_type.is_none() {
|
let span = if column_info.pseudo_element_type.is_none() {
|
||||||
column_info.node.to_threadsafe().get_span().unwrap_or(1)
|
column_info.node.get_span().unwrap_or(1)
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub(crate) use construct::AnonymousTableContent;
|
||||||
pub use construct::TableBuilder;
|
pub use construct::TableBuilder;
|
||||||
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
|
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::{ServoLayoutElement, ServoLayoutNode};
|
use script::layout_dom::{ServoLayoutElement, ServoThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -425,7 +425,7 @@ impl TableLevelBox {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&self,
|
&self,
|
||||||
context: &SharedStyleContext<'_>,
|
context: &SharedStyleContext<'_>,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use malloc_size_of_derive::MallocSizeOf;
|
use malloc_size_of_derive::MallocSizeOf;
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -159,7 +159,7 @@ impl TaffyItemBox {
|
||||||
pub(crate) fn repair_style(
|
pub(crate) fn repair_style(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: &ServoLayoutNode,
|
node: &ServoThreadSafeLayoutNode,
|
||||||
new_style: &Arc<ComputedValues>,
|
new_style: &Arc<ComputedValues>,
|
||||||
) {
|
) {
|
||||||
self.style = new_style.clone();
|
self.style = new_style.clone();
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
use bitflags::Flags;
|
use bitflags::Flags;
|
||||||
use layout_api::LayoutDamage;
|
use layout_api::LayoutDamage;
|
||||||
use layout_api::wrapper_traits::LayoutNode;
|
use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
||||||
use script::layout_dom::ServoLayoutNode;
|
use script::layout_dom::ServoThreadSafeLayoutNode;
|
||||||
use style::context::{SharedStyleContext, StyleContext};
|
use style::context::{SharedStyleContext, StyleContext};
|
||||||
use style::data::ElementData;
|
use style::data::ElementData;
|
||||||
use style::dom::{NodeInfo, TElement, TNode};
|
use style::dom::{NodeInfo, TElement, TNode};
|
||||||
|
@ -15,7 +15,6 @@ use style::values::computed::Display;
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom::{DOMLayoutData, NodeExt};
|
use crate::dom::{DOMLayoutData, NodeExt};
|
||||||
use crate::dom_traversal::iter_child_nodes;
|
|
||||||
|
|
||||||
pub struct RecalcStyle<'a> {
|
pub struct RecalcStyle<'a> {
|
||||||
context: &'a LayoutContext<'a>,
|
context: &'a LayoutContext<'a>,
|
||||||
|
@ -97,7 +96,7 @@ where
|
||||||
#[servo_tracing::instrument(skip_all)]
|
#[servo_tracing::instrument(skip_all)]
|
||||||
pub(crate) fn compute_damage_and_repair_style(
|
pub(crate) fn compute_damage_and_repair_style(
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoThreadSafeLayoutNode<'_>,
|
||||||
damage_from_environment: RestyleDamage,
|
damage_from_environment: RestyleDamage,
|
||||||
) -> RestyleDamage {
|
) -> RestyleDamage {
|
||||||
compute_damage_and_repair_style_inner(context, node, damage_from_environment)
|
compute_damage_and_repair_style_inner(context, node, damage_from_environment)
|
||||||
|
@ -105,7 +104,7 @@ pub(crate) fn compute_damage_and_repair_style(
|
||||||
|
|
||||||
pub(crate) fn compute_damage_and_repair_style_inner(
|
pub(crate) fn compute_damage_and_repair_style_inner(
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
node: ServoLayoutNode<'_>,
|
node: ServoThreadSafeLayoutNode<'_>,
|
||||||
damage_from_parent: RestyleDamage,
|
damage_from_parent: RestyleDamage,
|
||||||
) -> RestyleDamage {
|
) -> RestyleDamage {
|
||||||
let mut element_damage;
|
let mut element_damage;
|
||||||
|
@ -136,7 +135,7 @@ pub(crate) fn compute_damage_and_repair_style_inner(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut damage_from_children = RestyleDamage::empty();
|
let mut damage_from_children = RestyleDamage::empty();
|
||||||
for child in iter_child_nodes(node) {
|
for child in node.children() {
|
||||||
if child.is_element() {
|
if child.is_element() {
|
||||||
damage_from_children |=
|
damage_from_children |=
|
||||||
compute_damage_and_repair_style_inner(context, child, damage_for_children);
|
compute_damage_and_repair_style_inner(context, child, damage_for_children);
|
||||||
|
|
|
@ -116,6 +116,14 @@ impl<T: MallocSizeOf> MallocSizeOf for [T] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for [T] {
|
||||||
|
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
|
self.iter()
|
||||||
|
.map(|element| element.conditional_size_of(ops))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// For use on types where size_of() returns 0.
|
/// For use on types where size_of() returns 0.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! malloc_size_of_is_0(
|
macro_rules! malloc_size_of_is_0(
|
||||||
|
@ -352,6 +360,23 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: MallocConditionalSizeOf> MallocConditionalSizeOf for smallvec::SmallVec<A>
|
||||||
|
where
|
||||||
|
A: smallvec::Array,
|
||||||
|
A::Item: MallocConditionalSizeOf,
|
||||||
|
{
|
||||||
|
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
|
if !self.spilled() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shallow_size_of(ops) +
|
||||||
|
self.iter()
|
||||||
|
.map(|element| element.conditional_size_of(ops))
|
||||||
|
.sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: MallocSizeOf> MallocSizeOf for BinaryHeap<T> {
|
impl<T: MallocSizeOf> MallocSizeOf for BinaryHeap<T> {
|
||||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
self.iter().map(|element| element.size_of(ops)).sum()
|
self.iter().map(|element| element.size_of(ops)).sum()
|
||||||
|
|
|
@ -974,6 +974,20 @@ pub struct ServoThreadSafeLayoutElement<'dom> {
|
||||||
pub(super) pseudo: Option<PseudoElement>,
|
pub(super) pseudo: Option<PseudoElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'dom> ServoThreadSafeLayoutElement<'dom> {
|
||||||
|
/// The shadow root this element is a host of.
|
||||||
|
pub fn shadow_root(&self) -> Option<ServoShadowRoot<'dom>> {
|
||||||
|
self.element
|
||||||
|
.element
|
||||||
|
.get_shadow_root_for_layout()
|
||||||
|
.map(ServoShadowRoot::from_layout_js)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn slotted_nodes(&self) -> &[ServoLayoutNode<'dom>] {
|
||||||
|
self.element.slotted_nodes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom> {
|
impl<'dom> ThreadSafeLayoutElement<'dom> for ServoThreadSafeLayoutElement<'dom> {
|
||||||
type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'dom>;
|
type ConcreteThreadSafeLayoutNode = ServoThreadSafeLayoutNode<'dom>;
|
||||||
type ConcreteElement = ServoLayoutElement<'dom>;
|
type ConcreteElement = ServoLayoutElement<'dom>;
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
use base::id::{BrowsingContextId, PipelineId};
|
use base::id::{BrowsingContextId, PipelineId};
|
||||||
use fonts_traits::ByteIndex;
|
use fonts_traits::ByteIndex;
|
||||||
use html5ever::{local_name, ns};
|
use layout_api::wrapper_traits::{
|
||||||
use layout_api::wrapper_traits::{LayoutDataTrait, LayoutNode, ThreadSafeLayoutNode};
|
LayoutDataTrait, LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
|
||||||
|
};
|
||||||
use layout_api::{
|
use layout_api::{
|
||||||
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGElementData, StyleData,
|
GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutNodeType, SVGElementData, StyleData,
|
||||||
TrustedNodeAddress,
|
TrustedNodeAddress,
|
||||||
|
@ -98,22 +100,6 @@ impl<'dom> ServoLayoutNode<'dom> {
|
||||||
.map(LayoutDom::upcast)
|
.map(LayoutDom::upcast)
|
||||||
.map(ServoLayoutElement::from_layout_js)
|
.map(ServoLayoutElement::from_layout_js)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_text_input(&self) -> bool {
|
|
||||||
self.node.is_text_input()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_text_container_of_single_line_input(&self) -> bool {
|
|
||||||
self.node.is_text_container_of_single_line_input()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_in_ua_widget(&self) -> bool {
|
|
||||||
self.node.is_in_ua_widget()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn containing_shadow_host(&self) -> Option<ServoLayoutNode> {
|
|
||||||
Some(self.as_element()?.containing_shadow_host()?.as_node())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl style::dom::NodeInfo for ServoLayoutNode<'_> {
|
impl style::dom::NodeInfo for ServoLayoutNode<'_> {
|
||||||
|
@ -214,15 +200,6 @@ impl<'dom> LayoutNode<'dom> for ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self) {
|
|
||||||
let inner = self.get_jsmanaged();
|
|
||||||
if inner.layout_data().is_none() {
|
|
||||||
unsafe {
|
|
||||||
inner.initialize_layout_data(Box::<RequestedLayoutDataType>::default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_connected(&self) -> bool {
|
fn is_connected(&self) -> bool {
|
||||||
unsafe { self.node.get_flag(NodeFlags::IS_CONNECTED) }
|
unsafe { self.node.get_flag(NodeFlags::IS_CONNECTED) }
|
||||||
}
|
}
|
||||||
|
@ -280,6 +257,35 @@ impl<'dom> ServoThreadSafeLayoutNode<'dom> {
|
||||||
.map(ServoLayoutNode::from_layout_js)
|
.map(ServoLayoutNode::from_layout_js)
|
||||||
.map(Self::new)
|
.map(Self::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_text_container_of_single_line_input(&self) -> bool {
|
||||||
|
self.pseudo.is_none() && self.node.node.is_text_container_of_single_line_input()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_text_input(&self) -> bool {
|
||||||
|
self.node.node.is_text_input()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selected_style(&self) -> Arc<ComputedValues> {
|
||||||
|
let Some(element) = self.as_element() else {
|
||||||
|
// TODO(stshine): What should the selected style be for text?
|
||||||
|
debug_assert!(self.is_text_node());
|
||||||
|
return self.parent_style();
|
||||||
|
};
|
||||||
|
|
||||||
|
let style_data = &element.style_data().styles;
|
||||||
|
let get_selected_style = || {
|
||||||
|
// This is a workaround for handling the `::selection` pseudos where it would not
|
||||||
|
// propagate to the children and Shadow DOM elements. For this case, UA widget
|
||||||
|
// inner elements should follow the originating element in terms of selection.
|
||||||
|
if self.node.node.is_in_ua_widget() {
|
||||||
|
return Some(element.containing_shadow_host()?.as_node().selected_style());
|
||||||
|
}
|
||||||
|
style_data.pseudos.get(&PseudoElement::Selection).cloned()
|
||||||
|
};
|
||||||
|
|
||||||
|
get_selected_style().unwrap_or_else(|| style_data.primary().clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl style::dom::NodeInfo for ServoThreadSafeLayoutNode<'_> {
|
impl style::dom::NodeInfo for ServoThreadSafeLayoutNode<'_> {
|
||||||
|
@ -320,16 +326,20 @@ impl<'dom> ThreadSafeLayoutNode<'dom> for ServoThreadSafeLayoutNode<'dom> {
|
||||||
parent_data.styles.primary().clone()
|
parent_data.styles.primary().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initialize_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self) {
|
||||||
|
let inner = self.node.get_jsmanaged();
|
||||||
|
if inner.layout_data().is_none() {
|
||||||
|
unsafe {
|
||||||
|
inner.initialize_layout_data(Box::<RequestedLayoutDataType>::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn debug_id(self) -> usize {
|
fn debug_id(self) -> usize {
|
||||||
self.node.debug_id()
|
self.node.debug_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children(&self) -> style::dom::LayoutIterator<Self::ChildrenIterator> {
|
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(ServoThreadSafeLayoutNodeChildrenIterator::new(
|
|
||||||
shadow.as_node().to_threadsafe(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
style::dom::LayoutIterator(ServoThreadSafeLayoutNodeChildrenIterator::new(*self))
|
style::dom::LayoutIterator(ServoThreadSafeLayoutNodeChildrenIterator::new(*self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,98 +454,46 @@ impl<'dom> ThreadSafeLayoutNode<'dom> for ServoThreadSafeLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
pub enum ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
||||||
current_node: Option<ServoThreadSafeLayoutNode<'dom>>,
|
/// Iterating over the children of a node
|
||||||
parent_node: ServoThreadSafeLayoutNode<'dom>,
|
Node(Option<ServoThreadSafeLayoutNode<'dom>>),
|
||||||
|
/// Iterating over the assigned nodes of a `HTMLSlotElement`
|
||||||
|
Slottables(<Vec<ServoLayoutNode<'dom>> as IntoIterator>::IntoIter),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
impl<'dom> ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
||||||
pub fn new(parent: ServoThreadSafeLayoutNode<'dom>) -> Self {
|
#[allow(unsafe_code)]
|
||||||
let first_child = match parent.pseudo_element() {
|
fn new(
|
||||||
None => parent
|
parent: ServoThreadSafeLayoutNode<'dom>,
|
||||||
.with_pseudo(PseudoElement::Before)
|
) -> ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
||||||
.or_else(|| parent.with_pseudo(PseudoElement::DetailsSummary))
|
if let Some(element) = parent.as_element() {
|
||||||
.or_else(|| unsafe { parent.dangerous_first_child() }),
|
if let Some(shadow) = element.shadow_root() {
|
||||||
Some(PseudoElement::DetailsContent) | Some(PseudoElement::DetailsSummary) => unsafe {
|
return Self::new(shadow.as_node().to_threadsafe());
|
||||||
parent.dangerous_first_child()
|
};
|
||||||
},
|
|
||||||
_ => None,
|
let slotted_nodes = element.slotted_nodes();
|
||||||
};
|
if !slotted_nodes.is_empty() {
|
||||||
ServoThreadSafeLayoutNodeChildrenIterator {
|
#[allow(clippy::unnecessary_to_owned)] // Clippy is wrong.
|
||||||
current_node: first_child,
|
return Self::Slottables(slotted_nodes.to_owned().into_iter());
|
||||||
parent_node: parent,
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Self::Node(unsafe { parent.dangerous_first_child() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> Iterator for ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
impl<'dom> Iterator for ServoThreadSafeLayoutNodeChildrenIterator<'dom> {
|
||||||
type Item = ServoThreadSafeLayoutNode<'dom>;
|
type Item = ServoThreadSafeLayoutNode<'dom>;
|
||||||
fn next(&mut self) -> Option<ServoThreadSafeLayoutNode<'dom>> {
|
|
||||||
use selectors::Element;
|
|
||||||
match self.parent_node.pseudo_element() {
|
|
||||||
Some(PseudoElement::Before) | Some(PseudoElement::After) => None,
|
|
||||||
|
|
||||||
Some(PseudoElement::DetailsSummary) => {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let mut current_node = self.current_node;
|
match self {
|
||||||
loop {
|
Self::Node(node) => {
|
||||||
let next_node = if let Some(ref node) = current_node {
|
let next_sibling = unsafe { (*node)?.dangerous_next_sibling() };
|
||||||
if let Some(element) = node.as_element() {
|
std::mem::replace(node, next_sibling)
|
||||||
if element.has_local_name(&local_name!("summary")) &&
|
|
||||||
element.has_namespace(&ns!(html))
|
|
||||||
{
|
|
||||||
self.current_node = None;
|
|
||||||
return Some(*node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe { node.dangerous_next_sibling() }
|
|
||||||
} else {
|
|
||||||
self.current_node = None;
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
current_node = next_node;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Some(PseudoElement::DetailsContent) => {
|
|
||||||
let node = self.current_node;
|
|
||||||
let node = node.and_then(|node| {
|
|
||||||
if node.is_element() &&
|
|
||||||
node.as_element()
|
|
||||||
.unwrap()
|
|
||||||
.has_local_name(&local_name!("summary")) &&
|
|
||||||
node.as_element().unwrap().has_namespace(&ns!(html))
|
|
||||||
{
|
|
||||||
unsafe { node.dangerous_next_sibling() }
|
|
||||||
} else {
|
|
||||||
Some(node)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.current_node = node.and_then(|node| unsafe { node.dangerous_next_sibling() });
|
|
||||||
node
|
|
||||||
},
|
|
||||||
|
|
||||||
None | Some(_) => {
|
|
||||||
let node = self.current_node;
|
|
||||||
if let Some(ref node) = node {
|
|
||||||
self.current_node = match node.pseudo_element() {
|
|
||||||
Some(PseudoElement::Before) => self
|
|
||||||
.parent_node
|
|
||||||
.with_pseudo(PseudoElement::DetailsSummary)
|
|
||||||
.or_else(|| unsafe { self.parent_node.dangerous_first_child() })
|
|
||||||
.or_else(|| self.parent_node.with_pseudo(PseudoElement::After)),
|
|
||||||
Some(PseudoElement::DetailsSummary) => {
|
|
||||||
self.parent_node.with_pseudo(PseudoElement::DetailsContent)
|
|
||||||
},
|
|
||||||
Some(PseudoElement::DetailsContent) => {
|
|
||||||
self.parent_node.with_pseudo(PseudoElement::After)
|
|
||||||
},
|
|
||||||
Some(PseudoElement::After) => None,
|
|
||||||
None | Some(_) => unsafe { node.dangerous_next_sibling() }
|
|
||||||
.or_else(|| self.parent_node.with_pseudo(PseudoElement::After)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
node
|
|
||||||
},
|
},
|
||||||
|
Self::Slottables(slots) => slots.next().map(|node| node.to_threadsafe()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FusedIterator for ServoThreadSafeLayoutNodeChildrenIterator<'_> {}
|
||||||
|
|
|
@ -52,15 +52,6 @@ pub trait LayoutNode<'dom>: Copy + Debug + TNode + Send + Sync {
|
||||||
/// attempting to read or modify the opaque layout data of this node.
|
/// attempting to read or modify the opaque layout data of this node.
|
||||||
unsafe fn initialize_style_and_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self);
|
unsafe fn initialize_style_and_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self);
|
||||||
|
|
||||||
/// Initialize this node with empty opaque layout data.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// This method is unsafe because it modifies the given node during
|
|
||||||
/// layout. Callers should ensure that no other layout thread is
|
|
||||||
/// attempting to read or modify the opaque layout data of this node.
|
|
||||||
fn initialize_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self);
|
|
||||||
|
|
||||||
/// Get the [`StyleData`] for this node. Returns None if the node is unstyled.
|
/// Get the [`StyleData`] for this node. Returns None if the node is unstyled.
|
||||||
fn style_data(&self) -> Option<&'dom StyleData>;
|
fn style_data(&self) -> Option<&'dom StyleData>;
|
||||||
|
|
||||||
|
@ -157,6 +148,15 @@ pub trait ThreadSafeLayoutNode<'dom>: Clone + Copy + Debug + NodeInfo + PartialE
|
||||||
/// the parent until all the children have been processed.
|
/// the parent until all the children have been processed.
|
||||||
fn parent_style(&self) -> Arc<ComputedValues>;
|
fn parent_style(&self) -> Arc<ComputedValues>;
|
||||||
|
|
||||||
|
/// Initialize this node with empty opaque layout data.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This method is unsafe because it modifies the given node during
|
||||||
|
/// layout. Callers should ensure that no other layout thread is
|
||||||
|
/// attempting to read or modify the opaque layout data of this node.
|
||||||
|
fn initialize_layout_data<RequestedLayoutDataType: LayoutDataTrait>(&self);
|
||||||
|
|
||||||
fn debug_id(self) -> usize;
|
fn debug_id(self) -> usize;
|
||||||
|
|
||||||
/// Returns an iterator over this node's children.
|
/// Returns an iterator over this node's children.
|
||||||
|
@ -186,16 +186,6 @@ pub trait ThreadSafeLayoutNode<'dom>: Clone + Copy + Debug + NodeInfo + PartialE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_style(&self) -> Arc<ComputedValues> {
|
|
||||||
if let Some(el) = self.as_element() {
|
|
||||||
el.selected_style()
|
|
||||||
} else {
|
|
||||||
debug_assert!(self.is_text_node());
|
|
||||||
// TODO(stshine): What should the selected style be for text?
|
|
||||||
self.parent_style()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this node contributes content. This is used in the implementation of
|
/// Returns true if this node contributes content. This is used in the implementation of
|
||||||
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
|
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
|
||||||
fn is_content(&self) -> bool {
|
fn is_content(&self) -> bool {
|
||||||
|
@ -353,16 +343,6 @@ pub trait ThreadSafeLayoutElement<'dom>:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn selected_style(&self) -> Arc<ComputedValues> {
|
|
||||||
let data = self.style_data();
|
|
||||||
data.styles
|
|
||||||
.pseudos
|
|
||||||
.get(&PseudoElement::Selection)
|
|
||||||
.unwrap_or(data.styles.primary())
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_shadow_host(&self) -> bool;
|
fn is_shadow_host(&self) -> bool;
|
||||||
|
|
||||||
/// Returns whether this node is a body element of an html element root
|
/// Returns whether this node is a body element of an html element root
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue