aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Brubeck <mbrubeck@limpet.net>2016-05-25 10:48:09 -0700
committerMatt Brubeck <mbrubeck@limpet.net>2016-05-25 11:54:21 -0700
commit5c09e26e55bd7c013296403b86b0500101189ce4 (patch)
tree2389c686f631b873105a6d711652ae9b518efad4
parent116faa7617aa2cb648d57307505b23504900bc9f (diff)
downloadservo-5c09e26e55bd7c013296403b86b0500101189ce4.tar.gz
servo-5c09e26e55bd7c013296403b86b0500101189ce4.zip
Stop generating flows under display: none.
Because this is a bottom-up traversal it can generates flows and throw them away. To prevent that, this cascades an internal `-servo-under-display-none` property and then checks that during flow construction. Fixes #1536.
-rw-r--r--components/layout/construct.rs19
-rw-r--r--components/layout/incremental.rs1
-rw-r--r--components/layout/traversal.rs2
-rw-r--r--components/style/properties/longhand/box.mako.rs1
-rw-r--r--components/style/properties/longhand/inherited_box.mako.rs37
5 files changed, 50 insertions, 10 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 2a75c4025cb..77b388e8ade 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -1501,7 +1501,15 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS
//
// TODO: This should actually consult the table in that section to get the
// final computed value for 'display'.
- fn process(&mut self, node: &ConcreteThreadSafeLayoutNode) -> bool {
+ fn process(&mut self, node: &ConcreteThreadSafeLayoutNode) {
+ node.insert_flags(HAS_NEWLY_CONSTRUCTED_FLOW);
+
+ // Bail out if this node has an ancestor with display: none.
+ if node.style(self.style_context()).get_inheritedbox()._servo_under_display_none.0 {
+ self.set_flow_construction_result(node, ConstructionResult::None);
+ return;
+ }
+
// Get the `display` property for this node, and determine whether this node is floated.
let (display, float, positioning) = match node.type_id() {
None => {
@@ -1542,12 +1550,8 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS
// Switch on display and floatedness.
match (display, float, positioning) {
- // `display: none` contributes no flow construction result. Nuke the flow construction
- // results of children.
+ // `display: none` contributes no flow construction result.
(display::T::none, _, _) => {
- for child in node.children() {
- self.set_flow_construction_result(&child, ConstructionResult::None);
- }
self.set_flow_construction_result(node, ConstructionResult::None);
}
@@ -1654,9 +1658,6 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS
self.set_flow_construction_result(node, construction_result)
}
}
-
- node.insert_flags(HAS_NEWLY_CONSTRUCTED_FLOW);
- true
}
}
diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs
index 9670028cfa3..e0c5d804295 100644
--- a/components/layout/incremental.rs
+++ b/components/layout/incremental.rs
@@ -178,6 +178,7 @@ pub fn compute_damage(old: Option<&Arc<ServoComputedValues>>, new: &ServoCompute
], [
get_box.float, get_box.display, get_box.position, get_counters.content,
get_counters.counter_reset, get_counters.counter_increment,
+ get_inheritedbox._servo_under_display_none,
get_list.quotes, get_list.list_style_type,
// If these text or font properties change, we need to reconstruct the flow so that
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index 1fe5388549e..692d956f000 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -72,7 +72,7 @@ impl<'lc, 'ln> DomTraversalContext<ServoLayoutNode<'ln>> for RecalcStyleAndConst
/// A bottom-up, parallelizable traversal.
pub trait PostorderNodeMutTraversal<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> {
/// The operation to perform. Return true to continue or false to stop.
- fn process(&mut self, node: &ConcreteThreadSafeLayoutNode) -> bool;
+ fn process(&mut self, node: &ConcreteThreadSafeLayoutNode);
}
/// The flow construction traversal, which builds flows for styled nodes.
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index f80a42c88d2..aa0b416824d 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -78,6 +78,7 @@
_error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
longhands::_servo_text_decorations_in_effect::derive_from_display(context);
+ longhands::_servo_under_display_none::derive_from_display(context);
}
% endif
diff --git a/components/style/properties/longhand/inherited_box.mako.rs b/components/style/properties/longhand/inherited_box.mako.rs
index 6dc6f05c2e7..655d9dac674 100644
--- a/components/style/properties/longhand/inherited_box.mako.rs
+++ b/components/style/properties/longhand/inherited_box.mako.rs
@@ -88,3 +88,40 @@ ${helpers.single_keyword("color-adjust", "economy exact", products="gecko")}
}
}
</%helpers:longhand>
+
+// Used in the bottom-up flow construction traversal to avoid constructing flows for
+// descendants of nodes with `display: none`.
+<%helpers:longhand name="-servo-under-display-none" derived_from="display" products="servo">
+ use cssparser::ToCss;
+ use std::fmt;
+ use values::computed::ComputedValueAsSpecified;
+
+ #[derive(Copy, Clone, Debug, Eq, PartialEq, HeapSizeOf, Serialize, Deserialize)]
+ pub struct SpecifiedValue(pub bool);
+
+ pub mod computed_value {
+ pub type T = super::SpecifiedValue;
+ }
+ impl ComputedValueAsSpecified for SpecifiedValue {}
+
+ pub fn get_initial_value() -> computed_value::T {
+ SpecifiedValue(false)
+ }
+
+ impl ToCss for SpecifiedValue {
+ fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
+ Ok(()) // Internal property
+ }
+ }
+
+ #[inline]
+ pub fn derive_from_display<Cx: TContext>(context: &mut Cx) {
+ use properties::style_struct_traits::Box;
+ use super::display::computed_value::T as Display;
+
+ if context.style().get_box().clone_display() == Display::none {
+ context.mutate_style().mutate_inheritedbox()
+ .set__servo_under_display_none(SpecifiedValue(true));
+ }
+ }
+</%helpers:longhand>