aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/traversal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/traversal.rs')
-rw-r--r--components/style/traversal.rs61
1 files changed, 57 insertions, 4 deletions
diff --git a/components/style/traversal.rs b/components/style/traversal.rs
index 146069b1bc3..60df72ffeba 100644
--- a/components/style/traversal.rs
+++ b/components/style/traversal.rs
@@ -13,6 +13,7 @@ use restyle_hints::{HintComputationContext, RestyleHint};
use selector_parser::RestyleDamage;
use sharing::StyleSharingBehavior;
#[cfg(feature = "servo")] use servo_config::opts;
+use smallvec::SmallVec;
use std::borrow::BorrowMut;
/// A per-traversal-level chunk of data. This is sent down by the traversal, and
@@ -41,6 +42,8 @@ bitflags! {
/// Traverse and update all elements with CSS animations since
/// @keyframes rules may have changed
const FOR_CSS_RULE_CHANGES = 0x08,
+ /// Only include user agent style sheets when selector matching.
+ const FOR_DEFAULT_STYLES = 0x10,
}
}
@@ -64,6 +67,12 @@ impl TraversalFlags {
pub fn for_css_rule_changes(&self) -> bool {
self.contains(FOR_CSS_RULE_CHANGES)
}
+
+ /// Returns true if the traversal is to compute the default computed
+ /// styles for an element.
+ pub fn for_default_styles(&self) -> bool {
+ self.contains(FOR_DEFAULT_STYLES)
+ }
}
/// This structure exists to enforce that callers invoke pre_traverse, and also
@@ -537,10 +546,13 @@ fn resolve_style_internal<E, F>(context: &mut StyleContext<E>,
StyleSharingBehavior::Disallow);
context.thread_local.end_element(element);
- // Conservatively mark us as having dirty descendants, since there might
- // be other unstyled siblings we miss when walking straight up the parent
- // chain.
- unsafe { element.note_descendants::<DirtyDescendants>() };
+ if !context.shared.traversal_flags.for_default_styles() {
+ // Conservatively mark us as having dirty descendants, since there might
+ // be other unstyled siblings we miss when walking straight up the parent
+ // chain. No need to do this if we're computing default styles, since
+ // resolve_default_style will want the tree to be left as it is.
+ unsafe { element.note_descendants::<DirtyDescendants>() };
+ }
}
// If we're display:none and none of our ancestors are, we're the root
@@ -598,6 +610,47 @@ pub fn resolve_style<E, F, G, H>(context: &mut StyleContext<E>, element: E,
}
}
+/// Manually resolve default styles for the given Element, which are the styles
+/// only taking into account user agent and user cascade levels. The resolved
+/// style is made available via a callback, and will be dropped by the time this
+/// function returns.
+pub fn resolve_default_style<E, F, G, H>(context: &mut StyleContext<E>,
+ element: E,
+ ensure_data: &F,
+ set_data: &G,
+ callback: H)
+ where E: TElement,
+ F: Fn(E),
+ G: Fn(E, Option<ElementData>) -> Option<ElementData>,
+ H: FnOnce(&ElementStyles)
+{
+ // Save and clear out element data from the element and its ancestors.
+ let mut old_data: SmallVec<[(E, Option<ElementData>); 8]> = SmallVec::new();
+ {
+ let mut e = element;
+ loop {
+ old_data.push((e, set_data(e, None)));
+ match e.parent_element() {
+ Some(parent) => e = parent,
+ None => break,
+ }
+ }
+ }
+
+ // Resolve styles up the tree.
+ resolve_style_internal(context, element, ensure_data);
+
+ // Make them available for the scope of the callback. The callee may use the
+ // argument, or perform any other processing that requires the styles to exist
+ // on the Element.
+ callback(element.borrow_data().unwrap().styles());
+
+ // Swap the old element data back into the element and its ancestors.
+ for entry in old_data {
+ set_data(entry.0, entry.1);
+ }
+}
+
/// Calculates the style for a single node.
#[inline]
#[allow(unsafe_code)]