mirror of
https://github.com/servo/servo.git
synced 2025-06-23 16:44:33 +01:00
style: Allow calling GetBaseComputedStylesForElement for an unstyled element.
Before this refactoring, getComputedStyle could have side effects, and left the style data in the element, so we could never arrive there without data. There are a few crashtests that caught this, but this was already broken if you called animate() on an element deep in a display: none subtree. MozReview-Commit-ID: 1AvOvhAyOP3
This commit is contained in:
parent
c6d5dbbb01
commit
d15acc219e
2 changed files with 33 additions and 39 deletions
|
@ -840,37 +840,6 @@ pub trait MatchMethods : TElement {
|
||||||
// StyleChange::Changed conservatively.
|
// StyleChange::Changed conservatively.
|
||||||
StyleDifference::new(damage, StyleChange::Changed)
|
StyleDifference::new(damage, StyleChange::Changed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns computed values without animation and transition rules.
|
|
||||||
fn get_base_style(
|
|
||||||
&self,
|
|
||||||
context: &mut StyleContext<Self>,
|
|
||||||
style: &Arc<ComputedValues>,
|
|
||||||
) -> Arc<ComputedValues> {
|
|
||||||
use style_resolver::StyleResolverForElement;
|
|
||||||
|
|
||||||
let rule_node = style.rules.as_ref().unwrap();
|
|
||||||
let without_animation_rules =
|
|
||||||
context.shared.stylist.rule_tree().remove_animation_rules(rule_node);
|
|
||||||
if without_animation_rules == *rule_node {
|
|
||||||
// Note that unwrapping here is fine, because the style is only
|
|
||||||
// incomplete during the styling process.
|
|
||||||
return style.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This currently ignores visited styles, which seems acceptable,
|
|
||||||
// as existing browsers don't appear to animate visited styles.
|
|
||||||
let inputs =
|
|
||||||
CascadeInputs {
|
|
||||||
rules: Some(without_animation_rules),
|
|
||||||
visited_rules: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let style =
|
|
||||||
StyleResolverForElement::new(*self, context, RuleInclusion::All)
|
|
||||||
.cascade_style_and_visited_with_default_parents(inputs);
|
|
||||||
style
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: TElement> MatchMethods for E {}
|
impl<E: TElement> MatchMethods for E {}
|
||||||
|
|
|
@ -654,19 +654,35 @@ pub extern "C" fn Servo_AnimationValue_Uncompute(value: RawServoAnimationValueBo
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawServoStyleSetBorrowed,
|
pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawServoStyleSetBorrowed,
|
||||||
element: RawGeckoElementBorrowed,
|
element: RawGeckoElementBorrowed,
|
||||||
|
computed_values: ServoComputedValuesBorrowed,
|
||||||
snapshots: *const ServoElementSnapshotTable,
|
snapshots: *const ServoElementSnapshotTable,
|
||||||
pseudo_type: CSSPseudoElementType)
|
pseudo_type: CSSPseudoElementType)
|
||||||
-> ServoComputedValuesStrong
|
-> ServoComputedValuesStrong
|
||||||
{
|
{
|
||||||
use style::matching::MatchMethods;
|
use style::style_resolver::StyleResolverForElement;
|
||||||
|
|
||||||
debug_assert!(!snapshots.is_null());
|
debug_assert!(!snapshots.is_null());
|
||||||
|
let computed_values = ComputedValues::as_arc(&computed_values);
|
||||||
|
|
||||||
|
let rules = match computed_values.rules {
|
||||||
|
None => return computed_values.clone().into_strong(),
|
||||||
|
Some(ref rules) => rules,
|
||||||
|
};
|
||||||
|
|
||||||
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let without_animations =
|
||||||
let guard = global_style_data.shared_lock.read();
|
doc_data.stylist.rule_tree().remove_animation_rules(rules);
|
||||||
|
|
||||||
|
if without_animations == *rules {
|
||||||
|
return computed_values.clone().into_strong();
|
||||||
|
}
|
||||||
|
|
||||||
let element = GeckoElement(element);
|
let element = GeckoElement(element);
|
||||||
let element_data = element.borrow_data().unwrap();
|
|
||||||
|
let element_data = match element.borrow_data() {
|
||||||
|
Some(data) => data,
|
||||||
|
None => return computed_values.clone().into_strong(),
|
||||||
|
};
|
||||||
let styles = &element_data.styles;
|
let styles = &element_data.styles;
|
||||||
|
|
||||||
if let Some(pseudo) = PseudoElement::from_pseudo_type(pseudo_type) {
|
if let Some(pseudo) = PseudoElement::from_pseudo_type(pseudo_type) {
|
||||||
|
@ -678,6 +694,8 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe
|
||||||
.clone().into_strong();
|
.clone().into_strong();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let guard = global_style_data.shared_lock.read();
|
||||||
let shared = create_shared_context(&global_style_data,
|
let shared = create_shared_context(&global_style_data,
|
||||||
&guard,
|
&guard,
|
||||||
&doc_data,
|
&doc_data,
|
||||||
|
@ -689,10 +707,17 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe
|
||||||
thread_local: &mut tlc,
|
thread_local: &mut tlc,
|
||||||
};
|
};
|
||||||
|
|
||||||
element.get_base_style(
|
// This currently ignores visited styles, which seems acceptable, as
|
||||||
&mut context,
|
// existing browsers don't appear to animate visited styles.
|
||||||
styles.primary(),
|
let inputs =
|
||||||
).into_strong()
|
CascadeInputs {
|
||||||
|
rules: Some(without_animations),
|
||||||
|
visited_rules: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
StyleResolverForElement::new(element, &mut context, RuleInclusion::All)
|
||||||
|
.cascade_style_and_visited_with_default_parents(inputs)
|
||||||
|
.into_strong()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue