mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Cheat the system and use an Arc in BoxSlot
Ideally we want to be able to borrow from the DOM during box construction but that's not playing very well at the moment with the current bridge between script and layout.
This commit is contained in:
parent
745857066c
commit
c08cfbb5f3
3 changed files with 46 additions and 39 deletions
|
@ -6,10 +6,11 @@ use crate::element_data::{LayoutBox, LayoutDataForElement};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
|
||||||
use crate::wrapper::GetRawData;
|
use crate::wrapper::GetRawData;
|
||||||
use atomic_refcell::AtomicRefMut;
|
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||||
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::marker::PhantomData as marker;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::dom::TNode;
|
use style::dom::TNode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -43,7 +44,10 @@ pub(super) enum PseudoElementContentItem {
|
||||||
Replaced(ReplacedContent),
|
Replaced(ReplacedContent),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) trait TraversalHandler<Node> {
|
pub(super) trait TraversalHandler<'dom, Node>
|
||||||
|
where
|
||||||
|
Node: 'dom,
|
||||||
|
{
|
||||||
fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>);
|
fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>);
|
||||||
|
|
||||||
/// Or pseudo-element
|
/// Or pseudo-element
|
||||||
|
@ -52,14 +56,14 @@ pub(super) trait TraversalHandler<Node> {
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
display: DisplayGeneratingBox,
|
display: DisplayGeneratingBox,
|
||||||
contents: Contents<Node>,
|
contents: Contents<Node>,
|
||||||
box_slot: BoxSlot,
|
box_slot: BoxSlot<'dom>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_children_of<'dom, Node>(
|
fn traverse_children_of<'dom, Node>(
|
||||||
parent_element: Node,
|
parent_element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -81,7 +85,7 @@ fn traverse_children_of<'dom, Node>(
|
||||||
fn traverse_element<'dom, Node>(
|
fn traverse_element<'dom, Node>(
|
||||||
element: Node,
|
element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -94,7 +98,7 @@ fn traverse_element<'dom, Node>(
|
||||||
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
||||||
element.unset_boxes_in_subtree()
|
element.unset_boxes_in_subtree()
|
||||||
} else {
|
} else {
|
||||||
element.layout_data_mut().self_box = Some(LayoutBox::DisplayContents);
|
*element.layout_data_mut().self_box.borrow_mut() = Some(LayoutBox::DisplayContents);
|
||||||
traverse_children_of(element, context, handler)
|
traverse_children_of(element, context, handler)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -116,7 +120,7 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
which: WhichPseudoElement,
|
which: WhichPseudoElement,
|
||||||
element: Node,
|
element: Node,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -141,7 +145,7 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
fn traverse_pseudo_element_contents<'dom, Node>(
|
fn traverse_pseudo_element_contents<'dom, Node>(
|
||||||
pseudo_element_style: &Arc<ComputedValues>,
|
pseudo_element_style: &Arc<ComputedValues>,
|
||||||
items: Vec<PseudoElementContentItem>,
|
items: Vec<PseudoElementContentItem>,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) where
|
) where
|
||||||
Node: 'dom,
|
Node: 'dom,
|
||||||
{
|
{
|
||||||
|
@ -201,7 +205,7 @@ where
|
||||||
self,
|
self,
|
||||||
inherited_style: &Arc<ComputedValues>,
|
inherited_style: &Arc<ComputedValues>,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
handler: &mut impl TraversalHandler<Node>,
|
handler: &mut impl TraversalHandler<'dom, Node>,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler),
|
NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler),
|
||||||
|
@ -239,22 +243,25 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct BoxSlot<'dom> {
|
pub(super) struct BoxSlot<'dom> {
|
||||||
slot: Option<AtomicRefMut<'dom, Option<LayoutBox>>>,
|
slot: Option<Arc<AtomicRefCell<Option<LayoutBox>>>>,
|
||||||
|
marker: marker<&'dom ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom> BoxSlot<'dom> {
|
impl BoxSlot<'_> {
|
||||||
pub fn new(mut slot: AtomicRefMut<'dom, Option<LayoutBox>>) -> Self {
|
pub fn new(slot: Arc<AtomicRefCell<Option<LayoutBox>>>) -> Self {
|
||||||
*slot = None;
|
*slot.borrow_mut() = None;
|
||||||
Self { slot: Some(slot) }
|
let slot = Some(slot);
|
||||||
|
Self { slot, marker }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dummy() -> Self {
|
pub fn dummy() -> Self {
|
||||||
Self { slot: None }
|
let slot = None;
|
||||||
|
Self { slot, marker }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(mut self, box_: LayoutBox) {
|
pub fn set(mut self, box_: LayoutBox) {
|
||||||
if let Some(slot) = &mut self.slot {
|
if let Some(slot) = &mut self.slot {
|
||||||
**slot = Some(box_)
|
*slot.borrow_mut() = Some(box_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +269,7 @@ impl<'dom> BoxSlot<'dom> {
|
||||||
impl Drop for BoxSlot<'_> {
|
impl Drop for BoxSlot<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(slot) = &mut self.slot {
|
if let Some(slot) = &mut self.slot {
|
||||||
assert!(slot.is_some(), "failed to set a layout box")
|
assert!(slot.borrow().is_some(), "failed to set a layout box");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,8 +283,8 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync {
|
||||||
fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>;
|
fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>;
|
||||||
|
|
||||||
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
|
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
|
||||||
fn element_box_slot(&self) -> BoxSlot;
|
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot;
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
||||||
fn unset_boxes_in_subtree(self);
|
fn unset_boxes_in_subtree(self);
|
||||||
}
|
}
|
||||||
|
@ -320,27 +327,25 @@ where
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_box_slot(&self) -> BoxSlot {
|
fn element_box_slot(&self) -> BoxSlot<'dom> {
|
||||||
BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| {
|
BoxSlot::new(self.layout_data_mut().self_box.clone())
|
||||||
&mut data.self_box
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot {
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
||||||
BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| {
|
let mut data = self.layout_data_mut();
|
||||||
let pseudos = data.pseudo_elements.get_or_insert_with(Default::default);
|
let pseudos = data.pseudo_elements.get_or_insert_with(Default::default);
|
||||||
match which {
|
let cell = match which {
|
||||||
WhichPseudoElement::Before => &mut pseudos.before,
|
WhichPseudoElement::Before => &mut pseudos.before,
|
||||||
WhichPseudoElement::After => &mut pseudos.after,
|
WhichPseudoElement::After => &mut pseudos.after,
|
||||||
}
|
};
|
||||||
}))
|
BoxSlot::new(cell.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
||||||
if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements {
|
if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements {
|
||||||
match which {
|
match which {
|
||||||
WhichPseudoElement::Before => pseudos.before = None,
|
WhichPseudoElement::Before => *pseudos.before.borrow_mut() = None,
|
||||||
WhichPseudoElement::After => pseudos.after = None,
|
WhichPseudoElement::After => *pseudos.after.borrow_mut() = None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +357,8 @@ where
|
||||||
let traverse_children = {
|
let traverse_children = {
|
||||||
let mut layout_data = node.layout_data_mut();
|
let mut layout_data = node.layout_data_mut();
|
||||||
layout_data.pseudo_elements = None;
|
layout_data.pseudo_elements = None;
|
||||||
layout_data.self_box.take().is_some()
|
let self_box = layout_data.self_box.borrow_mut().take();
|
||||||
|
self_box.is_some()
|
||||||
};
|
};
|
||||||
if traverse_children {
|
if traverse_children {
|
||||||
// Only descend into children if we removed a box.
|
// Only descend into children if we removed a box.
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
|
|
||||||
use crate::flow::inline::InlineLevelBox;
|
use crate::flow::inline::InlineLevelBox;
|
||||||
use crate::flow::BlockLevelBox;
|
use crate::flow::BlockLevelBox;
|
||||||
|
use atomic_refcell::AtomicRefCell;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct LayoutDataForElement {
|
pub(crate) struct LayoutDataForElement {
|
||||||
pub(super) self_box: Option<LayoutBox>,
|
pub(super) self_box: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
|
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct PseudoElementBoxes {
|
pub(super) struct PseudoElementBoxes {
|
||||||
pub before: Option<LayoutBox>,
|
pub before: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
pub after: Option<LayoutBox>,
|
pub after: Arc<AtomicRefCell<Option<LayoutBox>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) enum LayoutBox {
|
pub(super) enum LayoutBox {
|
||||||
|
|
|
@ -178,7 +178,7 @@ impl BlockContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, Node> TraversalHandler<Node> for BlockContainerBuilder<'dom, '_, Node>
|
impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node>
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -187,7 +187,7 @@ where
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
display: DisplayGeneratingBox,
|
display: DisplayGeneratingBox,
|
||||||
contents: Contents<Node>,
|
contents: Contents<Node>,
|
||||||
box_slot: BoxSlot,
|
box_slot: BoxSlot<'dom>,
|
||||||
) {
|
) {
|
||||||
match display {
|
match display {
|
||||||
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
|
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue