diff options
-rw-r--r-- | components/style/dom.rs | 15 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 26 | ||||
-rw-r--r-- | components/style/matching.rs | 26 |
3 files changed, 59 insertions, 8 deletions
diff --git a/components/style/dom.rs b/components/style/dom.rs index c4647928efb..4dab32eba22 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -325,6 +325,21 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + } } + /// Returns the parent element we should inherit from. + /// + /// This is pretty much always the parent element itself, except in the case + /// of Gecko's Native Anonymous Content, which may need to find the closest + /// non-NAC ancestor. + fn inheritance_parent(&self) -> Option<Self> { + self.parent_element() + } + + /// For a given NAC element, return the closest non-NAC ancestor, which is + /// guaranteed to exist. + fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> { + unreachable!("Servo doesn't know about NAC"); + } + /// Get this element's style attribute. fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 4ac047e41d8..5461bd7768e 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -526,6 +526,32 @@ impl<'le> TElement for GeckoElement<'le> { type ConcreteNode = GeckoNode<'le>; type FontMetricsProvider = GeckoFontMetricsProvider; + fn inheritance_parent(&self) -> Option<Self> { + if self.is_native_anonymous() { + return self.closest_non_native_anonymous_ancestor(); + } + return self.parent_element(); + } + + fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> { + debug_assert!(self.is_native_anonymous()); + let mut parent = match self.parent_element() { + Some(e) => e, + None => return None, + }; + + loop { + if !parent.is_native_anonymous() { + return Some(parent); + } + + parent = match parent.parent_element() { + Some(p) => p, + None => return None, + }; + } + } + fn as_node(&self) -> Self::ConcreteNode { unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) } } diff --git a/components/style/matching.rs b/components/style/matching.rs index f8fbfd493c9..40c2661d245 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -33,8 +33,10 @@ use stylist::ApplicableDeclarationBlock; /// The way a style should be inherited. enum InheritMode { - /// Inherit from the parent element, as normal CSS dictates. - FromParentElement, + /// Inherit from the parent element, as normal CSS dictates, _or_ from the + /// closest non-Native Anonymous element in case this is Native Anonymous + /// Content. + Normal, /// Inherit from the primary style, this is used while computing eager /// pseudos, like ::before and ::after when we're traversing the parent. FromPrimaryStyle, @@ -423,8 +425,8 @@ trait PrivateMatchMethods: TElement { let parent_el; let parent_data; let style_to_inherit_from = match inherit_mode { - InheritMode::FromParentElement => { - parent_el = self.parent_element(); + InheritMode::Normal => { + parent_el = self.inheritance_parent(); parent_data = parent_el.as_ref().and_then(|e| e.borrow_data()); let parent_values = parent_data.as_ref().map(|d| { // Sometimes Gecko eagerly styles things without processing @@ -500,7 +502,7 @@ trait PrivateMatchMethods: TElement { let inherit_mode = if eager_pseudo_style.is_some() { InheritMode::FromPrimaryStyle } else { - InheritMode::FromParentElement + InheritMode::Normal }; self.cascade_with_rules(context.shared, @@ -623,7 +625,7 @@ trait PrivateMatchMethods: TElement { &context.thread_local.font_metrics_provider, &without_transition_rules, primary_style, - InheritMode::FromParentElement)) + InheritMode::Normal)) } #[cfg(feature = "gecko")] @@ -1002,8 +1004,16 @@ pub trait MatchMethods : TElement { self.apply_selector_flags(map, element, flags); }; + let selector_matching_target = match implemented_pseudo { + Some(..) => { + self.closest_non_native_anonymous_ancestor() + .expect("Pseudo-element without non-NAC parent?") + }, + None => *self, + }; + // Compute the primary rule node. - *relations = stylist.push_applicable_declarations(self, + *relations = stylist.push_applicable_declarations(&selector_matching_target, Some(bloom), style_attribute, smil_override, @@ -1448,7 +1458,7 @@ pub trait MatchMethods : TElement { font_metrics_provider, &without_animation_rules, primary_style, - InheritMode::FromParentElement) + InheritMode::Normal) } } |