Allow the ComputedValues in ComputedStyle to be null.

This is necessary to start synthesizing the styles in match_element and avoid
round-tripping them through the caller.
This commit is contained in:
Bobby Holley 2017-02-08 15:13:21 -08:00
parent 1c530f9279
commit 5873de3fb6
8 changed files with 53 additions and 32 deletions

View file

@ -777,7 +777,7 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
debug_assert!(self.is_text_node()); debug_assert!(self.is_text_node());
let parent = self.node.parent_node().unwrap().as_element().unwrap(); let parent = self.node.parent_node().unwrap().as_element().unwrap();
let parent_data = parent.get_data().unwrap().borrow(); let parent_data = parent.get_data().unwrap().borrow();
parent_data.styles().primary.values.clone() parent_data.styles().primary.values().clone()
} }
fn debug_id(self) -> usize { fn debug_id(self) -> usize {

View file

@ -389,7 +389,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> { fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> {
match self.get_pseudo_element_type() { match self.get_pseudo_element_type() {
PseudoElementType::Normal => self.get_style_data().unwrap().borrow() PseudoElementType::Normal => self.get_style_data().unwrap().borrow()
.styles().primary.values.clone(), .styles().primary.values().clone(),
other => { other => {
// Precompute non-eagerly-cascaded pseudo-element styles if not // Precompute non-eagerly-cascaded pseudo-element styles if not
// cached before. // cached before.
@ -406,7 +406,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
let new_style = let new_style =
context.stylist.precomputed_values_for_pseudo( context.stylist.precomputed_values_for_pseudo(
&style_pseudo, &style_pseudo,
Some(&data.styles().primary.values), Some(data.styles().primary.values()),
&context.default_computed_values, &context.default_computed_values,
false); false);
data.styles_mut().pseudos data.styles_mut().pseudos
@ -424,7 +424,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
.lazily_compute_pseudo_element_style( .lazily_compute_pseudo_element_style(
unsafe { &self.unsafe_get() }, unsafe { &self.unsafe_get() },
&style_pseudo, &style_pseudo,
&data.styles().primary.values, data.styles().primary.values(),
&context.default_computed_values); &context.default_computed_values);
data.styles_mut().pseudos data.styles_mut().pseudos
.insert(style_pseudo.clone(), new_style.unwrap()); .insert(style_pseudo.clone(), new_style.unwrap());
@ -434,7 +434,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
self.get_style_data().unwrap().borrow() self.get_style_data().unwrap().borrow()
.styles().pseudos.get(&style_pseudo) .styles().pseudos.get(&style_pseudo)
.unwrap().values.clone() .unwrap().values().clone()
} }
} }
} }
@ -445,7 +445,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
data.styles().pseudos data.styles().pseudos
.get(&PseudoElement::Selection).map(|s| s) .get(&PseudoElement::Selection).map(|s| s)
.unwrap_or(&data.styles().primary) .unwrap_or(&data.styles().primary)
.values.clone() .values().clone()
} }
/// Returns the already resolved style of the node. /// Returns the already resolved style of the node.
@ -460,10 +460,10 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
let data = self.get_style_data().unwrap().borrow(); let data = self.get_style_data().unwrap().borrow();
match self.get_pseudo_element_type() { match self.get_pseudo_element_type() {
PseudoElementType::Normal PseudoElementType::Normal
=> data.styles().primary.values.clone(), => data.styles().primary.values().clone(),
other other
=> data.styles().pseudos => data.styles().pseudos
.get(&other.style_pseudo_element()).unwrap().values.clone(), .get(&other.style_pseudo_element()).unwrap().values().clone(),
} }
} }
} }

View file

@ -30,8 +30,9 @@ pub struct ComputedStyle {
pub rules: StrongRuleNode, pub rules: StrongRuleNode,
/// The computed values for each property obtained by cascading the /// The computed values for each property obtained by cascading the
/// matched rules. /// matched rules. This can only be none during a transient interval of
pub values: Arc<ComputedValues>, /// the styling algorithm, and callers can safely unwrap it.
pub values: Option<Arc<ComputedValues>>,
} }
impl ComputedStyle { impl ComputedStyle {
@ -39,9 +40,29 @@ impl ComputedStyle {
pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self { pub fn new(rules: StrongRuleNode, values: Arc<ComputedValues>) -> Self {
ComputedStyle { ComputedStyle {
rules: rules, rules: rules,
values: values, values: Some(values),
} }
} }
/// Constructs a partial ComputedStyle, whose ComputedVaues will be filled
/// in later.
pub fn new_partial(rules: StrongRuleNode) -> Self {
ComputedStyle {
rules: rules,
values: None,
}
}
/// Returns a reference to the ComputedValues. The values can only be null during
/// the styling algorithm, so this is safe to call elsewhere.
pub fn values(&self) -> &Arc<ComputedValues> {
self.values.as_ref().unwrap()
}
/// Mutable version of the above.
pub fn values_mut(&mut self) -> &mut Arc<ComputedValues> {
self.values.as_mut().unwrap()
}
} }
// We manually implement Debug for ComputedStyle so that we can avoid the // We manually implement Debug for ComputedStyle so that we can avoid the
@ -121,7 +142,7 @@ impl ElementStyles {
/// Whether this element `display` value is `none`. /// Whether this element `display` value is `none`.
pub fn is_display_none(&self) -> bool { pub fn is_display_none(&self) -> bool {
self.primary.values.get_box().clone_display() == display::T::none self.primary.values().get_box().clone_display() == display::T::none
} }
} }

View file

@ -197,7 +197,7 @@ fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n: N) -> f
let dd = el.has_dirty_descendants(); let dd = el.has_dirty_descendants();
let data = el.borrow_data(); let data = el.borrow_data();
let styles = data.as_ref().and_then(|d| d.get_styles()); let styles = data.as_ref().and_then(|d| d.get_styles());
let values = styles.map(|s| &s.primary.values); let values = styles.map(|s| s.primary.values());
write!(f, "{:?} dd={} data={:?} values={:?}", el, dd, &data, values) write!(f, "{:?} dd={} data={:?} values={:?}", el, dd, &data, values)
} else { } else {
write!(f, "{:?}", n) write!(f, "{:?}", n)

View file

@ -737,9 +737,9 @@ pub trait MatchMethods : TElement {
// can decide more easily if it knows that it's a child of // can decide more easily if it knows that it's a child of
// replaced content, or similar stuff! // replaced content, or similar stuff!
let maybe_damage = { let maybe_damage = {
let previous = data.get_styles().map(|x| &x.primary.values); let previous = data.get_styles().map(|x| x.primary.values());
let existing = self.existing_style_for_restyle_damage(previous, None); let existing = self.existing_style_for_restyle_damage(previous, None);
existing.map(|e| RestyleDamage::compute(e, &shared_style.values)) existing.map(|e| RestyleDamage::compute(e, &shared_style.values()))
}; };
if let Some(d) = maybe_damage { if let Some(d) = maybe_damage {
data.restyle_mut().damage |= d; data.restyle_mut().damage |= d;
@ -887,7 +887,7 @@ pub trait MatchMethods : TElement {
// specific with that frame, but not wanting to flush all of // specific with that frame, but not wanting to flush all of
// layout). // layout).
debug_assert!(cfg!(feature = "gecko") || d.has_current_styles()); debug_assert!(cfg!(feature = "gecko") || d.has_current_styles());
&d.styles().primary.values d.styles().primary.values()
}); });
let mut new_styles; let mut new_styles;
@ -901,9 +901,9 @@ pub trait MatchMethods : TElement {
// Update animations before the cascade. This may modify the // Update animations before the cascade. This may modify the
// value of the old primary style. // value of the old primary style.
self.update_animations_for_cascade(&context.shared, self.update_animations_for_cascade(&context.shared,
&mut previous.primary.values, previous.primary.values_mut(),
&mut possibly_expired_animations); &mut possibly_expired_animations);
(Some(&previous.primary.values), Some(&mut previous.pseudos)) (Some(previous.primary.values()), Some(&mut previous.pseudos))
} }
}; };
@ -924,7 +924,7 @@ pub trait MatchMethods : TElement {
let damage = let damage =
self.compute_damage_and_cascade_pseudos(old_primary, self.compute_damage_and_cascade_pseudos(old_primary,
old_pseudos, old_pseudos,
&new_styles.primary.values, &new_styles.primary.values(),
&mut new_styles.pseudos, &mut new_styles.pseudos,
context, context,
pseudo_rule_nodes, pseudo_rule_nodes,
@ -987,7 +987,7 @@ pub trait MatchMethods : TElement {
// Update animations before the cascade. This may modify // Update animations before the cascade. This may modify
// the value of old_pseudo_style. // the value of old_pseudo_style.
self.update_animations_for_cascade(&context.shared, self.update_animations_for_cascade(&context.shared,
&mut old_pseudo_style.values, old_pseudo_style.values_mut(),
possibly_expired_animations); possibly_expired_animations);
} }
} }
@ -996,7 +996,7 @@ pub trait MatchMethods : TElement {
self.cascade_node_pseudo_element(context, self.cascade_node_pseudo_element(context,
Some(new_primary), Some(new_primary),
maybe_old_pseudo_style.as_ref() maybe_old_pseudo_style.as_ref()
.map(|s| &s.values), .map(|s| s.values()),
&new_rule_node, &new_rule_node,
&possibly_expired_animations, &possibly_expired_animations,
CascadeBooleans { CascadeBooleans {
@ -1008,7 +1008,7 @@ pub trait MatchMethods : TElement {
if damage != rebuild_and_reflow { if damage != rebuild_and_reflow {
damage = damage | match maybe_old_pseudo_style { damage = damage | match maybe_old_pseudo_style {
None => rebuild_and_reflow, None => rebuild_and_reflow,
Some(ref old) => self.compute_restyle_damage(Some(&old.values), Some(ref old) => self.compute_restyle_damage(Some(old.values()),
&new_pseudo_values, &new_pseudo_values,
Some(&pseudo)), Some(&pseudo)),
}; };

View file

@ -349,7 +349,7 @@ impl Stylist {
} }
}; };
self.precomputed_values_for_pseudo(&pseudo, Some(parent_style), default_style, inherit_all) self.precomputed_values_for_pseudo(&pseudo, Some(parent_style), default_style, inherit_all)
.values .values.unwrap()
} }
/// Computes a pseudo-element style lazily during layout. /// Computes a pseudo-element style lazily during layout.

View file

@ -246,7 +246,7 @@ pub trait DomTraversal<E: TElement> : Sync {
// recursively drops Servo ElementData when the XBL insertion parent of // recursively drops Servo ElementData when the XBL insertion parent of
// an Element is changed. // an Element is changed.
if cfg!(feature = "gecko") && thread_local.is_initial_style() && if cfg!(feature = "gecko") && thread_local.is_initial_style() &&
parent_data.styles().primary.values.has_moz_binding() { parent_data.styles().primary.values().has_moz_binding() {
if log.allow() { debug!("Parent {:?} has XBL binding, deferring traversal", parent); } if log.allow() { debug!("Parent {:?} has XBL binding, deferring traversal", parent); }
return false; return false;
} }
@ -552,7 +552,7 @@ fn compute_style<E, D>(_traversal: &D,
context.thread_local context.thread_local
.style_sharing_candidate_cache .style_sharing_candidate_cache
.insert_if_possible(&element, .insert_if_possible(&element,
&data.styles().primary.values, data.styles().primary.values(),
match_results.relations); match_results.relations);
} }
} }

View file

@ -683,7 +683,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null); let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent, data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent,
data.default_computed_values(), false) data.default_computed_values(), false)
.values .values.unwrap()
.into_strong() .into_strong()
} }
@ -709,7 +709,7 @@ pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
match get_pseudo_style(element, pseudo_tag, data.styles(), doc_data) { match get_pseudo_style(element, pseudo_tag, data.styles(), doc_data) {
Some(values) => values.into_strong(), Some(values) => values.into_strong(),
None if !is_probe => data.styles().primary.values.clone().into_strong(), None if !is_probe => data.styles().primary.values().clone().into_strong(),
None => Strong::null(), None => Strong::null(),
} }
} }
@ -720,13 +720,13 @@ fn get_pseudo_style(element: GeckoElement, pseudo_tag: *mut nsIAtom,
{ {
let pseudo = PseudoElement::from_atom_unchecked(Atom::from(pseudo_tag), false); let pseudo = PseudoElement::from_atom_unchecked(Atom::from(pseudo_tag), false);
match SelectorImpl::pseudo_element_cascade_type(&pseudo) { match SelectorImpl::pseudo_element_cascade_type(&pseudo) {
PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.values.clone()), PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.values().clone()),
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"), PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
PseudoElementCascadeType::Lazy => { PseudoElementCascadeType::Lazy => {
let d = doc_data.borrow_mut(); let d = doc_data.borrow_mut();
let base = &styles.primary.values; let base = styles.primary.values();
d.stylist.lazily_compute_pseudo_element_style(&element, &pseudo, base, &d.default_computed_values()) d.stylist.lazily_compute_pseudo_element_style(&element, &pseudo, base, &d.default_computed_values())
.map(|s| s.values.clone()) .map(|s| s.values().clone())
}, },
} }
} }
@ -1167,7 +1167,7 @@ pub extern "C" fn Servo_ResolveStyle(element: RawGeckoElementBorrowed,
return per_doc_data.default_computed_values().clone().into_strong(); return per_doc_data.default_computed_values().clone().into_strong();
} }
data.styles().primary.values.clone().into_strong() data.styles().primary.values().clone().into_strong()
} }
#[no_mangle] #[no_mangle]
@ -1184,7 +1184,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
} else { } else {
None None
}; };
maybe_pseudo.unwrap_or_else(|| styles.primary.values.clone()) maybe_pseudo.unwrap_or_else(|| styles.primary.values().clone())
}; };
// In the common case we already have the style. Check that before setting // In the common case we already have the style. Check that before setting