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 dom::window::Window;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::slice; use std::slice;
use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use style::parser::ParserContextExtraData; use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand, Importance}; 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() { *element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
None // Step 2 None // Step 2
} else { } else {
Some(decl_block) Some(Arc::new(decl_block))
}; };
element.sync_property_with_attrs_style(); element.sync_property_with_attrs_style();
let node = element.upcast::<Node>(); let node = element.upcast::<Node>();

View file

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

View file

@ -451,9 +451,9 @@ impl<'le> TElement for ServoLayoutElement<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast()) ServoLayoutNode::from_layout_js(self.element.upcast())
} }
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> { fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
unsafe { 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 as_node(&self) -> Self::ConcreteNode;
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock>; fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>>;
fn get_state(&self) -> ElementState; fn get_state(&self) -> ElementState;

View file

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

View file

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

View file

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

View file

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

View file

@ -356,7 +356,7 @@ pub extern "C" fn Servo_StyleSet_Drop(data: *mut RawServoStyleSet) -> () {
} }
pub struct GeckoDeclarationBlock { pub struct GeckoDeclarationBlock {
pub declarations: Option<PropertyDeclarationBlock>, pub declarations: Option<Arc<PropertyDeclarationBlock>>,
// XXX The following two fields are made atomic to work around the // XXX The following two fields are made atomic to work around the
// ownership system so that they can be changed inside a shared // ownership system so that they can be changed inside a shared
// instance. It wouldn't provide safety as Rust usually promises, // instance. It wouldn't provide safety as Rust usually promises,
@ -377,7 +377,7 @@ pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
-> ServoDeclarationBlockStrong { -> ServoDeclarationBlockStrong {
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) }; let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock { GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock {
declarations: GeckoElement::parse_style_attribute(value), declarations: GeckoElement::parse_style_attribute(value).map(Arc::new),
cache: AtomicPtr::new(cache), cache: AtomicPtr::new(cache),
immutable: AtomicBool::new(false), immutable: AtomicBool::new(false),
})) }))

View file

@ -35,7 +35,6 @@ use snapshot::GeckoElementSnapshot;
use snapshot_helpers; use snapshot_helpers;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::BitOr; use std::ops::BitOr;
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
@ -460,8 +459,6 @@ lazy_static! {
}; };
} }
static NO_STYLE_ATTRIBUTE: Option<PropertyDeclarationBlock> = None;
impl<'le> TElement for GeckoElement<'le> { impl<'le> TElement for GeckoElement<'le> {
type ConcreteNode = GeckoNode<'le>; type ConcreteNode = GeckoNode<'le>;
type ConcreteDocument = GeckoDocument<'le>; type ConcreteDocument = GeckoDocument<'le>;
@ -470,14 +467,16 @@ impl<'le> TElement for GeckoElement<'le> {
unsafe { GeckoNode::from_raw(self.element as *mut RawGeckoNode) } unsafe { GeckoNode::from_raw(self.element as *mut RawGeckoNode) }
} }
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> { fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) }; let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) };
if declarations.is_null() { if declarations.is_null() {
&NO_STYLE_ATTRIBUTE None
} else { } else {
GeckoDeclarationBlock::with(declarations, |declarations| { let opt_ptr = GeckoDeclarationBlock::with(declarations, |declarations| {
unsafe { transmute(&declarations.declarations) } // Use a raw poointer to extend the lifetime
}) declarations.declarations.as_ref().map(|r| r as *const Arc<_>)
});
opt_ptr.map(|ptr| unsafe { &*ptr })
} }
} }

View file

@ -40,10 +40,10 @@ macro_rules! sizeof_checker (
// Update the sizes here // Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 40); sizeof_checker!(size_event_target, EventTarget, 40);
sizeof_checker!(size_node, Node, 152); sizeof_checker!(size_node, Node, 152);
sizeof_checker!(size_element, Element, 328); sizeof_checker!(size_element, Element, 320);
sizeof_checker!(size_htmlelement, HTMLElement, 344); sizeof_checker!(size_htmlelement, HTMLElement, 336);
sizeof_checker!(size_div, HTMLDivElement, 344); sizeof_checker!(size_div, HTMLDivElement, 336);
sizeof_checker!(size_span, HTMLSpanElement, 344); sizeof_checker!(size_span, HTMLSpanElement, 336);
sizeof_checker!(size_text, Text, 184); sizeof_checker!(size_text, Text, 184);
sizeof_checker!(size_characterdata, CharacterData, 184); sizeof_checker!(size_characterdata, CharacterData, 184);
sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16); sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16);

View file

@ -6,7 +6,7 @@ use cssparser::Parser;
use selectors::parser::{LocalName, ParserContext, parse_selector_list}; use selectors::parser::{LocalName, ParserContext, parse_selector_list};
use std::sync::Arc; use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use style::properties::Importance; use style::properties::{Importance, PropertyDeclarationBlock};
use style::selector_matching::{DeclarationBlock, Rule, SelectorMap}; use style::selector_matching::{DeclarationBlock, Rule, SelectorMap};
/// Helper method to get some Rules from selector strings. /// Helper method to get some Rules from selector strings.
@ -19,7 +19,10 @@ fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
Rule { Rule {
selector: s.complex_selector.clone(), selector: s.complex_selector.clone(),
declarations: DeclarationBlock { declarations: DeclarationBlock {
mixed_declarations: Arc::new(Vec::new()), mixed_declarations: Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(Vec::new()),
important_count: 0,
}),
importance: Importance::Normal, importance: Importance::Normal,
specificity: s.specificity, specificity: s.specificity,
source_order: i, source_order: i,

View file

@ -236,15 +236,19 @@ fn test_parse_stylesheet() {
Arc::new(Keyframe { Arc::new(Keyframe {
selector: KeyframeSelector::new_for_unit_testing( selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(0.)]), vec![KeyframePercentage::new(0.)]),
block: Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(vec![ declarations: Arc::new(vec![
(PropertyDeclaration::Width(DeclaredValue::Value( (PropertyDeclaration::Width(DeclaredValue::Value(
LengthOrPercentageOrAuto::Percentage(Percentage(0.)))), LengthOrPercentageOrAuto::Percentage(Percentage(0.)))),
Importance::Normal), Importance::Normal),
]), ]),
important_count: 0,
})
}), }),
Arc::new(Keyframe { Arc::new(Keyframe {
selector: KeyframeSelector::new_for_unit_testing( selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(1.)]), vec![KeyframePercentage::new(1.)]),
block: Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(vec![ declarations: Arc::new(vec![
(PropertyDeclaration::Width(DeclaredValue::Value( (PropertyDeclaration::Width(DeclaredValue::Value(
LengthOrPercentageOrAuto::Percentage(Percentage(1.)))), LengthOrPercentageOrAuto::Percentage(Percentage(1.)))),
@ -254,6 +258,8 @@ fn test_parse_stylesheet() {
vec![animation_play_state::SingleSpecifiedValue::running]))), vec![animation_play_state::SingleSpecifiedValue::running]))),
Importance::Normal), Importance::Normal),
]), ]),
important_count: 0,
}),
}), }),
] ]
})) }))