aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/dom.rs15
-rw-r--r--components/style/gecko/wrapper.rs26
-rw-r--r--components/style/matching.rs26
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)
}
}