Backed out 4 changesets (bug 1467536) for permafailing on layout/style/test/test_bug418986-2.html. a=backout
authorGurzau Raul <rgurzau@mozilla.com>
Sat, 09 Jun 2018 10:45:08 +0300
changeset 478687 35bd1a865ff5262e05f2e421d499e8c42a5df2de
parent 478686 ac8a73f9dbb79f890176cdaaf4b044f51de364a2
child 478725 d584b6f0b2d387f0def9204bc233544f8c8d70ba
child 478791 e8157c8580f89ea168abb77f1b74065f9204f770
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1467536, 418986
milestone62.0a1
backs out4e1cee0e0a48d3e85bd3c20342354c95c5039d77
697892c54d637dff936723bae3cbc14b8e893cf5
13b38c2d32511c2bbd76860d2e4c074cf7c43dc3
086eaeb69efa93ef0d690578c146e173e5831f8d
first release with
nightly linux32
35bd1a865ff5 / 62.0a1 / 20180609100028 / files
nightly linux64
35bd1a865ff5 / 62.0a1 / 20180609100028 / files
nightly mac
35bd1a865ff5 / 62.0a1 / 20180609100028 / files
nightly win32
35bd1a865ff5 / 62.0a1 / 20180609100028 / files
nightly win64
35bd1a865ff5 / 62.0a1 / 20180609100028 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1467536) for permafailing on layout/style/test/test_bug418986-2.html. a=backout Backed out changeset 4e1cee0e0a48 (bug 1467536) Backed out changeset 697892c54d63 (bug 1467536) Backed out changeset 13b38c2d3251 (bug 1467536) Backed out changeset 086eaeb69efa (bug 1467536)
layout/style/CSSPropFlags.h
layout/style/ServoBindingList.h
layout/style/ServoCSSPropList.mako.py
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
servo/components/style/properties/data.py
servo/components/style/properties/properties.mako.rs
servo/ports/geckolib/glue.rs
--- a/layout/style/CSSPropFlags.h
+++ b/layout/style/CSSPropFlags.h
@@ -44,18 +44,15 @@ enum class CSSPropFlags : uint8_t
 
   // This property can be animated on the compositor.
   CanAnimateOnCompositor = 1 << 4,
 
   // This property is an internal property that is not represented in
   // the DOM. Properties with this flag are defined in an #ifndef
   // CSS_PROP_LIST_EXCLUDE_INTERNAL section.
   Internal = 1 << 5,
-
-  // Whether this property should be serialized by Servo in getComputedStyle.
-  SerializedByServo = 1 << 6,
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CSSPropFlags)
 
 } // namespace mozilla
 
 #endif // mozilla_CSSPropFlags_h
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -820,31 +820,28 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetCom
                    const mozilla::ServoElementSnapshotTable* snapshots,
                    RawServoAnimationValueBorrowed animation)
 
 // For canvas font.
 SERVO_BINDING_FUNC(Servo_SerializeFontValueForCanvas, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsAString* buffer)
 
-// GetComputedStyle APIs.
+// Get custom property value.
 SERVO_BINDING_FUNC(Servo_GetCustomPropertyValue, bool,
                    ComputedStyleBorrowed computed_values,
                    const nsAString* name, nsAString* value)
 
 SERVO_BINDING_FUNC(Servo_GetCustomPropertiesCount, uint32_t,
                    ComputedStyleBorrowed computed_values)
 
 SERVO_BINDING_FUNC(Servo_GetCustomPropertyNameAt, bool,
                    ComputedStyleBorrowed, uint32_t index,
                    nsAString* name)
 
-SERVO_BINDING_FUNC(Servo_GetPropertyValue, void,
-                   ComputedStyleBorrowed computed_values,
-                   nsCSSPropertyID property, nsAString* value)
 
 SERVO_BINDING_FUNC(Servo_ProcessInvalidations, void,
                    RawServoStyleSetBorrowed set,
                    RawGeckoElementBorrowed element,
                    const mozilla::ServoElementSnapshotTable* snapshots)
 
 
 SERVO_BINDING_FUNC(Servo_HasPendingRestyleAncestor, bool,
--- a/layout/style/ServoCSSPropList.mako.py
+++ b/layout/style/ServoCSSPropList.mako.py
@@ -63,60 +63,30 @@ def is_internal(prop):
 
 def method(prop):
     if prop.name == "float":
         return "CssFloat"
     if prop.name.startswith("-x-"):
         return prop.camel_case[1:]
     return prop.camel_case
 
-# Colors, integers and lengths are easy as well.
-#
-# TODO(emilio): This will go away once the rest of the longhands have been
-# moved or perhaps using a blacklist for the ones with non-layout-dependence
-# but other non-trivial dependence like scrollbar colors.
-SERIALIZED_PREDEFINED_TYPES = [
-    "Color",
-    "Integer",
-    "Length",
-    "Opacity",
-]
-
-def serialized_by_servo(prop):
-    # If the property requires layout information, no such luck.
-    if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags:
-        return False
-    # No shorthands yet.
-    if prop.type() == "shorthand":
-        return False
-    # Keywords are all fine.
-    if prop.keyword:
-        return True
-    if prop.predefined_type in SERIALIZED_PREDEFINED_TYPES:
-        return True
-    # TODO(emilio): Enable the rest of the longhands.
-    return False
-
-
 def flags(prop):
     result = []
     if prop.explicitly_enabled_in_chrome():
         result.append("EnabledInUASheetsAndChrome")
     elif prop.explicitly_enabled_in_ua_sheets():
         result.append("EnabledInUASheets")
     if is_internal(prop):
         result.append("Internal")
     if prop.enabled_in == "":
         result.append("Inaccessible")
     if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags:
         result.append("GetCSNeedsLayoutFlush")
     if "CAN_ANIMATE_ON_COMPOSITOR" in prop.flags:
         result.append("CanAnimateOnCompositor")
-    if serialized_by_servo(prop):
-        result.append("SerializedByServo")
     return ", ".join('"CSSPropFlags::{}"'.format(flag) for flag in result)
 
 def pref(prop):
     if prop.gecko_pref:
         return '"' + prop.gecko_pref + '"'
     return '""'
 
 def sub_properties(prop):
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -430,57 +430,30 @@ nsComputedDOMStyle::GetParentRule()
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
                                      nsAString& aReturn)
 {
   aReturn.Truncate();
 
-  nsCSSPropertyID prop =
-    nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent);
-
-  const ComputedStyleMap::Entry* entry = nullptr;
-  if (prop != eCSSPropertyExtra_variable) {
-    entry = GetComputedStyleMap()->FindEntryForProperty(prop);
-    if (!entry) {
-      return NS_OK;
-    }
-  }
-
-  const bool layoutFlushIsNeeded = entry && entry->IsLayoutFlushNeeded();
-  UpdateCurrentStyleSources(layoutFlushIsNeeded);
-  if (!mComputedStyle) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  auto cleanup = mozilla::MakeScopeExit([&] {
-    ClearCurrentStyleSources();
-  });
-
-  if (!entry) {
-    MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
-    const nsAString& name =
-      Substring(aPropertyName, CSS_CUSTOM_NAME_PREFIX_LENGTH);
-    Servo_GetCustomPropertyValue(mComputedStyle, &name, &aReturn);
-    return NS_OK;
-  }
-
-  if (!nsCSSProps::PropHasFlags(prop, CSSPropFlags::SerializedByServo)) {
-    if (RefPtr<CSSValue> value = (this->*entry->mGetter)()) {
-      ErrorResult rv;
-      nsString text;
-      value->GetCssText(text, rv);
-      aReturn.Assign(text);
-      return rv.StealNSResult();
-    }
-    return NS_OK;
-  }
-
-  Servo_GetPropertyValue(mComputedStyle, prop, &aReturn);
+  ErrorResult error;
+  RefPtr<CSSValue> val =
+    GetPropertyCSSValueWithoutWarning(aPropertyName, error);
+  if (error.Failed()) {
+    return error.StealNSResult();
+  }
+
+  if (val) {
+    nsString text;
+    val->GetCssText(text, error);
+    aReturn.Assign(text);
+    return error.StealNSResult();
+  }
+
   return NS_OK;
 }
 
 /* static */
 already_AddRefed<ComputedStyle>
 nsComputedDOMStyle::GetComputedStyle(Element* aElement,
                                      nsAtom* aPseudo,
                                      StyleType aStyleType)
@@ -1009,16 +982,67 @@ nsComputedDOMStyle::ClearCurrentStyleSou
     ClearComputedStyle();
   }
 
   mOuterFrame = nullptr;
   mInnerFrame = nullptr;
   mPresShell = nullptr;
 }
 
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::GetPropertyCSSValueWithoutWarning(
+  const nsAString& aPropertyName,
+  ErrorResult& aRv)
+{
+  nsCSSPropertyID prop =
+    nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent);
+
+  bool needsLayoutFlush;
+  ComputedStyleMap::Entry::ComputeMethod getter;
+
+  if (prop == eCSSPropertyExtra_variable) {
+    needsLayoutFlush = false;
+    getter = nullptr;
+  } else {
+    const ComputedStyleMap::Entry* propEntry =
+      GetComputedStyleMap()->FindEntryForProperty(prop);
+
+    if (!propEntry) {
+#ifdef DEBUG_ComputedDOMStyle
+      NS_WARNING(PromiseFlatCString(NS_ConvertUTF16toUTF8(aPropertyName) +
+                                    NS_LITERAL_CSTRING(" is not queryable!")).get());
+#endif
+
+      // NOTE:  For branches, we should flush here for compatibility!
+      return nullptr;
+    }
+
+    needsLayoutFlush = propEntry->IsLayoutFlushNeeded();
+    getter = propEntry->mGetter;
+  }
+
+  UpdateCurrentStyleSources(needsLayoutFlush);
+  if (!mComputedStyle) {
+    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+    return nullptr;
+  }
+
+  RefPtr<CSSValue> val;
+  if (prop == eCSSPropertyExtra_variable) {
+    val = DoGetCustomProperty(aPropertyName);
+  } else {
+    // Call our pointer-to-member-function.
+    val = (this->*getter)();
+  }
+
+  ClearCurrentStyleSources();
+
+  return val.forget();
+}
+
 NS_IMETHODIMP
 nsComputedDOMStyle::RemoveProperty(const nsAString& aPropertyName,
                                    nsAString& aReturn)
 {
   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
 }
 
 
@@ -7163,16 +7187,36 @@ nsComputedDOMStyle::DoGetAnimationPlaySt
 }
 
 static void
 MarkComputedStyleMapDirty(const char* aPref, void* aData)
 {
   static_cast<ComputedStyleMap*>(aData)->MarkDirty();
 }
 
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName)
+{
+  MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
+
+  nsString variableValue;
+  const nsAString& name = Substring(aPropertyName,
+                                    CSS_CUSTOM_NAME_PREFIX_LENGTH);
+  bool present =
+    Servo_GetCustomPropertyValue(mComputedStyle, &name, &variableValue);
+  if (!present) {
+    return nullptr;
+  }
+
+  RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+  val->SetString(variableValue);
+
+  return val.forget();
+}
+
 void
 nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent)
 {
   NS_ASSERTION(mContent == aContent, "didn't we register mContent?");
   NS_ASSERTION(mResolvedComputedStyle,
                "should have only registered an observer when "
                "mResolvedComputedStyle is true");
 
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -54,16 +54,20 @@ class nsComputedDOMStyle final : public 
                                , public nsStubMutationObserver
 {
 private:
   // Convenience typedefs:
   typedef nsCSSKTableEntry KTableEntry;
   typedef mozilla::dom::CSSValue CSSValue;
   typedef mozilla::StyleGeometryBox StyleGeometryBox;
 
+  already_AddRefed<CSSValue>
+  GetPropertyCSSValueWithoutWarning(const nsAString& aProp,
+                                    mozilla::ErrorResult& aRv);
+
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsComputedDOMStyle,
                                                                    nsICSSDeclaration)
 
   NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER
   nsresult GetPropertyValue(const nsCSSPropertyID aPropID,
                             nsAString& aValue) override;
@@ -608,16 +612,19 @@ private:
 
   already_AddRefed<CSSValue> DoGetClipPath();
   already_AddRefed<CSSValue> DoGetFilter();
   already_AddRefed<CSSValue> DoGetMaskType();
   already_AddRefed<CSSValue> DoGetPaintOrder();
 
   already_AddRefed<CSSValue> DoGetContextProperties();
 
+  /* Custom properties */
+  already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName);
+
   /* Helper functions */
   void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
   void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
                                 const mozilla::StyleComplexColor& aColor);
   void SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue,
                               const mozilla::StyleComplexColor& aColor,
                               uint8_t aWidgetType);
   void SetValueToStyleImage(const nsStyleImage& aStyleImage,
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -221,20 +221,16 @@ class Longhand(object):
             # discrete). For now, it is still non-animatable.
             self.animatable = False
             self.transitionable = False
             self.animation_value_type = None
 
         # See compute_damage for the various values this can take
         self.servo_restyle_damage = servo_restyle_damage
 
-    @staticmethod
-    def type():
-        return "longhand"
-
     def experimental(self, product):
         if product == "gecko":
             return bool(self.gecko_pref)
         return bool(self.servo_pref)
 
     # FIXME(emilio): Shorthand and Longhand should really share a base class.
     def explicitly_enabled_in_ua_sheets(self):
         return self.enabled_in in ["ua", "chrome"]
@@ -360,20 +356,16 @@ class Shorthand(object):
             if sub.transitionable:
                 transitionable = True
                 break
         return transitionable
 
     animatable = property(get_animatable)
     transitionable = property(get_transitionable)
 
-    @staticmethod
-    def type():
-        return "shorthand"
-
     def experimental(self, product):
         if product == "gecko":
             return bool(self.gecko_pref)
         return bool(self.servo_pref)
 
     # FIXME(emilio): Shorthand and Longhand should really share a base class.
     def explicitly_enabled_in_ua_sheets(self):
         return self.enabled_in in ["ua", "chrome"]
@@ -395,20 +387,16 @@ class Alias(object):
         self.camel_case = to_camel_case(self.ident)
         self.original = original
         self.enabled_in = original.enabled_in
         self.servo_pref = original.servo_pref
         self.gecko_pref = gecko_pref
         self.allowed_in_page_rule = original.allowed_in_page_rule
         self.allowed_in_keyframe_block = original.allowed_in_keyframe_block
 
-    @staticmethod
-    def type():
-        return "alias"
-
     def experimental(self, product):
         if product == "gecko":
             return bool(self.gecko_pref)
         return bool(self.servo_pref)
 
     def explicitly_enabled_in_ua_sheets(self):
         return self.enabled_in in ["ua", "chrome"]
 
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -17,17 +17,18 @@ use custom_properties::CustomPropertiesB
 use servo_arc::{Arc, UniqueArc};
 use smallbitvec::SmallBitVec;
 use std::borrow::Cow;
 use std::{ops, ptr};
 use std::cell::RefCell;
 use std::fmt::{self, Write};
 use std::mem::{self, ManuallyDrop};
 
-use cssparser::{Parser, RGBA, TokenSerializationType};
+#[cfg(feature = "servo")] use cssparser::RGBA;
+use cssparser::{Parser, TokenSerializationType};
 use cssparser::ParserInput;
 #[cfg(feature = "servo")] use euclid::SideOffsets2D;
 use context::QuirksMode;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")] use gecko_bindings::bindings;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID};
 #[cfg(feature = "servo")] use logical_geometry::LogicalMargin;
 #[cfg(feature = "servo")] use computed_values;
@@ -39,16 +40,17 @@ use parser::ParserContext;
 use rule_cache::{RuleCache, RuleCacheConditions};
 use selector_parser::PseudoElement;
 use selectors::parser::SelectorParseErrorKind;
 #[cfg(feature = "servo")] use servo_config::prefs::PREFS;
 use shared_lock::StylesheetGuards;
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 use stylesheets::{CssRuleType, Origin, UrlExtraData};
+#[cfg(feature = "servo")] use values::Either;
 use values::generics::text::LineHeight;
 use values::computed;
 use values::computed::NonNegativeLength;
 use values::serialize_atom_name;
 use rule_tree::{CascadeLevel, StrongRuleNode};
 use self::computed_value_flags::*;
 use str::{CssString, CssStringBorrow, CssStringWriter};
 use style_adjuster::StyleAdjuster;
@@ -827,23 +829,23 @@ bitflags! {
         /// absolutely positioned elements.
         const ABSPOS_CB = 1 << 2;
         /// This longhand property applies to ::first-letter.
         const APPLIES_TO_FIRST_LETTER = 1 << 3;
         /// This longhand property applies to ::first-line.
         const APPLIES_TO_FIRST_LINE = 1 << 4;
         /// This longhand property applies to ::placeholder.
         const APPLIES_TO_PLACEHOLDER = 1 << 5;
-        /// This property's getComputedStyle implementation requires layout
-        /// to be flushed.
-        const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6;
 
         /* The following flags are currently not used in Rust code, they
          * only need to be listed in corresponding properties so that
          * they can be checked in the C++ side via ServoCSSPropList.h. */
+        /// This property's getComputedStyle implementation requires layout
+        /// to be flushed.
+        const GETCS_NEEDS_LAYOUT_FLUSH = 0;
         /// This property can be animated on the compositor.
         const CAN_ANIMATE_ON_COMPOSITOR = 0;
     }
 }
 
 /// An identifier for a given longhand property.
 #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)]
 #[repr(u16)]
@@ -2607,69 +2609,16 @@ impl ComputedValues {
     pub fn visited_rules(&self) -> Option<<&StrongRuleNode> {
         self.visited_style.as_ref().and_then(|s| s.rules.as_ref())
     }
 
     /// Gets a reference to the custom properties map (if one exists).
     pub fn custom_properties(&self) -> Option<<&Arc<::custom_properties::CustomPropertiesMap>> {
         self.custom_properties.as_ref()
     }
-
-    /// Writes the value of the given longhand as a string in `dest`.
-    ///
-    /// Note that the value will usually be the computed value, except for
-    /// colors, where it's resolved.
-    pub fn get_longhand_property_value<W>(
-        &self,
-        property_id: LonghandId,
-        dest: &mut CssWriter<W>
-    ) -> fmt::Result
-    where
-        W: Write,
-    {
-        // TODO(emilio): Is it worth to merge branches here just like
-        // PropertyDeclaration::to_css does?
-        //
-        // We'd need to get a concept of ~resolved value, which may not be worth
-        // it.
-        match property_id {
-            % for prop in data.longhands:
-            LonghandId::${prop.camel_case} => {
-                let style_struct =
-                    self.get_${prop.style_struct.ident.strip("_")}();
-                let value =
-                    style_struct
-                    % if prop.logical:
-                    .clone_${prop.ident}(self.writing_mode);
-                    % else:
-                    .clone_${prop.ident}();
-                    % endif
-
-                % if prop.predefined_type == "Color":
-                let value = self.resolve_color(value);
-                % endif
-
-                value.to_css(dest)
-            }
-            % endfor
-        }
-    }
-
-    /// Resolves the currentColor keyword.
-    ///
-    /// Any color value from computed values (except for the 'color' property
-    /// itself) should go through this method.
-    ///
-    /// Usage example:
-    /// let top_color =
-    ///   style.resolve_color(style.get_border().clone_border_top_color());
-    #[inline]
-    pub fn resolve_color(&self, color: computed::Color) -> RGBA {
-        color.to_rgba(self.get_color().clone_color())
-    }
 }
 
 #[cfg(feature = "servo")]
 impl ComputedValues {
     /// Create a new refcounted `ComputedValues`
     pub fn new(
         _: &Device,
         _: Option<<&ComputedValues>,
@@ -2772,16 +2721,28 @@ impl ComputedValuesInner {
     }
 
     /// Whether the current style is multicolumn.
     #[inline]
     pub fn is_multicol(&self) -> bool {
         self.get_column().is_multicol()
     }
 
+    /// Resolves the currentColor keyword.
+    ///
+    /// Any color value from computed values (except for the 'color' property
+    /// itself) should go through this method.
+    ///
+    /// Usage example:
+    /// let top_color = style.resolve_color(style.Border.border_top_color);
+    #[inline]
+    pub fn resolve_color(&self, color: computed::Color) -> RGBA {
+        color.to_rgba(self.get_color().color)
+    }
+
     /// Get the logical computed inline size.
     #[inline]
     pub fn content_inline_size(&self) -> computed::LengthOrPercentageOrAuto {
         let position_style = self.get_position();
         if self.writing_mode.is_vertical() {
             position_style.height
         } else {
             position_style.width
@@ -2936,29 +2897,29 @@ impl ComputedValuesInner {
 
         // Neither perspective nor transform present
         false
     }
 
     /// Serializes the computed value of this property as a string.
     pub fn computed_value_to_string(&self, property: PropertyDeclarationId) -> String {
         match property {
-            PropertyDeclarationId::Longhand(id) => {
-                let mut s = String::new();
-                self.get_longhand_property_value(
-                    property,
-                    &mut CssWriter::new(&mut s)
-                ).unwrap();
-                s
-            }
+            % for style_struct in data.active_style_structs():
+                % for longhand in style_struct.longhands:
+                    PropertyDeclarationId::Longhand(LonghandId::${longhand.camel_case}) => {
+                        self.${style_struct.ident}.${longhand.ident}.to_css_string()
+                    }
+                % endfor
+            % endfor
             PropertyDeclarationId::Custom(name) => {
                 self.custom_properties
                     .as_ref()
                     .and_then(|map| map.get(name))
-                    .map_or(String::new(), |value| value.to_css_string())
+                    .map(|value| value.to_css_string())
+                    .unwrap_or(String::new())
             }
         }
     }
 }
 
 % if product == "gecko":
     pub use ::servo_arc::RawOffsetArc as BuilderArc;
     /// Clone an arc, returning a regular arc
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -5128,35 +5128,16 @@ pub extern "C" fn Servo_StyleSet_HasDocu
 ) -> bool {
     let state = DocumentState::from_bits_truncate(state);
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
 
     data.stylist.has_document_state_dependency(state)
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Servo_GetPropertyValue(
-    computed_values: ComputedStyleBorrowed,
-    prop: nsCSSPropertyID,
-    value: *mut nsAString,
-) {
-    use style::properties::PropertyFlags;
-
-    let longhand = LonghandId::from_nscsspropertyid(prop).expect("Not a longhand?");
-    debug_assert!(
-        !longhand.flags().contains(PropertyFlags::GETCS_NEEDS_LAYOUT_FLUSH),
-        "We're not supposed to serialize layout-dependent properties"
-    );
-    computed_values.get_longhand_property_value(
-        longhand,
-        &mut CssWriter::new(&mut *value),
-    ).unwrap();
-}
-
-#[no_mangle]
 pub unsafe extern "C" fn Servo_GetCustomPropertyValue(
     computed_values: ComputedStyleBorrowed,
     name: *const nsAString,
     value: *mut nsAString,
 ) -> bool {
     let custom_properties = match computed_values.custom_properties() {
         Some(p) => p,
         None => return false,