diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 89c895ca4f2..2e05b1ed694 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -1318,6 +1318,9 @@ impl<'a, 'ln, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln>> return false } + if node.in_fragmentation_container() { + return false + } let mut style = node.style().clone(); let mut data = node.mutate_layout_data().unwrap(); diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 8d4f818d2b6..652dd8c6359 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -50,7 +50,7 @@ use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers; use script::dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; use script::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers}; use script::dom::node::{HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY}; -use script::dom::node::{LayoutNodeHelpers, Node, OpaqueStyleAndLayoutData}; +use script::dom::node::{IN_FRAGMENTATION_CONTAINER, LayoutNodeHelpers, Node, OpaqueStyleAndLayoutData}; use script::dom::text::Text; use script::layout_interface::TrustedNodeAddress; use selectors::matching::DeclarationBlock; @@ -226,6 +226,14 @@ impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> { self.node.set_flag(HAS_DIRTY_DESCENDANTS, value) } + fn in_fragmentation_container(&self) -> bool { + unsafe { self.node.get_flag(IN_FRAGMENTATION_CONTAINER) } + } + + unsafe fn set_in_fragmentation_container(&self, value: bool) { + self.node.set_flag(IN_FRAGMENTATION_CONTAINER, value) + } + unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> { self.borrow_layout_data_unchecked().map(|d| &(*d).style_data as *const PrivateStyleData) } @@ -753,6 +761,8 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized { } } + fn in_fragmentation_container(&self) -> bool; + /// If this is a text node, generated content, or a form element, copies out /// its content. Otherwise, panics. /// @@ -929,6 +939,10 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> { } } + fn in_fragmentation_container(&self) -> bool { + self.node.in_fragmentation_container() + } + fn text_content(&self) -> TextContent { if self.pseudo != PseudoElementType::Normal { let data = &self.borrow_layout_data().unwrap().style_data; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index e5d1367e993..3f8bcefeef8 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -144,6 +144,9 @@ bitflags! { #[doc = "Specifies whether this node is focusable and whether it is supposed \ to be reachable with using sequential focus navigation."] const SEQUENTIALLY_FOCUSABLE = 0x20, + + /// Whether any ancestor is a fragmentation container + const IN_FRAGMENTATION_CONTAINER = 0x40 } } diff --git a/components/style/dom.rs b/components/style/dom.rs index 25656b22e5c..63c645901b3 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -129,6 +129,10 @@ pub trait TNode<'ln> : Sized + Copy + Clone { } } + fn in_fragmentation_container(&self) -> bool; + + unsafe fn set_in_fragmentation_container(&self, value: bool); + /// Borrows the PrivateStyleData without checks. #[inline(always)] unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData>; diff --git a/components/style/matching.rs b/components/style/matching.rs index b8f555edc02..f2a1515ef07 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -700,6 +700,11 @@ pub trait MatchMethods<'ln> : TNode<'ln> { // This method needs to borrow the data as mutable, so make sure data_ref goes out of // scope first. self.set_restyle_damage(damage); + + self.set_in_fragmentation_container( + parent.as_ref().map_or(false, |p| p.in_fragmentation_container()) || + self.borrow_data().unwrap().style.as_ref().unwrap().is_multicol() + ); } } } diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index 1c71181e795..77563f91ee3 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -182,6 +182,17 @@ impl<'ln> TNode<'ln> for GeckoNode<'ln> { unimplemented!() } + fn in_fragmentation_container(&self) -> bool { + // FIXME(SimonSapin): Servo uses this to implement CSS multicol / fragmentation + // Maybe this isn’t useful for Gecko? + false + } + + unsafe fn set_in_fragmentation_container(&self, _value: bool) { + // FIXME(SimonSapin): Servo uses this to implement CSS multicol / fragmentation + // Maybe this isn’t useful for Gecko? + } + #[inline(always)] unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> { self.get_node_data().as_ref().map(|d| d.as_unsafe_cell().get() as *const PrivateStyleData)