diff --git a/components/style/matching.rs b/components/style/matching.rs index e10c19baaca0..320546147bfd 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -17,7 +17,7 @@ use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_T use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE}; use invalidation::element::restyle_hints::RestyleHint; use log::LogLevel::Trace; -use properties::{ALLOW_SET_ROOT_FONT_SIZE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP}; +use properties::{ALLOW_SET_ROOT_FONT_SIZE, PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP}; use properties::{AnimationRules, CascadeFlags, ComputedValues}; use properties::{VISITED_DEPENDENT_ONLY, cascade}; use properties::longhands::display::computed_value as display; @@ -29,15 +29,23 @@ use sharing::StyleSharingBehavior; use stylearc::Arc; use stylist::RuleInclusion; -/// The way a style should be inherited. -enum InheritMode { +/// Whether we are cascading for an eager pseudo-element or something else. +/// +/// Controls where we inherit styles from, and whether display:contents is +/// prohibited. +#[derive(PartialEq, Copy, Clone)] +enum CascadeTarget { /// Inherit from the parent element, as normal CSS dictates, _or_ from the /// closest non-Native Anonymous element in case this is Native Anonymous - /// Content. + /// Content. display:contents is allowed. Normal, /// Inherit from the primary style, this is used while computing eager /// pseudos, like ::before and ::after when we're traversing the parent. - FromPrimaryStyle, + /// Also prohibits display:contents from having an effect. + /// + /// TODO(emilio) display:contents really should apply to ::before/::after. + /// https://github.com/w3c/csswg-drafts/issues/1345 + EagerPseudo, } /// Represents the result of comparing an element's old and new style. @@ -251,7 +259,7 @@ trait PrivateMatchMethods: TElement { font_metrics_provider: &FontMetricsProvider, rule_node: &StrongRuleNode, primary_style: &ComputedStyle, - inherit_mode: InheritMode, + cascade_target: CascadeTarget, cascade_visited: CascadeVisitedMode, visited_values_to_insert: Option>) -> Arc { @@ -263,15 +271,17 @@ trait PrivateMatchMethods: TElement { if cascade_visited.visited_dependent_only() { cascade_flags.insert(VISITED_DEPENDENT_ONLY); } - if !self.is_native_anonymous() { + if self.is_native_anonymous() || cascade_target == CascadeTarget::EagerPseudo { + cascade_flags.insert(PROHIBIT_DISPLAY_CONTENTS); + } else { cascade_flags.insert(ALLOW_SET_ROOT_FONT_SIZE); } // Grab the inherited values. let parent_el; let parent_data; - let style_to_inherit_from = match inherit_mode { - InheritMode::Normal => { + let style_to_inherit_from = match cascade_target { + CascadeTarget::Normal => { parent_el = self.inheritance_parent(); parent_data = parent_el.as_ref().and_then(|e| e.borrow_data()); let parent_style = parent_data.as_ref().map(|d| { @@ -287,7 +297,7 @@ trait PrivateMatchMethods: TElement { }); parent_style.map(|s| cascade_visited.values(s)) } - InheritMode::FromPrimaryStyle => { + CascadeTarget::EagerPseudo => { parent_el = Some(self.clone()); Some(cascade_visited.values(primary_style)) } @@ -390,17 +400,17 @@ trait PrivateMatchMethods: TElement { // Grab the rule node. let style = eager_pseudo_style.unwrap_or(primary_style); let rule_node = cascade_visited.rules(style); - let inherit_mode = if eager_pseudo_style.is_some() { - InheritMode::FromPrimaryStyle + let cascade_target = if eager_pseudo_style.is_some() { + CascadeTarget::EagerPseudo } else { - InheritMode::Normal + CascadeTarget::Normal }; self.cascade_with_rules(context.shared, &context.thread_local.font_metrics_provider, rule_node, primary_style, - inherit_mode, + cascade_target, cascade_visited, visited_values_to_insert) } @@ -536,7 +546,7 @@ trait PrivateMatchMethods: TElement { &context.thread_local.font_metrics_provider, &without_transition_rules, primary_style, - InheritMode::Normal, + CascadeTarget::Normal, CascadeVisitedMode::Unvisited, None)) } @@ -1480,7 +1490,7 @@ pub trait MatchMethods : TElement { font_metrics_provider, &without_animation_rules, primary_style, - InheritMode::Normal, + CascadeTarget::Normal, CascadeVisitedMode::Unvisited, None) } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 72af0a2d6d77..0ba5e29314eb 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2479,6 +2479,10 @@ bitflags! { /// ::backdrop and all NAC will resolve rem units against /// the toplevel root element now. const ALLOW_SET_ROOT_FONT_SIZE = 0x08, + /// Whether to convert display:contents into display:inline. This + /// is used by Gecko to prevent display:contents on generated + /// content. + const PROHIBIT_DISPLAY_CONTENTS = 0x10, } } @@ -2851,8 +2855,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device, { StyleAdjuster::new(&mut style, is_root_element) - .adjust(context.layout_parent_style, - flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)); + .adjust(context.layout_parent_style, flags); } % if product == "gecko": diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 8d148c5360c2..19ceecedca7a 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -6,7 +6,10 @@ //! for it to adhere to the CSS spec. use app_units::Au; -use properties::{self, ComputedValues, StyleBuilder}; +use properties::{self, CascadeFlags, ComputedValues}; +use properties::{SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, StyleBuilder}; +#[cfg(feature = "gecko")] +use properties::PROHIBIT_DISPLAY_CONTENTS; use properties::longhands::display::computed_value::T as display; use properties::longhands::float::computed_value::T as float; use properties::longhands::overflow_x::computed_value::T as overflow; @@ -54,7 +57,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo fn blockify_if_necessary(&mut self, layout_parent_style: &ComputedValues, - skip_root_and_element_display_fixup: bool) { + flags: CascadeFlags) { let mut blockify = false; macro_rules! blockify_if { ($if_what:expr) => { @@ -64,7 +67,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } } - if !skip_root_and_element_display_fixup { + if !flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) { blockify_if!(self.is_root_element); blockify_if!(layout_parent_style.get_box().clone_display().is_item_container()); } @@ -275,6 +278,19 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } } + /// Native anonymous content converts display:contents into display:inline. + #[cfg(feature = "gecko")] + fn adjust_for_prohibited_display_contents(&mut self, flags: CascadeFlags) { + // TODO: We should probably convert display:contents into display:none + // in some cases too: https://drafts.csswg.org/css-display/#unbox + if !flags.contains(PROHIBIT_DISPLAY_CONTENTS) || + self.style.get_box().clone_display() != display::contents { + return; + } + + self.style.mutate_box().set_display(display::inline); + } + /// -moz-center, -moz-left and -moz-right are used for HTML's alignment. /// /// This is covering the
...
case. @@ -305,10 +321,13 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// `nsStyleContext::ApplyStyleFixups`. pub fn adjust(&mut self, layout_parent_style: &ComputedValues, - skip_root_and_element_display_fixup: bool) { + flags: CascadeFlags) { + #[cfg(feature = "gecko")] + { + self.adjust_for_prohibited_display_contents(flags); + } self.adjust_for_top_layer(); - self.blockify_if_necessary(layout_parent_style, - skip_root_and_element_display_fixup); + self.blockify_if_necessary(layout_parent_style, flags); self.adjust_for_position(); self.adjust_for_overflow(); #[cfg(feature = "gecko")]