Bug 1367904 - Part 6: stylo: Introduce ComputedValuesInner; r?bholley draft
authorManish Goregaokar <manishearth@gmail.com>
Mon, 17 Jul 2017 11:41:44 -0700
changeset 610215 fe2cdd0514bea246cbde7f0720914372c897bffc
parent 610214 e275d55a9b6690bd3b9cabdb2d134d7386bda835
child 610216 2bbfc7ed05df7d38d9f6e1a1f1f30e79e27095b4
push id68805
push userbmo:manishearth@gmail.com
push dateTue, 18 Jul 2017 00:30:54 +0000
reviewersbholley
bugs1367904
milestone56.0a1
Bug 1367904 - Part 6: stylo: Introduce ComputedValuesInner; r?bholley MozReview-Commit-ID: 7BU0Pzhuul3
layout/style/ServoBindings.toml
servo/components/style/gecko/generated/structs_debug.rs
servo/components/style/gecko/generated/structs_release.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/selector_parser.rs
servo/components/style/servo/restyle_damage.rs
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -310,17 +310,17 @@ opaque-types = [
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::ServoUnsafeCell", servo = "::std::cell::UnsafeCell" },
     { generic = true, gecko = "mozilla::ServoCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoFontComputationData", servo = "::properties::FontComputationData" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::stylearc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
-    { generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::stylearc::Arc<ServoComputedValues2>>" },
+    { generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::stylearc::Arc<::properties::ComputedValues>>" },
     { generic = false, gecko = "mozilla::ServoComputedValueFlags", servo = "::properties::computed_value_flags::ComputedValueFlags" },
     { generic = true, gecko = "mozilla::ServoRawOffsetArc", servo = "::stylearc::RawOffsetArc" },
 ]
 fixups = [
     { pat = "root::nsString", rep = "::nsstring::nsStringRepr" },
 ]
 
 [bindings]
--- a/servo/components/style/gecko/generated/structs_debug.rs
+++ b/servo/components/style/gecko/generated/structs_debug.rs
@@ -8,17 +8,17 @@ use atomic_refcell::AtomicRefCell;
 use data::ElementData;
 pub type ServoUnsafeCell<T> = ::std::cell::UnsafeCell<T>;
 pub type ServoCell<T> = ::std::cell::Cell<T>;
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
 pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::stylearc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
-pub type ServoVisitedStyle = Option<::stylearc::Arc<ServoComputedValues2>>;
+pub type ServoVisitedStyle = Option<::stylearc::Arc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::stylearc::RawOffsetArc<T>;
 
 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
 pub mod root {
     #[repr(C)]
     pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
     impl <T> __BindgenUnionField<T> {
--- a/servo/components/style/gecko/generated/structs_release.rs
+++ b/servo/components/style/gecko/generated/structs_release.rs
@@ -8,17 +8,17 @@ use atomic_refcell::AtomicRefCell;
 use data::ElementData;
 pub type ServoUnsafeCell<T> = ::std::cell::UnsafeCell<T>;
 pub type ServoCell<T> = ::std::cell::Cell<T>;
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
 pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::stylearc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
-pub type ServoVisitedStyle = Option<::stylearc::Arc<ServoComputedValues2>>;
+pub type ServoVisitedStyle = Option<::stylearc::Arc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::stylearc::RawOffsetArc<T>;
 
 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
 pub mod root {
     #[repr(C)]
     pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
     impl <T> __BindgenUnionField<T> {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -54,37 +54,41 @@ use gecko::values::round_border_to_devic
 use logical_geometry::WritingMode;
 use media_queries::Device;
 use properties::animated_properties::TransitionProperty;
 use properties::computed_value_flags::ComputedValueFlags;
 use properties::{longhands, FontComputationData, Importance, LonghandId};
 use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
 use rule_tree::StrongRuleNode;
 use std::mem::{forget, transmute, zeroed};
-use std::ptr;
+use std::{cmp, ops, ptr};
 use stylearc::{Arc, RawOffsetArc};
-use std::cmp;
 use values::{Auto, CustomIdent, Either, KeyframesName};
 use values::computed::ToComputedValue;
 use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
 use values::specified::length::Percentage;
 use computed_values::border_style;
 
 pub mod style_structs {
     % for style_struct in data.style_structs:
     pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
     % endfor
 }
 
 
-pub use ::gecko_bindings::structs::mozilla::ServoComputedValues2 as ComputedValues;
-
-impl Clone for ComputedValues {
+pub use ::gecko_bindings::structs::mozilla::ServoComputedValues2 as ComputedValuesInner;
+
+#[derive(Clone, Debug)]
+pub struct ComputedValues {
+    pub inner: ComputedValuesInner
+}
+
+impl Clone for ComputedValuesInner {
     fn clone(&self) -> Self {
-        ComputedValues {
+        ComputedValuesInner {
             % for style_struct in data.style_structs:
                 ${style_struct.gecko_name}: self.${style_struct.gecko_name}.clone(),
             % endfor
             custom_properties: self.custom_properties.clone(),
             writing_mode: self.writing_mode.clone(),
             font_computation_data: self.font_computation_data.clone(),
             flags: self.flags.clone(),
             rules: self.rules.clone(),
@@ -100,42 +104,61 @@ impl ComputedValues {
                flags: ComputedValueFlags,
                rules: Option<StrongRuleNode>,
                visited_style: Option<Arc<ComputedValues>>,
                % for style_struct in data.style_structs:
                ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
                % endfor
     ) -> Self {
         ComputedValues {
-            custom_properties,
-            writing_mode,
-            font_computation_data: FontComputationData::new(font_size_keyword),
-            flags,
-            rules,
-            visited_style: visited_style,
-            % for style_struct in data.style_structs:
-            ${style_struct.gecko_name}: Arc::into_raw_offset(${style_struct.ident}),
-            % endfor
+            inner: ComputedValuesInner {
+                custom_properties: custom_properties,
+                writing_mode: writing_mode,
+                font_computation_data: FontComputationData::new(font_size_keyword),
+                rules: rules,
+                visited_style: visited_style,
+                flags: flags,
+                % for style_struct in data.style_structs:
+                ${style_struct.gecko_name}: Arc::into_raw_offset(${style_struct.ident}),
+                % endfor
+            }
         }
     }
 
     pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
         Arc::new(ComputedValues {
-            custom_properties: None,
-            writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
-            font_computation_data: FontComputationData::default_values(),
-            flags: ComputedValueFlags::empty(),
-            rules: None,
-            visited_style: None,
-            % for style_struct in data.style_structs:
-                ${style_struct.gecko_name}: Arc::into_raw_offset(style_structs::${style_struct.name}::default(pres_context)),
-            % endfor
+            inner: ComputedValuesInner {
+                custom_properties: None,
+                writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
+                font_computation_data: FontComputationData::default_values(),
+                rules: None,
+                visited_style: None,
+                flags: ComputedValueFlags::empty(),
+                % for style_struct in data.style_structs:
+                    ${style_struct.gecko_name}: Arc::into_raw_offset(style_structs::${style_struct.name}::default(pres_context)),
+                % endfor
+            }
         })
     }
-
+}
+
+impl ops::Deref for ComputedValues {
+    type Target = ComputedValuesInner;
+    fn deref(&self) -> &ComputedValuesInner {
+        &self.inner
+    }
+}
+
+impl ops::DerefMut for ComputedValues {
+    fn deref_mut(&mut self) -> &mut ComputedValuesInner {
+        &mut self.inner
+    }
+}
+
+impl ComputedValuesInner {
     #[inline]
     pub fn is_display_contents(&self) -> bool {
         self.get_box().clone_display() == longhands::display::computed_value::T::contents
     }
 
     /// Returns true if the value of the `content` property would make a
     /// pseudo-element not rendered.
     #[inline]
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -7,19 +7,17 @@
 // Please note that valid Rust syntax may be mangled by the Mako parser.
 // For example, Vec<&Foo> will be mangled as Vec&Foo>. To work around these issues, the code
 // can be escaped. In the above example, Vec<<&Foo> or Vec< &Foo> achieves the desired result of Vec<&Foo>.
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 use std::borrow::Cow;
 use std::collections::HashSet;
-use std::fmt;
-use std::mem;
-use std::ops::Deref;
+use std::{fmt, mem, ops};
 use stylearc::{Arc, UniqueArc};
 
 use app_units::Au;
 #[cfg(feature = "servo")] use cssparser::RGBA;
 use cssparser::{Parser, TokenSerializationType, serialize_identifier};
 use cssparser::{ParserInput, CompactCowStr};
 #[cfg(feature = "servo")] use euclid::SideOffsets2D;
 use computed_values;
@@ -108,17 +106,17 @@ pub struct FontComputationData {
     /// and is 1 when there was just a keyword and no relative values.
     ///
     /// When this is Some, we compute font sizes by computing the keyword against
     /// the generic font, and then multiplying it by the ratio.
    pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>
 }
 
 
-impl FontComputationData{
+impl FontComputationData {
         /// Assigns values for variables in struct FontComputationData
     pub fn new(font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>) -> Self {
         FontComputationData {
             font_size_keyword: font_size_keyword
         }
     }
         /// Assigns default values for variables in struct FontComputationData
    pub fn default_values() -> Self {
@@ -1870,29 +1868,21 @@ pub mod style_structs {
         % endif
     % endfor
 % endfor
 
 
 #[cfg(feature = "gecko")]
 pub use gecko_properties::ComputedValues;
 
-/// A legacy alias for a servo-version of ComputedValues. Should go away soon.
-#[cfg(feature = "servo")]
-pub type ServoComputedValues = ComputedValues;
 
-/// The struct that Servo uses to represent computed values.
-///
-/// This struct contains an immutable atomically-reference-counted pointer to
-/// every kind of style struct.
-///
-/// When needed, the structs may be copied in order to get mutated.
 #[cfg(feature = "servo")]
 #[cfg_attr(feature = "servo", derive(Clone, Debug))]
-pub struct ComputedValues {
+/// Actual data of ComputedValues, to match up with Gecko
+pub struct ComputedValuesInner {
     % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
     % endfor
     custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
     /// The writing mode of this computed values struct.
     pub writing_mode: WritingMode,
     /// The keyword behind the current font-size property, if any
     pub font_computation_data: FontComputationData,
@@ -1906,47 +1896,84 @@ pub struct ComputedValues {
     pub rules: Option<StrongRuleNode>,
 
     /// The element's computed values if visited, only computed if there's a
     /// relevant link for this element. A element's "relevant link" is the
     /// element being matched if it is a link or the nearest ancestor link.
     visited_style: Option<Arc<ComputedValues>>,
 }
 
+/// The struct that Servo uses to represent computed values.
+///
+/// This struct contains an immutable atomically-reference-counted pointer to
+/// every kind of style struct.
+///
+/// When needed, the structs may be copied in order to get mutated.
+#[cfg(feature = "servo")]
+#[cfg_attr(feature = "servo", derive(Clone, Debug))]
+pub struct ComputedValues {
+    /// The actual computed values
+    ///
+    /// In Gecko the outer ComputedValues is actually a style context,
+    /// whereas ComputedValuesInner is the core set of computed values.
+    ///
+    /// We maintain this distinction in servo to reduce the amount of special casing.
+    pub inner: ComputedValuesInner,
+}
+
 #[cfg(feature = "servo")]
 impl ComputedValues {
     /// Construct a `ComputedValues` instance.
     pub fn new(
         custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
         writing_mode: WritingMode,
         font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
         flags: ComputedValueFlags,
         rules: Option<StrongRuleNode>,
         visited_style: Option<Arc<ComputedValues>>,
         % for style_struct in data.active_style_structs():
         ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
         % endfor
     ) -> Self {
-        let font_computation_data = FontComputationData::new(font_size_keyword);
         ComputedValues {
-            custom_properties,
-            writing_mode,
-            font_computation_data,
-            flags,
-            rules,
-            visited_style,
-        % for style_struct in data.active_style_structs():
-            ${style_struct.ident},
-        % endfor
+            inner: ComputedValuesInner {
+                custom_properties: custom_properties,
+                writing_mode: writing_mode,
+                font_computation_data: FontComputationData::new(font_size_keyword),
+                rules: rules,
+                visited_style: visited_style,
+                flags: flags,
+            % for style_struct in data.active_style_structs():
+                ${style_struct.ident}: ${style_struct.ident},
+            % endfor
+            }
         }
     }
 
     /// Get the initial computed values.
     pub fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES }
+}
 
+#[cfg(feature = "servo")]
+impl ops::Deref for ComputedValues {
+    type Target = ComputedValuesInner;
+    fn deref(&self) -> &ComputedValuesInner {
+        &self.inner
+    }
+}
+
+#[cfg(feature = "servo")]
+impl ops::DerefMut for ComputedValues {
+    fn deref_mut(&mut self) -> &mut ComputedValuesInner {
+        &mut self.inner
+    }
+}
+
+#[cfg(feature = "servo")]
+impl ComputedValuesInner {
     % for style_struct in data.active_style_structs():
         /// Clone the ${style_struct.name} struct.
         #[inline]
         pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
             self.${style_struct.ident}.clone()
         }
 
         /// Get a immutable reference to the ${style_struct.name} struct.
@@ -2367,17 +2394,17 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
         match self {
             StyleStructRef::Owned(v) => v.shareable(),
             StyleStructRef::Borrowed(v) => clone_arc(v),
             StyleStructRef::Vacated => panic!("Accessed vacated style struct")
         }
     }
 }
 
-impl<'a, T: 'a> Deref for StyleStructRef<'a, T> {
+impl<'a, T: 'a> ops::Deref for StyleStructRef<'a, T> {
     type Target = T;
 
     fn deref(&self) -> &T {
         match *self {
             StyleStructRef::Owned(ref v) => &**v,
             StyleStructRef::Borrowed(v) => &**v,
             StyleStructRef::Vacated => panic!("Accessed vacated style struct")
         }
@@ -2554,38 +2581,40 @@ impl<'a> StyleBuilder<'a> {
 pub use self::lazy_static_module::INITIAL_SERVO_VALUES;
 
 // Use a module to work around #[cfg] on lazy_static! not being applied to every generated item.
 #[cfg(feature = "servo")]
 #[allow(missing_docs)]
 mod lazy_static_module {
     use logical_geometry::WritingMode;
     use stylearc::Arc;
-    use super::{ComputedValues, longhands, style_structs, FontComputationData};
+    use super::{ComputedValues, ComputedValuesInner, longhands, style_structs, FontComputationData};
     use super::computed_value_flags::ComputedValueFlags;
 
     /// The initial values for all style structs as defined by the specification.
     lazy_static! {
         pub static ref INITIAL_SERVO_VALUES: ComputedValues = ComputedValues {
-            % for style_struct in data.active_style_structs():
-                ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
-                    % for longhand in style_struct.longhands:
-                        ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
-                    % endfor
-                    % if style_struct.name == "Font":
-                        hash: 0,
-                    % endif
-                }),
-            % endfor
-            custom_properties: None,
-            writing_mode: WritingMode::empty(),
-            flags: ComputedValueFlags::empty(),
-            font_computation_data: FontComputationData::default_values(),
-            rules: None,
-            visited_style: None,
+            inner: ComputedValuesInner {
+                % for style_struct in data.active_style_structs():
+                    ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
+                        % for longhand in style_struct.longhands:
+                            ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
+                        % endfor
+                        % if style_struct.name == "Font":
+                            hash: 0,
+                        % endif
+                    }),
+                % endfor
+                custom_properties: None,
+                writing_mode: WritingMode::empty(),
+                font_computation_data: FontComputationData::default_values(),
+                rules: None,
+                visited_style: None,
+                flags: ComputedValueFlags::empty(),
+            }
         };
     }
 }
 
 /// A per-longhand function that performs the CSS cascade for that longhand.
 pub type CascadePropertyFn =
     extern "Rust" fn(declaration: &PropertyDeclaration,
                      inherited_style: &ComputedValues,
--- a/servo/components/style/selector_parser.rs
+++ b/servo/components/style/selector_parser.rs
@@ -33,17 +33,17 @@ pub use gecko::snapshot::GeckoElementSna
 pub use servo::restyle_damage::ServoRestyleDamage as RestyleDamage;
 
 #[cfg(feature = "gecko")]
 pub use gecko::restyle_damage::GeckoRestyleDamage as RestyleDamage;
 
 /// A type that represents the previous computed values needed for restyle
 /// damage calculation.
 #[cfg(feature = "servo")]
-pub type PreExistingComputedValues = ::properties::ServoComputedValues;
+pub type PreExistingComputedValues = ::properties::ComputedValues;
 
 /// A type that represents the previous computed values needed for restyle
 /// damage calculation.
 #[cfg(feature = "gecko")]
 pub type PreExistingComputedValues = ::gecko_bindings::structs::nsStyleContext;
 
 /// Servo's selector parser.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/servo/restyle_damage.rs
+++ b/servo/components/style/servo/restyle_damage.rs
@@ -5,17 +5,17 @@
 //! The restyle damage is a hint that tells layout which kind of operations may
 //! be needed in presence of incremental style changes.
 
 #![deny(missing_docs)]
 
 use computed_values::display;
 use heapsize::HeapSizeOf;
 use matching::{StyleChange, StyleDifference};
-use properties::ServoComputedValues;
+use properties::ComputedValues;
 use std::fmt;
 
 bitflags! {
     #[doc = "Individual layout actions that may be necessary after restyling."]
     pub flags ServoRestyleDamage: u8 {
         #[doc = "Repaint the node itself."]
         #[doc = "Currently unused; need to decide how this propagates."]
         const REPAINT = 0x01,
@@ -55,18 +55,18 @@ bitflags! {
 
 impl HeapSizeOf for ServoRestyleDamage {
     fn heap_size_of_children(&self) -> usize { 0 }
 }
 
 impl ServoRestyleDamage {
     /// Compute the `StyleDifference` (including the appropriate restyle damage)
     /// for a given style change between `old` and `new`.
-    pub fn compute_style_difference(old: &ServoComputedValues,
-                                    new: &ServoComputedValues)
+    pub fn compute_style_difference(old: &ComputedValues,
+                                    new: &ComputedValues)
                                     -> StyleDifference {
         let damage = compute_damage(old, new);
         let change = if damage.is_empty() { StyleChange::Unchanged } else { StyleChange::Changed };
         StyleDifference::new(damage, change)
     }
 
     /// Returns a bitmask that represents a flow that needs to be rebuilt and
     /// reflowed.
@@ -177,21 +177,21 @@ macro_rules! add_if_not_equal(
             $damage.insert($($effect)|*);
             true
         } else {
             false
         }
     })
 );
 
-fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> ServoRestyleDamage {
+fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> ServoRestyleDamage {
     let mut damage = ServoRestyleDamage::empty();
 
     // This should check every CSS property, as enumerated in the fields of
-    // http://doc.servo.org/style/properties/struct.ServoComputedValues.html
+    // http://doc.servo.org/style/properties/struct.ComputedValues.html
 
     // FIXME: Test somehow that every property is included.
 
     add_if_not_equal!(old, new, damage,
                       [REPAINT, REPOSITION, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW,
                        REFLOW, RECONSTRUCT_FLOW], [
         get_box.clear, get_box.float, get_box.display, get_box.position, get_counters.content,
         get_counters.counter_reset, get_counters.counter_increment,