Use Arc<PropertyDeclarationBlock> everwhere it’s appropriate.

This commit is contained in:
Simon Sapin 2016-08-31 01:06:45 +02:00
parent c50e6add4a
commit acc38aa8c2
13 changed files with 85 additions and 68 deletions

View file

@ -15,6 +15,7 @@ use dom::node::{Node, NodeDamage, window_from_node};
use dom::window::Window;
use std::ascii::AsciiExt;
use std::slice;
use std::sync::Arc;
use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand, Importance};
@ -367,7 +368,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
*element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
None // Step 2
} else {
Some(decl_block)
Some(Arc::new(decl_block))
};
element.sync_property_with_attrs_style();
let node = element.upcast::<Node>();

View file

@ -109,7 +109,7 @@ pub struct Element {
prefix: Option<DOMString>,
attrs: DOMRefCell<Vec<JS<Attr>>>,
id_attribute: DOMRefCell<Option<Atom>>,
style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
style_attribute: DOMRefCell<Option<Arc<PropertyDeclarationBlock>>>,
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
class_list: MutNullableHeap<JS<DOMTokenList>>,
state: Cell<ElementState>,
@ -297,7 +297,7 @@ pub trait LayoutElementHelpers {
#[allow(unsafe_code)]
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
fn id_attribute(&self) -> *const Option<Atom>;
fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock>;
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>;
fn local_name(&self) -> &Atom;
fn namespace(&self) -> &Namespace;
fn get_checked_state_for_layout(&self) -> bool;
@ -329,7 +329,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
#[inline]
fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock {
DeclarationBlock::from_declarations(
Arc::new(vec![(rule, Importance::Normal)]),
Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(vec![(rule, Importance::Normal)]),
important_count: 0,
}),
Importance::Normal)
}
@ -615,7 +618,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
#[allow(unsafe_code)]
fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock> {
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>> {
unsafe {
(*self.unsafe_get()).style_attribute.borrow_for_layout()
}
@ -704,7 +707,7 @@ impl Element {
self.attrs.borrow()
}
pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> {
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<PropertyDeclarationBlock>>> {
&self.style_attribute
}
@ -774,6 +777,7 @@ impl Element {
matching
});
if let Some(index) = index {
let declarations = Arc::make_mut(declarations);
Arc::make_mut(&mut declarations.declarations).remove(index);
if importance.unwrap().important() {
declarations.important_count -= 1;
@ -796,6 +800,7 @@ impl Element {
{
// Usually, the reference count will be 1 here. But transitions could make it greater
// than that.
let declaration_block = Arc::make_mut(declaration_block);
let existing_declarations = Arc::make_mut(&mut declaration_block.declarations);
'outer: for incoming_declaration in declarations {
@ -829,10 +834,10 @@ impl Element {
0
};
*inline_declarations = Some(PropertyDeclarationBlock {
*inline_declarations = Some(Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(declarations.into_iter().map(|d| (d, importance)).collect()),
important_count: important_count,
});
}));
}
update(self, declarations, importance);
@ -847,6 +852,7 @@ impl Element {
if let &mut Some(ref mut block) = &mut *inline_declarations {
// Usually, the reference counts of `from` and `to` will be 1 here. But transitions
// could make them greater than that.
let block = Arc::make_mut(block);
let declarations = Arc::make_mut(&mut block.declarations);
for &mut (ref declaration, ref mut importance) in declarations {
if properties.iter().any(|p| declaration.name() == **p) {
@ -2102,8 +2108,11 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| {
let win = window_from_node(self);
parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(),
ParserContextExtraData::default())
Arc::new(parse_style_attribute(
&value,
&doc.base_url(),
win.css_error_reporter(),
ParserContextExtraData::default()))
});
if node.is_in_doc() {
node.dirty(NodeDamage::NodeStyleDamaged);

View file

@ -451,9 +451,9 @@ impl<'le> TElement for ServoLayoutElement<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
}
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> {
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
unsafe {
&*self.element.style_attribute()
(*self.element.style_attribute()).as_ref()
}
}

View file

@ -192,7 +192,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
fn as_node(&self) -> Self::ConcreteNode;
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock>;
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>>;
fn get_state(&self) -> ElementState;

View file

@ -7,7 +7,7 @@ use cssparser::{DeclarationListParser, DeclarationParser};
use parser::{ParserContext, log_css_error};
use properties::PropertyDeclarationParseResult;
use properties::animated_properties::TransitionProperty;
use properties::{PropertyDeclaration, Importance};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, Importance};
use std::sync::Arc;
/// A number from 1 to 100, indicating the percentage of the animation where
@ -77,7 +77,7 @@ pub struct Keyframe {
/// so the second value of these tuples is always `Importance::Normal`.
/// But including them enables `compute_style_for_animation_step` to create a `DeclarationBlock`
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
pub declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub block: Arc<PropertyDeclarationBlock>,
}
/// A keyframes step value. This can be a synthetised keyframes animation, that
@ -88,7 +88,7 @@ pub struct Keyframe {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum KeyframesStepValue {
/// See `Keyframe::declarations`s docs about the presence of `Importance`.
Declarations(Arc<Vec<(PropertyDeclaration, Importance)>>),
Declarations(Arc<PropertyDeclarationBlock>),
ComputedValues,
}
@ -113,8 +113,8 @@ impl KeyframesStep {
fn new(percentage: KeyframePercentage,
value: KeyframesStepValue) -> Self {
let declared_timing_function = match value {
KeyframesStepValue::Declarations(ref declarations) => {
declarations.iter().any(|&(ref prop_decl, _)| {
KeyframesStepValue::Declarations(ref block) => {
block.declarations.iter().any(|&(ref prop_decl, _)| {
match *prop_decl {
PropertyDeclaration::AnimationTimingFunction(..) => true,
_ => false,
@ -154,7 +154,7 @@ fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
let mut ret = vec![];
// NB: declarations are already deduplicated, so we don't have to check for
// it here.
for &(ref declaration, _) in keyframe.declarations.iter() {
for &(ref declaration, _) in keyframe.block.declarations.iter() {
if let Some(property) = TransitionProperty::from_declaration(declaration) {
ret.push(property);
}
@ -179,7 +179,7 @@ impl KeyframesAnimation {
for keyframe in keyframes {
for percentage in keyframe.selector.0.iter() {
steps.push(KeyframesStep::new(*percentage,
KeyframesStepValue::Declarations(keyframe.declarations.clone())));
KeyframesStepValue::Declarations(keyframe.block.clone())));
}
}
@ -265,7 +265,10 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
}
Ok(Arc::new(Keyframe {
selector: prelude,
declarations: Arc::new(declarations),
block: Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(declarations),
important_count: 0,
}),
}))
}
}

View file

@ -14,7 +14,7 @@ use context::{StyleContext, SharedStyleContext};
use data::PrivateStyleData;
use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
use properties::longhands::display::computed_value as display;
use properties::{ComputedValues, cascade};
use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
use selector_impl::{TheSelectorImpl, PseudoElement};
use selector_matching::{DeclarationBlock, Stylist};
use selectors::bloom::BloomFilter;
@ -139,7 +139,7 @@ impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> {
for declaration in self.declarations {
// Each declaration contians an Arc, which is a stable
// pointer; we use that for hashing and equality.
let ptr: *const Vec<_> = &*declaration.mixed_declarations;
let ptr: *const PropertyDeclarationBlock = &*declaration.mixed_declarations;
ptr.hash(state);
declaration.importance.hash(state);
}
@ -651,7 +651,7 @@ pub trait ElementMatchMethods : TElement {
applicable_declarations: &mut ApplicableDeclarations)
-> StyleRelations {
use traversal::relations_are_shareable;
let style_attribute = self.style_attribute().as_ref();
let style_attribute = self.style_attribute();
let mut relations =
stylist.push_applicable_declarations(self,

View file

@ -282,7 +282,7 @@ impl Importance {
/// Overridden declarations are skipped.
// FIXME (https://github.com/servo/servo/issues/3426)
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PropertyDeclarationBlock {
#[cfg_attr(feature = "servo", ignore_heap_size_of = "#7038")]

View file

@ -181,7 +181,7 @@ impl Stylist {
selector: selector.complex_selector.clone(),
declarations: DeclarationBlock {
specificity: selector.specificity,
mixed_declarations: $style_rule.declarations.declarations.clone(),
mixed_declarations: $style_rule.declarations.clone(),
importance: $importance,
source_order: rules_source_order,
},
@ -346,7 +346,7 @@ impl Stylist {
&self,
element: &E,
parent_bf: Option<&BloomFilter>,
style_attribute: Option<&PropertyDeclarationBlock>,
style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
pseudo_element: Option<&PseudoElement>,
applicable_declarations: &mut V) -> StyleRelations
where E: Element<Impl=TheSelectorImpl> +
@ -398,14 +398,12 @@ impl Stylist {
debug!("author normal: {:?}", relations);
// Step 4: Normal style attributes.
if let Some(ref sa) = style_attribute {
if let Some(sa) = style_attribute {
if sa.declarations.len() as u32 - sa.important_count > 0 {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
DeclarationBlock::from_declarations(
sa.declarations.clone(),
Importance::Normal));
DeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
}
}
@ -420,14 +418,12 @@ impl Stylist {
debug!("author important: {:?}", relations);
// Step 6: `!important` style attributes.
if let Some(ref sa) = style_attribute {
if let Some(sa) = style_attribute {
if sa.important_count > 0 {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
DeclarationBlock::from_declarations(
sa.declarations.clone(),
Importance::Important));
DeclarationBlock::from_declarations(sa.clone(), Importance::Important));
}
}
@ -845,7 +841,7 @@ pub struct Rule {
pub struct DeclarationBlock {
/// Contains declarations of either importance, but only those of self.importance are relevant.
/// Use DeclarationBlock::iter
pub mixed_declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub mixed_declarations: Arc<PropertyDeclarationBlock>,
pub importance: Importance,
pub source_order: usize,
pub specificity: u32,
@ -853,7 +849,7 @@ pub struct DeclarationBlock {
impl DeclarationBlock {
#[inline]
pub fn from_declarations(declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
importance: Importance)
-> Self {
DeclarationBlock {
@ -866,7 +862,7 @@ impl DeclarationBlock {
pub fn iter(&self) -> DeclarationBlockIter {
DeclarationBlockIter {
iter: self.mixed_declarations.iter(),
iter: self.mixed_declarations.declarations.iter(),
importance: self.importance,
}
}