diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index a2a77125a97..4d81d457f88 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -218,7 +218,7 @@ impl CSSStyleDeclaration { let mut string = String::new(); - self.owner.with_block(|ref pdb| { + self.owner.with_block(|pdb| { pdb.property_value_to_css(&id, &mut string).unwrap(); }); @@ -281,7 +281,7 @@ impl CSSStyleDeclaration { impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length fn Length(&self) -> u32 { - self.owner.with_block(|ref pdb| { + self.owner.with_block(|pdb| { pdb.declarations.len() as u32 }) } @@ -311,7 +311,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { return DOMString::new() }; - self.owner.with_block(|ref pdb| { + self.owner.with_block(|pdb| { if pdb.property_priority(&id).important() { DOMString::from("important") } else { @@ -406,7 +406,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface fn IndexedGetter(&self, index: u32) -> Option { - self.owner.with_block(|ref pdb| { + self.owner.with_block(|pdb| { pdb.declarations.get(index as usize).map(|entry| { let (ref declaration, importance) = *entry; let mut css = declaration.to_css_string(); @@ -420,7 +420,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext fn CssText(&self) -> DOMString { - self.owner.with_block(|ref pdb| { + self.owner.with_block(|pdb| { DOMString::from(pdb.to_css_string()) }) } diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index fcb05c8dc34..87bebc308d2 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -12,10 +12,10 @@ use parking_lot::RwLock; use parser::{ParserContext, ParserContextExtraData, log_css_error}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId}; use properties::{PropertyDeclarationId, LonghandId, DeclaredValue}; +use properties::LonghandIdSet; use properties::PropertyDeclarationParseResult; use properties::animated_properties::TransitionProperty; use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction; -use properties::property_bit_field::PropertyBitField; use std::fmt; use std::sync::Arc; use style_traits::ToCss; @@ -248,7 +248,7 @@ pub struct KeyframesAnimation { /// Get all the animated properties in a keyframes animation. fn get_animated_properties(keyframes: &[Arc>]) -> Vec { let mut ret = vec![]; - let mut seen = PropertyBitField::new(); + let mut seen = LonghandIdSet::new(); // NB: declarations are already deduplicated, so we don't have to check for // it here. for keyframe in keyframes { diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index bde41fc6d8e..949de6bd38e 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -274,6 +274,39 @@ impl PropertyDeclarationBlock { } } } + + /// Only keep the "winning" declaration for any given property, by importance then source order. + pub fn deduplicate(&mut self) { + let mut deduplicated = Vec::with_capacity(self.declarations.len()); + let mut seen_normal = PropertyDeclarationIdSet::new(); + let mut seen_important = PropertyDeclarationIdSet::new(); + + for (declaration, importance) in self.declarations.drain(..).rev() { + if importance.important() { + let id = declaration.id(); + if seen_important.contains(id) { + self.important_count -= 1; + continue + } + if seen_normal.contains(id) { + let previous_len = deduplicated.len(); + deduplicated.retain(|&(ref d, _)| PropertyDeclaration::id(d) != id); + debug_assert_eq!(deduplicated.len(), previous_len - 1); + } + seen_important.insert(id); + } else { + let id = declaration.id(); + if seen_normal.contains(id) || + seen_important.contains(id) { + continue + } + seen_normal.insert(id) + } + deduplicated.push((declaration, importance)) + } + deduplicated.reverse(); + self.declarations = deduplicated; + } } impl ToCss for PropertyDeclarationBlock { @@ -612,6 +645,6 @@ pub fn parse_property_declaration_list(context: &ParserContext, declarations: iter.parser.declarations, important_count: important_count, }; - super::deduplicate_property_declarations(&mut block); + block.deduplicate(); block } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 901779eba59..bc8f4b60899 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -159,10 +159,6 @@ impl ComputedValues { !self.get_box().gecko.mBinding.mRawPtr.is_null() } - pub fn root_font_size(&self) -> Au { self.root_font_size } - pub fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; } - pub fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; } - // FIXME(bholley): Implement this properly. #[inline] pub fn is_multicol(&self) -> bool { false } @@ -1247,9 +1243,6 @@ fn static_assert() { unsafe { transmute(self.gecko.mFont.weight) } } - // This is used for PartialEq, which we don't implement for gecko style structs. - pub fn compute_font_hash(&mut self) {} - pub fn set_font_synthesis(&mut self, v: longhands::font_synthesis::computed_value::T) { use gecko_bindings::structs::{NS_FONT_SYNTHESIS_WEIGHT, NS_FONT_SYNTHESIS_STYLE}; diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index a55e7e2b153..ca5806fc2de 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -230,7 +230,7 @@ use cascade_info::CascadeInfo; use error_reporting::ParseErrorReporter; use properties::longhands; - use properties::property_bit_field::PropertyBitField; + use properties::LonghandIdSet; use properties::{ComputedValues, PropertyDeclaration}; use properties::style_structs; use std::boxed::Box as StdBox; @@ -245,7 +245,6 @@ inherited_style: &ComputedValues, default_style: &Arc, context: &mut computed::Context, - seen: &mut PropertyBitField, cacheable: &mut bool, cascade_info: &mut Option<<&mut CascadeInfo>, error_reporter: &mut StdBox) { @@ -256,16 +255,7 @@ _ => panic!("entered the wrong cascade_property() implementation"), }; - % if property.logical: - let wm = context.style.writing_mode; - % endif - <% maybe_wm = "wm" if property.logical else "" %> - <% maybe_physical = "_physical" if property.logical else "" %> % if not property.derived_from: - if seen.get${maybe_physical}_${property.ident}(${maybe_wm}) { - return - } - seen.set${maybe_physical}_${property.ident}(${maybe_wm}); { let custom_props = context.style().custom_properties(); ::properties::substitute_variables_${property.ident}( @@ -275,6 +265,9 @@ cascade_info.on_cascade_property(&declaration, &value); } + % if property.logical: + let wm = context.style.writing_mode; + % endif <% maybe_wm = ", wm" if property.logical else "" %> match *value { DeclaredValue::Value(ref specified_value) => { @@ -321,7 +314,6 @@ cascade_property_custom(declaration, inherited_style, context, - seen, cacheable, error_reporter); % endif diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 25b2bf5616a..696d9038353 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -84,7 +84,6 @@ fn cascade_property_custom(_declaration: &PropertyDeclaration, _inherited_style: &ComputedValues, context: &mut computed::Context, - _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut StdBox) { longhands::_servo_display_for_hypothetical_box::derive_from_display(context); diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 1add7ea5680..4b05c50b970 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -6,8 +6,7 @@ <% from data import Method %> <% data.new_style_struct("Font", - inherited=True, - additional_methods=[Method("compute_font_hash", is_mut=True)]) %> + inherited=True) %> <%helpers:longhand name="font-family" animatable="False" need_index="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-family"> use self::computed_value::{FontFamily, FamilyName}; diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index 30342595b4b..9b2a851bc6f 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -204,7 +204,6 @@ ${helpers.single_keyword("unicode-bidi", fn cascade_property_custom(_declaration: &PropertyDeclaration, _inherited_style: &ComputedValues, context: &mut computed::Context, - _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut StdBox) { longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context); diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index bb5be1bbd25..60e1059e99a 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -29,6 +29,7 @@ use font_metrics::FontMetricsProvider; #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide}; use logical_geometry::WritingMode; use parser::{Parse, ParserContext, ParserContextExtraData}; +use properties::animated_properties::TransitionProperty; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; use servo_url::ServoUrl; use style_traits::ToCss; @@ -39,7 +40,6 @@ use cascade_info::CascadeInfo; use rule_tree::StrongRuleNode; #[cfg(feature = "servo")] use values::specified::BorderStyle; -use self::property_bit_field::PropertyBitField; pub use self::declaration_block::*; #[cfg(feature = "gecko")] @@ -178,92 +178,92 @@ pub mod animated_properties { <%include file="/helpers/animated_properties.mako.rs" /> } +/// A set of longhand properties +pub struct LonghandIdSet { + storage: [u32; (${len(data.longhands)} - 1 + 32) / 32] +} -// TODO(SimonSapin): Convert this to a syntax extension rather than a Mako template. -// Maybe submit for inclusion in libstd? -#[allow(missing_docs)] -pub mod property_bit_field { - use logical_geometry::WritingMode; - use properties::animated_properties::TransitionProperty; - - /// A bitfield for all longhand properties, in order to quickly test whether - /// we've seen one of them. - pub struct PropertyBitField { - storage: [u32; (${len(data.longhands)} - 1 + 32) / 32] +impl LonghandIdSet { + /// Create an empty set + #[inline] + pub fn new() -> LonghandIdSet { + LonghandIdSet { storage: [0; (${len(data.longhands)} - 1 + 32) / 32] } } - impl PropertyBitField { - /// Create a new `PropertyBitField`, with all the bits set to zero. - #[inline] - pub fn new() -> PropertyBitField { - PropertyBitField { storage: [0; (${len(data.longhands)} - 1 + 32) / 32] } - } + /// Return whether the given property is in the set + #[inline] + pub fn contains(&self, id: LonghandId) -> bool { + let bit = id as usize; + (self.storage[bit / 32] & (1 << (bit % 32))) != 0 + } - #[inline] - fn get(&self, bit: usize) -> bool { - (self.storage[bit / 32] & (1 << (bit % 32))) != 0 - } + /// Add the given property to the set + #[inline] + pub fn insert(&mut self, id: LonghandId) { + let bit = id as usize; + self.storage[bit / 32] |= 1 << (bit % 32); + } - #[inline] - fn set(&mut self, bit: usize) { - self.storage[bit / 32] |= 1 << (bit % 32) + /// Set the corresponding bit of TransitionProperty. + /// This function will panic if TransitionProperty::All is given. + pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) { + match *property { + % for prop in data.longhands: + % if prop.animatable: + TransitionProperty::${prop.camel_case} => self.insert(LonghandId::${prop.camel_case}), + % endif + % endfor + TransitionProperty::All => unreachable!("Tried to set TransitionProperty::All in a PropertyBitfield"), } - % for i, property in enumerate(data.longhands): - % if not property.derived_from: - #[allow(non_snake_case, missing_docs)] - #[inline] - pub fn get_${property.ident}(&self) -> bool { - self.get(${i}) - } - #[allow(non_snake_case, missing_docs)] - #[inline] - pub fn set_${property.ident}(&mut self) { - self.set(${i}) - } - % endif - % if property.logical: - #[allow(non_snake_case, missing_docs)] - pub fn get_physical_${property.ident}(&self, wm: WritingMode) -> bool { - <%helpers:logical_setter_helper name="${property.name}"> - <%def name="inner(physical_ident)"> - self.get_${physical_ident}() - - - } - #[allow(non_snake_case, missing_docs)] - pub fn set_physical_${property.ident}(&mut self, wm: WritingMode) { - <%helpers:logical_setter_helper name="${property.name}"> - <%def name="inner(physical_ident)"> - self.set_${physical_ident}() - - - } - % endif - % endfor + } - /// Set the corresponding bit of TransitionProperty. - /// This function will panic if TransitionProperty::All is given. - pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) { - match *property { - % for i, prop in enumerate(data.longhands): - % if prop.animatable: - TransitionProperty::${prop.camel_case} => self.set(${i}), - % endif - % endfor - TransitionProperty::All => unreachable!("Tried to set TransitionProperty::All in a PropertyBitfield"), - } + /// Return true if the corresponding bit of TransitionProperty is set. + /// This function will panic if TransitionProperty::All is given. + pub fn has_transition_property_bit(&self, property: &TransitionProperty) -> bool { + match *property { + % for prop in data.longhands: + % if prop.animatable: + TransitionProperty::${prop.camel_case} => self.contains(LonghandId::${prop.camel_case}), + % endif + % endfor + TransitionProperty::All => unreachable!("Tried to get TransitionProperty::All in a PropertyBitfield"), } + } +} - /// Return true if the corresponding bit of TransitionProperty is set. - /// This function will panic if TransitionProperty::All is given. - pub fn has_transition_property_bit(&self, property: &TransitionProperty) -> bool { - match *property { - % for i, prop in enumerate(data.longhands): - % if prop.animatable: - TransitionProperty::${prop.camel_case} => self.get(${i}), - % endif - % endfor - TransitionProperty::All => unreachable!("Tried to get TransitionProperty::All in a PropertyBitfield"), +/// A specialized set of PropertyDeclarationId +pub struct PropertyDeclarationIdSet { + longhands: LonghandIdSet, + + // FIXME: Use a HashSet instead? This Vec is usually small, so linear scan might be ok. + custom: Vec<::custom_properties::Name>, +} + +impl PropertyDeclarationIdSet { + /// Empty set + pub fn new() -> Self { + PropertyDeclarationIdSet { + longhands: LonghandIdSet::new(), + custom: Vec::new(), + } + } + + /// Returns whether the given ID is in the set + pub fn contains(&mut self, id: PropertyDeclarationId) -> bool { + match id { + PropertyDeclarationId::Longhand(id) => self.longhands.contains(id), + PropertyDeclarationId::Custom(name) => self.custom.contains(name), + } + } + + /// Insert the given ID in the set + pub fn insert(&mut self, id: PropertyDeclarationId) { + match id { + PropertyDeclarationId::Longhand(id) => self.longhands.insert(id), + PropertyDeclarationId::Custom(name) => { + if !self.custom.contains(name) { + self.custom.push(name.clone()) + } } } } @@ -367,79 +367,6 @@ pub mod property_bit_field { % endif % endfor -/// Given a property declaration block, only keep the "winning" declaration for -/// any given property, by importance then source order. -/// -/// The input and output are in source order -fn deduplicate_property_declarations(block: &mut PropertyDeclarationBlock) { - let mut deduplicated = Vec::with_capacity(block.declarations.len()); - let mut seen_normal = PropertyBitField::new(); - let mut seen_important = PropertyBitField::new(); - let mut seen_custom_normal = Vec::new(); - let mut seen_custom_important = Vec::new(); - - for (declaration, importance) in block.declarations.drain(..).rev() { - match declaration { - % for property in data.longhands: - PropertyDeclaration::${property.camel_case}(..) => { - % if not property.derived_from: - if importance.important() { - if seen_important.get_${property.ident}() { - block.important_count -= 1; - continue - } - if seen_normal.get_${property.ident}() { - remove_one(&mut deduplicated, |d| { - matches!(d, &(PropertyDeclaration::${property.camel_case}(..), _)) - }); - } - seen_important.set_${property.ident}() - } else { - if seen_normal.get_${property.ident}() || - seen_important.get_${property.ident}() { - continue - } - seen_normal.set_${property.ident}() - } - % else: - unreachable!(); - % endif - }, - % endfor - PropertyDeclaration::Custom(ref name, _) => { - if importance.important() { - if seen_custom_important.contains(name) { - block.important_count -= 1; - continue - } - if seen_custom_normal.contains(name) { - remove_one(&mut deduplicated, |d| { - matches!(d, &(PropertyDeclaration::Custom(ref n, _), _) if n == name) - }); - } - seen_custom_important.push(name.clone()) - } else { - if seen_custom_normal.contains(name) || - seen_custom_important.contains(name) { - continue - } - seen_custom_normal.push(name.clone()) - } - } - } - deduplicated.push((declaration, importance)) - } - deduplicated.reverse(); - block.declarations = deduplicated; -} - -#[inline] -fn remove_one bool>(v: &mut Vec, mut remove_this: F) { - let previous_len = v.len(); - v.retain(|x| !remove_this(x)); - debug_assert_eq!(v.len(), previous_len - 1); -} - /// An enum to represent a CSS Wide keyword. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum CSSWideKeyword { @@ -483,6 +410,25 @@ impl LonghandId { % endfor } } + + /// If this is a logical property, return the corresponding physical one in the given writing mode. + /// Otherwise, return unchanged. + pub fn to_physical(&self, wm: WritingMode) -> Self { + match *self { + % for property in data.longhands: + % if property.logical: + LonghandId::${property.camel_case} => { + <%helpers:logical_setter_helper name="${property.name}"> + <%def name="inner(physical_ident)"> + LonghandId::${to_camel_case(physical_ident)} + + + } + % endif + % endfor + _ => *self + } + } } /// An identifier for a given shorthand property. @@ -653,7 +599,7 @@ impl ToCss for DeclaredValue { /// An identifier for a given property declaration, which can be either a /// longhand or a custom property. -#[derive(PartialEq, Clone)] +#[derive(PartialEq, Clone, Copy)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum PropertyDeclarationId<'a> { /// A longhand. @@ -1438,14 +1384,6 @@ impl ComputedValues { /// Since this isn't supported in Servo, this is always false for Servo. pub fn is_display_contents(&self) -> bool { false } - /// Get the root font size. - fn root_font_size(&self) -> Au { self.root_font_size } - - /// Set the root font size. - fn set_root_font_size(&mut self, size: Au) { self.root_font_size = size } - /// Set the writing mode for this style. - pub fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; } - /// Whether the current style is multicolumn. #[inline] pub fn is_multicol(&self) -> bool { @@ -1730,7 +1668,6 @@ pub type CascadePropertyFn = inherited_style: &ComputedValues, default_style: &Arc, context: &mut computed::Context, - seen: &mut PropertyBitField, cacheable: &mut bool, cascade_info: &mut Option<<&mut CascadeInfo>, error_reporter: &mut StdBox); @@ -1855,7 +1792,7 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D, ComputedValues::new(custom_properties, flags.contains(SHAREABLE), WritingMode::empty(), - inherited_style.root_font_size(), + inherited_style.root_font_size, % for style_struct in data.active_style_structs(): % if style_struct.inherited: inherited_style.clone_${style_struct.name_lower}(), @@ -1868,7 +1805,7 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D, ComputedValues::new(custom_properties, flags.contains(SHAREABLE), WritingMode::empty(), - inherited_style.root_font_size(), + inherited_style.root_font_size, % for style_struct in data.active_style_structs(): inherited_style.clone_${style_struct.name_lower}(), % endfor @@ -1890,7 +1827,7 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D, // NB: The cacheable boolean is not used right now, but will be once we // start caching computed values in the rule nodes. let mut cacheable = true; - let mut seen = PropertyBitField::new(); + let mut seen = LonghandIdSet::new(); // Declaration blocks are stored in increasing precedence order, we want // them in decreasing order here. @@ -1940,19 +1877,25 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D, continue } + <% maybe_to_physical = ".to_physical(writing_mode)" if category_to_cascade_now != "early" else "" %> + let physical_longhand_id = longhand_id ${maybe_to_physical}; + if seen.contains(physical_longhand_id) { + continue + } + seen.insert(physical_longhand_id); + let discriminant = longhand_id as usize; (CASCADE_PROPERTY[discriminant])(declaration, inherited_style, default_style, &mut context, - &mut seen, &mut cacheable, &mut cascade_info, &mut error_reporter); } % if category_to_cascade_now == "early": - let mode = get_writing_mode(context.style.get_inheritedbox()); - context.style.set_writing_mode(mode); + let writing_mode = get_writing_mode(context.style.get_inheritedbox()); + context.style.writing_mode = writing_mode; % endif % endfor @@ -2090,13 +2033,17 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D, if is_root_element { let s = style.get_font().clone_font_size(); - style.set_root_font_size(s); + style.root_font_size = s; } - if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || - seen.get_font_family() { - style.mutate_font().compute_font_hash(); - } + % if product == "servo": + if seen.contains(LonghandId::FontStyle) || + seen.contains(LonghandId::FontWeight) || + seen.contains(LonghandId::FontStretch) || + seen.contains(LonghandId::FontFamily) { + style.mutate_font().compute_font_hash(); + } + % endif style } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 4cfba96bd4a..ec5afbae022 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -1338,8 +1338,8 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis pres_context: RawGeckoPresContextBorrowed, computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut) { + use style::properties::LonghandIdSet; use style::properties::declaration_block::Importance; - use style::properties::property_bit_field::PropertyBitField; use style::values::computed::Context; let style = ComputedValues::as_arc(&style); @@ -1359,7 +1359,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis for (index, keyframe) in keyframes.iter().enumerate() { let ref mut animation_values = computed_keyframes[index]; - let mut seen = PropertyBitField::new(); + let mut seen = LonghandIdSet::new(); // mServoDeclarationBlock is null in the case where we have an invalid css property. let iter = keyframe.mPropertyValues.iter() @@ -1429,7 +1429,7 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet style: ServoComputedValuesBorrowed, keyframes: RawGeckoKeyframeListBorrowedMut) -> bool { use style::gecko_bindings::structs::Keyframe; - use style::properties::property_bit_field::PropertyBitField; + use style::properties::LonghandIdSet; let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut(); let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) }; @@ -1482,7 +1482,7 @@ pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSet declaration.is_animatable() }); - let mut seen = PropertyBitField::new(); + let mut seen = LonghandIdSet::new(); for (index, &(ref declaration, _)) in animatable.enumerate() { unsafe {