Bug 1382017 - stylo: Remove usage of ServoComputedValues from binding functions; r?xidorn draft
authorManish Goregaokar <manishearth@gmail.com>
Tue, 18 Jul 2017 23:17:34 -0700 (2017-07-19)
changeset 612899 de74e3ac81a4f11f1ea32e2b8001a3a96fb6bdcd
parent 612898 a2841b616ca915bad01d347256f4f1fa737fe3c1
child 612900 301ffd5aaec8da845cc684bc3707329e62fb43a2
child 612920 345899482d5c4e167c175804e9c38ef76891c629
push id69633
push userbmo:manishearth@gmail.com
push dateFri, 21 Jul 2017 06:11:28 +0000 (2017-07-21)
reviewersxidorn
bugs1382017
milestone56.0a1
Bug 1382017 - stylo: Remove usage of ServoComputedValues from binding functions; r?xidorn MozReview-Commit-ID: 3KygTIIMVvF
layout/base/nsCSSFrameConstructor.cpp
layout/inspector/inDOMUtils.cpp
layout/style/ServoBindingList.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.toml
layout/style/ServoStyleContext.cpp
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/nsComputedDOMStyle.cpp
servo/components/servo_arc/lib.rs
servo/components/style/gecko/arc_types.rs
servo/components/style/gecko/generated/bindings.rs
servo/components/style/gecko/generated/structs_debug.rs
servo/components/style/gecko/generated/structs_release.rs
servo/components/style/properties/gecko.mako.rs
servo/ports/geckolib/glue.rs
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1924,17 +1924,17 @@ nsCSSFrameConstructor::CreateGeneratedCo
   // just stick the style on the element and avoid an additional traversal.
   //
   // We don't do this for pseudos that may trigger animations or transitions,
   // since those need to be kicked off by the traversal machinery.
   bool hasServoAnimations = false;
   ServoStyleContext* servoStyle = pseudoStyleContext->GetAsServo();
   if (servoStyle) {
     hasServoAnimations =
-      Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle->ComputedValues());
+      Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle);
     if (!hasServoAnimations) {
       Servo_SetExplicitStyle(container, servoStyle);
     }
   }
 
   // stylo: ServoRestyleManager does not handle transitions yet, and when it
   // does it probably won't need to track reframed style contexts to start
   // transitions correctly.
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -267,18 +267,17 @@ inDOMUtils::GetCSSStyleRules(nsIDOMEleme
     nsIDocument* doc = element->GetOwnerDocument();
     nsIPresShell* shell = doc->GetShell();
     if (!shell) {
       return NS_OK;
     }
 
     ServoStyleContext* servo = styleContext->AsServo();
     nsTArray<const RawServoStyleRule*> rawRuleList;
-    Servo_ComputedValues_GetStyleRuleList(servo->ComputedValues(),
-                                          &rawRuleList);
+    Servo_ComputedValues_GetStyleRuleList(servo, &rawRuleList);
 
     ServoStyleSet* styleSet = shell->StyleSet()->AsServo();
     ServoStyleRuleMap* map = styleSet->StyleRuleMap();
     map->EnsureTable();
 
     // Find matching rules in the table.
     for (const RawServoStyleRule* rawRule : Reversed(rawRuleList)) {
       if (ServoStyleRule* rule = map->Lookup(rawRule)) {
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -230,17 +230,17 @@ SERVO_BINDING_FUNC(Servo_GetComputedKeyf
                    ServoStyleContextBorrowed style,
                    RawServoStyleSetBorrowed set,
                    RawGeckoComputedKeyframeValuesListBorrowedMut result)
 SERVO_BINDING_FUNC(Servo_ComputedValues_ExtractAnimationValue,
                    RawServoAnimationValueStrong,
                    ServoStyleContextBorrowed computed_values,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_ComputedValues_SpecifiesAnimationsOrTransitions, bool,
-                   ServoComputedValuesBorrowed computed_values)
+                   ServoStyleContextBorrowed computed_values)
 SERVO_BINDING_FUNC(Servo_Property_IsAnimatable, bool,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_Property_IsTransitionable, bool,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_Property_IsDiscreteAnimatable, bool,
                    nsCSSPropertyID property)
 SERVO_BINDING_FUNC(Servo_GetProperties_Overriding_Animation, void,
                    RawGeckoElementBorrowed,
@@ -467,25 +467,25 @@ SERVO_BINDING_FUNC(Servo_ComputedValues_
                    nsIAtom* pseudo_tag,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoStyleContextStrong,
                    RawServoStyleSetBorrowed set,
                    nsIAtom* pseudo_tag,
                    ServoStyleContextBorrowedOrNull parent_style,
                    mozilla::InheritTarget target)
 SERVO_BINDING_FUNC(Servo_ComputedValues_GetStyleBits, uint64_t,
-                   ServoComputedValuesBorrowed values)
+                   ServoStyleContextBorrowed values)
 SERVO_BINDING_FUNC(Servo_ComputedValues_EqualCustomProperties, bool,
                    ServoComputedValuesBorrowed first,
                    ServoComputedValuesBorrowed second)
 // Gets the source style rules for the computed values. This returns
 // the result via rules, which would include a list of unowned pointers
 // to RawServoStyleRule.
 SERVO_BINDING_FUNC(Servo_ComputedValues_GetStyleRuleList, void,
-                   ServoComputedValuesBorrowed values,
+                   ServoStyleContextBorrowed values,
                    RawGeckoServoStyleRuleListBorrowedMut rules)
 
 // Initialize Servo components. Should be called exactly once at startup.
 SERVO_BINDING_FUNC(Servo_Initialize, void,
                    RawGeckoURLExtraData* dummy_url_data)
 // Shut down Servo components. Should be called exactly once at shutdown.
 SERVO_BINDING_FUNC(Servo_Shutdown, void)
 
@@ -558,24 +558,24 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetBas
 
 // For canvas font.
 SERVO_BINDING_FUNC(Servo_SerializeFontValueForCanvas, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsAString* buffer)
 
 // Get custom property value.
 SERVO_BINDING_FUNC(Servo_GetCustomPropertyValue, bool,
-                   ServoComputedValuesBorrowed computed_values,
+                   ServoStyleContextBorrowed computed_values,
                    const nsAString* name, nsAString* value)
 
 SERVO_BINDING_FUNC(Servo_GetCustomPropertiesCount, uint32_t,
-                   ServoComputedValuesBorrowed computed_values)
+                   ServoStyleContextBorrowed computed_values)
 
 SERVO_BINDING_FUNC(Servo_GetCustomPropertyNameAt, bool,
-                   ServoComputedValuesBorrowed, uint32_t index,
+                   ServoStyleContextBorrowed, uint32_t index,
                    nsAString* name)
 
 SERVO_BINDING_FUNC(Servo_GetEmptyVariables, const nsStyleVariables*)
 
 
 // AddRef / Release functions
 #define SERVO_ARC_TYPE(name_, type_)                                \
   SERVO_BINDING_FUNC(Servo_##name_##_AddRef, void, type_##Borrowed) \
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -412,16 +412,21 @@ Gecko_CalcStyleDifference(const ServoSty
   uint32_t samePointerStructs;  // unused
   nsChangeHint result = const_cast<ServoStyleContext*>(aOldStyle)->
     CalcStyleDifference(
       const_cast<ServoStyleContext*>(aNewStyle),
       &equalStructs,
       &samePointerStructs,
       relevantStructs);
 
+  uint32_t equalStructs, samePointerStructs;
+  nsChangeHint result =
+    aOldStyleContext->CalcStyleDifference(aComputedValues,
+                                          &equalStructs,
+                                          &samePointerStructs);
   *aAnyStyleChanged = equalStructs != NS_STYLE_INHERIT_MASK;
   return result;
 }
 
 nsChangeHint
 Gecko_HintsHandledForDescendants(nsChangeHint aHint)
 {
   return aHint & ~NS_HintsNotHandledForDescendantsIn(aHint);
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -320,17 +320,17 @@ mapped-generic-types = [
     { 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<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
     { generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>" },
     { generic = false, gecko = "mozilla::ServoComputedValueFlags", servo = "::properties::computed_value_flags::ComputedValueFlags" },
     { generic = true, gecko = "mozilla::ServoRawOffsetArc", servo = "::servo_arc::RawOffsetArc" },
-    { generic = false, gecko = "ServoStyleContextStrong", servo = "::gecko_bindings::sugar::ownership::Strong<ServoStyleContext>" },
+    { generic = false, gecko = "ServoStyleContextStrong", servo = "::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>" },
 ]
 fixups = [
     { pat = "root::nsString", rep = "::nsstring::nsStringRepr" },
 ]
 
 [bindings]
 headers = ["mozilla/ServoBindings.h"]
 hide-types = [
@@ -340,17 +340,17 @@ hide-types = [
     "ServoStyleContextBorrowedOrNull",
 ]
 raw-lines = [
     "pub use nsstring::{nsACString, nsAString, nsString, nsStringRepr};",
     "use gecko_bindings::structs::nsStyleTransformMatrix;",
     "use gecko_bindings::structs::nsTArray;",
     "type nsACString_internal = nsACString;",
     "type nsAString_internal = nsAString;",
-    "pub type ServoStyleContextBorrowed<'a> = &'a ServoStyleContext;",
+    "pub type ServoStyleContextBorrowed<'a> = &'a ::properties::ComputedValues;",
     "pub type ServoStyleContextBorrowedOrNull<'a> = Option<&'a ::properties::ComputedValues>;",
     "pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;",
     "pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;",
 ]
 whitelist-functions = ["Servo_.*", "Gecko_.*"]
 structs-types = [
     "mozilla::css::GridTemplateAreasValue",
     "mozilla::css::ErrorReporter",
--- a/layout/style/ServoStyleContext.cpp
+++ b/layout/style/ServoStyleContext.cpp
@@ -20,17 +20,17 @@ ServoStyleContext::ServoStyleContext(
     nsPresContext* aPresContext,
     nsIAtom* aPseudoTag,
     CSSPseudoElementType aPseudoType,
     ServoComputedValuesForgotten aComputedValues)
   : nsStyleContext(aParent, aPseudoTag, aPseudoType)
   , mSource(aComputedValues)
 {
   mPresContext = aPresContext;
-  AddStyleBit(Servo_ComputedValues_GetStyleBits(&mSource));
+  AddStyleBit(Servo_ComputedValues_GetStyleBits(this));
 
   FinishConstruction();
 
   // No need to call ApplyStyleFixups here, since fixups are handled by Servo when
   // producing the ServoComputedValues.
 }
 
 void
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -456,17 +456,17 @@ ServoStyleSet::ResolvePseudoElementStyle
   MOZ_ASSERT(computedValues);
 
   bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
                          aType == CSSPseudoElementType::after;
   computedValues->UpdateWithElementState(isBeforeOrAfter ? aOriginatingElement : nullptr);
   return computedValues.forget();
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<ServoStyleContext>
 ServoStyleSet::ResolveTransientStyle(Element* aElement,
                                      CSSPseudoElementType aPseudoType,
                                      nsIAtom* aPseudoTag,
                                      StyleRuleInclusion aRuleInclusion)
 {
   RefPtr<ServoStyleContext> result =
     ResolveTransientServoStyle(aElement, aPseudoType, aPseudoTag, aRuleInclusion);
   result->UpdateWithElementState(nullptr);
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -181,24 +181,24 @@ public:
                             CSSPseudoElementType aType,
                             ServoStyleContext* aParentContext,
                             dom::Element* aPseudoElement);
 
   // Resolves style for a (possibly-pseudo) Element without assuming that the
   // style has been resolved, and without worrying about setting the style
   // context up to live in the style context tree (a null parent is used).
   // |aPeudoTag| and |aPseudoType| must match.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<ServoStyleContext>
   ResolveTransientStyle(dom::Element* aElement,
                         CSSPseudoElementType aPseudoType,
                         nsIAtom* aPseudoTag,
                         StyleRuleInclusion aRules =
                           StyleRuleInclusion::All);
 
-  // Similar to ResolveTransientStyle() but returns ServoComputedValues.
+  // Similar to ResolveTransientStyle() but doesn't update the context state
   // Unlike ResolveServoStyle() this function calls PreTraverseSync().
   already_AddRefed<ServoStyleContext>
   ResolveTransientServoStyle(dom::Element* aElement,
                              CSSPseudoElementType aPseudoType,
                              nsIAtom* aPseudoTag,
                              StyleRuleInclusion aRules =
                                StyleRuleInclusion::All);
 
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -349,17 +349,17 @@ nsComputedDOMStyle::GetLength(uint32_t* 
 
   uint32_t length = GetComputedStyleMap()->Length();
 
   // Make sure we have up to date style so that we can include custom
   // properties.
   UpdateCurrentStyleSources(false);
   if (mStyleContext) {
     length += mStyleContext->IsServo()
-      ? Servo_GetCustomPropertiesCount(mStyleContext->ComputedValues())
+      ? Servo_GetCustomPropertiesCount(mStyleContext->AsServo())
       : StyleVariables()->mVariables.Count();
   }
 
   *aLength = length;
 
   ClearCurrentStyleSources();
 
   return NS_OK;
@@ -1089,26 +1089,25 @@ nsComputedDOMStyle::IndexedGetter(uint32
 
   bool isServo = mStyleContext->IsServo();
 
   const nsStyleVariables* variables = isServo
     ? nullptr
     : StyleVariables();
 
   const uint32_t count = isServo
-    ? Servo_GetCustomPropertiesCount(mStyleContext->ComputedValues())
+    ? Servo_GetCustomPropertiesCount(mStyleContext->AsServo())
     : variables->mVariables.Count();
 
   const uint32_t index = aIndex - length;
   if (index < count) {
     aFound = true;
     nsString varName;
     if (isServo) {
-      Servo_GetCustomPropertyNameAt(mStyleContext->ComputedValues(),
-                                    index, &varName);
+      Servo_GetCustomPropertyNameAt(mStyleContext->AsServo(), index, &varName);
     } else {
       variables->mVariables.GetVariableAt(index, varName);
     }
     aPropName.AssignLiteral("--");
     aPropName.Append(varName);
   } else {
     aFound = false;
   }
@@ -6944,18 +6943,17 @@ 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 = mStyleContext->IsServo()
-    ? Servo_GetCustomPropertyValue(mStyleContext->ComputedValues(),
-                                   &name, &variableValue)
+    ? Servo_GetCustomPropertyValue(mStyleContext->AsServo(), &name, &variableValue)
     : StyleVariables()->mVariables.Get(name, variableValue);
   if (!present) {
     return nullptr;
   }
 
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   val->SetString(variableValue);
 
--- a/servo/components/servo_arc/lib.rs
+++ b/servo/components/servo_arc/lib.rs
@@ -884,16 +884,22 @@ impl<'a, T> Clone for ArcBorrow<'a, T> {
 impl<'a, T> ArcBorrow<'a, T> {
     pub fn clone_arc(&self) -> Arc<T> {
         let arc = unsafe { Arc::from_raw(self.0) };
         // addref it!
         mem::forget(arc.clone());
         arc
     }
 
+    /// For constructing from a reference known to be Arc-backed,
+    /// e.g. if we obtain such a reference over FFI
+    pub unsafe fn from_ref(r: &'a T) -> Self {
+        ArcBorrow(r)
+    }
+
     pub fn with_arc<F, U>(&self, f: F) -> U where F: FnOnce(&Arc<T>) -> U, T: 'static {
         // Synthesize transient Arc, which never touches the refcount.
         let transient = unsafe { NoDrop::new(Arc::from_raw(self.0)) };
 
         // Expose the transient Arc to the callback, which may clone it if it wants.
         let result = f(&transient);
 
         // Forget the transient Arc to leave the refcount untouched.
--- a/servo/components/style/gecko/arc_types.rs
+++ b/servo/components/style/gecko/arc_types.rs
@@ -8,23 +8,24 @@
 
 #![allow(non_snake_case, missing_docs)]
 
 use gecko_bindings::bindings::{RawServoImportRule, RawServoSupportsRule};
 use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule};
 use gecko_bindings::bindings::{RawServoMediaRule, RawServoNamespaceRule, RawServoPageRule};
 use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule};
 use gecko_bindings::bindings::ServoCssRules;
-use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoStyleRule, RawServoMediaList};
-use gecko_bindings::structs::{RawServoStyleSheetContents, ServoStyleContext};
-use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
+use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoStyleRule};
+use gecko_bindings::structs::{RawServoMediaList, RawServoStyleSheetContents};
+use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong};
 use media_queries::MediaList;
 use properties::{ComputedValues, PropertyDeclarationBlock};
 use properties::animated_properties::AnimationValue;
 use rule_tree::StrongRuleNode;
+use servo_arc::{Arc, ArcBorrow};
 use shared_lock::Locked;
 use std::{mem, ptr};
 use stylesheets::{CssRules, StylesheetContents, StyleRule, ImportRule, KeyframesRule, MediaRule};
 use stylesheets::{NamespaceRule, PageRule, SupportsRule, DocumentRule};
 use stylesheets::keyframes_rule::Keyframe;
 
 macro_rules! impl_arc_ffi {
     ($servo_type:ty => $gecko_type:ty [$addref:ident, $release:ident]) => {
@@ -46,19 +47,16 @@ macro_rules! impl_arc_ffi {
 }
 
 impl_arc_ffi!(Locked<CssRules> => ServoCssRules
               [Servo_CssRules_AddRef, Servo_CssRules_Release]);
 
 impl_arc_ffi!(StylesheetContents => RawServoStyleSheetContents
               [Servo_StyleSheetContents_AddRef, Servo_StyleSheetContents_Release]);
 
-impl_arc_ffi!(ComputedValues => ServoStyleContext
-              [Servo_StyleContext_AddRef, Servo_StyleContext_Release]);
-
 impl_arc_ffi!(Locked<PropertyDeclarationBlock> => RawServoDeclarationBlock
               [Servo_DeclarationBlock_AddRef, Servo_DeclarationBlock_Release]);
 
 impl_arc_ffi!(Locked<StyleRule> => RawServoStyleRule
               [Servo_StyleRule_AddRef, Servo_StyleRule_Release]);
 
 impl_arc_ffi!(Locked<ImportRule> => RawServoImportRule
               [Servo_ImportRule_AddRef, Servo_ImportRule_Release]);
@@ -109,8 +107,33 @@ pub unsafe extern "C" fn Servo_RuleNode_
     mem::forget(StrongRuleNode::from_ffi(&obj).clone());
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_RuleNode_Release(obj: &RawServoRuleNode) {
     let ptr = StrongRuleNode::from_ffi(&obj);
     ptr::read(ptr as *const StrongRuleNode);
 }
+
+// ServoStyleContext is not an opaque type on any side of FFI.
+// This means that doing the HasArcFFI type trick is actually unsound,
+// since it gives us a way to construct an Arc<ServoStyleContext> from
+// an &ServoStyleContext, which in general is not allowed. So we
+// implement the restricted set of arc type functionality we need.
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_StyleContext_AddRef(obj: &ComputedValues) {
+    mem::forget(ArcBorrow::from_ref(obj).clone_arc());
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_StyleContext_Release(obj: &ComputedValues) {
+    ArcBorrow::from_ref(obj).with_arc(|a: &Arc<ComputedValues>| {
+        let _: Arc<ComputedValues> = ptr::read(a);
+    });
+}
+
+
+impl From<Arc<ComputedValues>> for Strong<ComputedValues> {
+    fn from(arc: Arc<ComputedValues>) -> Self {
+        unsafe { mem::transmute(Arc::into_raw_offset(arc)) }
+    }
+}
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -1,16 +1,16 @@
 /* automatically generated by rust-bindgen */
 
 pub use nsstring::{nsACString, nsAString, nsString, nsStringRepr};
 use gecko_bindings::structs::nsStyleTransformMatrix;
 use gecko_bindings::structs::nsTArray;
 type nsACString_internal = nsACString;
 type nsAString_internal = nsAString;
-pub type ServoStyleContextBorrowed<'a> = &'a ServoStyleContext;
+pub type ServoStyleContextBorrowed<'a> = &'a ::properties::ComputedValues;
 pub type ServoStyleContextBorrowedOrNull<'a> = Option<&'a ::properties::ComputedValues>;
 pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;
 pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;
 use gecko_bindings::structs::mozilla::css::GridTemplateAreasValue;
 use gecko_bindings::structs::mozilla::css::ErrorReporter;
 use gecko_bindings::structs::mozilla::css::ImageValue;
 use gecko_bindings::structs::mozilla::css::URLValue;
 use gecko_bindings::structs::mozilla::css::URLValueData;
@@ -2317,17 +2317,17 @@ extern "C" {
     pub fn Servo_ComputedValues_ExtractAnimationValue(computed_values:
                                                           ServoStyleContextBorrowed,
                                                       property:
                                                           nsCSSPropertyID)
      -> RawServoAnimationValueStrong;
 }
 extern "C" {
     pub fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(computed_values:
-                                                                     ServoComputedValuesBorrowed)
+                                                                     ServoStyleContextBorrowed)
      -> bool;
 }
 extern "C" {
     pub fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool;
 }
 extern "C" {
     pub fn Servo_Property_IsTransitionable(property: nsCSSPropertyID) -> bool;
 }
@@ -2700,29 +2700,29 @@ extern "C" {
                                         pseudo_tag: *mut nsIAtom,
                                         parent_style:
                                             ServoStyleContextBorrowedOrNull,
                                         target: InheritTarget)
      -> ServoStyleContextStrong;
 }
 extern "C" {
     pub fn Servo_ComputedValues_GetStyleBits(values:
-                                                 ServoComputedValuesBorrowed)
+                                                 ServoStyleContextBorrowed)
      -> u64;
 }
 extern "C" {
     pub fn Servo_ComputedValues_EqualCustomProperties(first:
                                                           ServoComputedValuesBorrowed,
                                                       second:
                                                           ServoComputedValuesBorrowed)
      -> bool;
 }
 extern "C" {
     pub fn Servo_ComputedValues_GetStyleRuleList(values:
-                                                     ServoComputedValuesBorrowed,
+                                                     ServoStyleContextBorrowed,
                                                  rules:
                                                      RawGeckoServoStyleRuleListBorrowedMut);
 }
 extern "C" {
     pub fn Servo_Initialize(dummy_url_data: *mut RawGeckoURLExtraData);
 }
 extern "C" {
     pub fn Servo_Shutdown();
@@ -2799,27 +2799,27 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_SerializeFontValueForCanvas(declarations:
                                                  RawServoDeclarationBlockBorrowed,
                                              buffer: *mut nsAString);
 }
 extern "C" {
     pub fn Servo_GetCustomPropertyValue(computed_values:
-                                            ServoComputedValuesBorrowed,
+                                            ServoStyleContextBorrowed,
                                         name: *const nsAString,
                                         value: *mut nsAString) -> bool;
 }
 extern "C" {
     pub fn Servo_GetCustomPropertiesCount(computed_values:
-                                              ServoComputedValuesBorrowed)
+                                              ServoStyleContextBorrowed)
      -> u32;
 }
 extern "C" {
-    pub fn Servo_GetCustomPropertyNameAt(arg1: ServoComputedValuesBorrowed,
+    pub fn Servo_GetCustomPropertyNameAt(arg1: ServoStyleContextBorrowed,
                                          index: u32, name: *mut nsAString)
      -> bool;
 }
 extern "C" {
     pub fn Servo_GetEmptyVariables() -> *const nsStyleVariables;
 }
 extern "C" {
     pub fn Gecko_CreateCSSErrorReporter(sheet: *mut ServoStyleSheet,
--- a/servo/components/style/gecko/generated/structs_debug.rs
+++ b/servo/components/style/gecko/generated/structs_debug.rs
@@ -11,17 +11,17 @@ pub type ServoCell<T> = ::std::cell::Cel
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
 pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
 pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::servo_arc::RawOffsetArc<T>;
-pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<ServoStyleContext>;
+pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>;
 
 #[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> {
         #[inline]
         pub fn new() -> Self {
--- a/servo/components/style/gecko/generated/structs_release.rs
+++ b/servo/components/style/gecko/generated/structs_release.rs
@@ -11,17 +11,17 @@ pub type ServoCell<T> = ::std::cell::Cel
 pub type ServoNodeData = AtomicRefCell<ElementData>;
 pub type ServoWritingMode = ::logical_geometry::WritingMode;
 pub type ServoFontComputationData = ::properties::FontComputationData;
 pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>;
 pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>;
 pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>;
 pub type ServoComputedValueFlags = ::properties::computed_value_flags::ComputedValueFlags;
 pub type ServoRawOffsetArc<T> = ::servo_arc::RawOffsetArc<T>;
-pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<ServoStyleContext>;
+pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<::properties::ComputedValues>;
 
 #[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> {
         #[inline]
         pub fn new() -> Self {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -222,17 +222,18 @@ impl ComputedValuesInner {
         self,
         pres_context: bindings::RawGeckoPresContextBorrowed,
         parent: ParentStyleContextInfo,
         pseudo_ty: structs::CSSPseudoElementType,
         pseudo_tag: *mut structs::nsIAtom
     ) -> Arc<ComputedValues> {
         let arc = unsafe {
             let arc: Arc<ComputedValues> = Arc::new(uninitialized());
-            bindings::Gecko_ServoStyleContext_Init(&arc.0 as *const _ as *mut _, parent, pres_context,
+            bindings::Gecko_ServoStyleContext_Init(&arc.0 as *const _ as *mut _,
+                                                   parent, pres_context,
                                                    &self, pseudo_ty, pseudo_tag);
             // We're simulating a move by having C++ do a memcpy and then forgetting
             // it on this end.
             forget(self);
             arc
         };
         arc
     }
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use atomic_refcell::AtomicRefMut;
 use cssparser::{Parser, ParserInput};
 use cssparser::ToCss as ParserToCss;
 use env_logger::LogBuilder;
 use selectors::Element;
 use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
-use servo_arc::{Arc, RawOffsetArc};
+use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use std::env;
 use std::fmt::Write;
 use std::ptr;
 use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
 use style::context::ThreadLocalStyleContext;
 use style::data::{ElementData, ElementStyles, RestyleData};
 use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
 use style::dom::{ShowSubtreeData, TElement, TNode};
@@ -661,46 +661,46 @@ pub extern "C" fn Servo_StyleSet_GetBase
                                                                  computed_values: ServoStyleContextBorrowed,
                                                                  snapshots: *const ServoElementSnapshotTable,
                                                                  pseudo_type: CSSPseudoElementType)
                                                                  -> ServoStyleContextStrong
 {
     use style::style_resolver::StyleResolverForElement;
 
     debug_assert!(!snapshots.is_null());
-    let computed_values = ComputedValues::as_arc(&computed_values);
+    let computed_values = unsafe { ArcBorrow::from_ref(computed_values) };
 
     let rules = match computed_values.rules {
-        None => return computed_values.clone().into_strong(),
+        None => return computed_values.clone_arc().into(),
         Some(ref rules) => rules,
     };
 
     let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let without_animations =
         doc_data.stylist.rule_tree().remove_animation_rules(rules);
 
     if without_animations == *rules {
-        return computed_values.clone().into_strong();
+        return computed_values.clone_arc().into();
     }
 
     let element = GeckoElement(element);
 
     let element_data = match element.borrow_data() {
         Some(data) => data,
-        None => return computed_values.clone().into_strong(),
+        None => return computed_values.clone_arc().into(),
     };
     let styles = &element_data.styles;
 
     if let Some(pseudo) = PseudoElement::from_pseudo_type(pseudo_type) {
         // This style already doesn't have animations.
         return styles
             .pseudos
             .get(&pseudo)
             .expect("GetBaseComputedValuesForElement for an unexisting pseudo?")
-            .clone().into_strong();
+            .clone().into();
     }
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
     let shared = create_shared_context(&global_style_data,
                                        &guard,
                                        &doc_data,
                                        TraversalFlags::empty(),
@@ -716,31 +716,30 @@ pub extern "C" fn Servo_StyleSet_GetBase
     let inputs =
         CascadeInputs {
             rules: Some(without_animations),
             visited_rules: None,
         };
 
     StyleResolverForElement::new(element, &mut context, RuleInclusion::All)
         .cascade_style_and_visited_with_default_parents(inputs)
-        .into_strong()
+        .into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputedValues_ExtractAnimationValue(computed_values: ServoStyleContextBorrowed,
                                                              property_id: nsCSSPropertyID)
                                                              -> RawServoAnimationValueStrong
 {
     let property = match AnimatableLonghand::from_nscsspropertyid(property_id) {
         Some(longhand) => longhand,
         None => return Strong::null(),
     };
 
-    let computed_values = ComputedValues::as_arc(&computed_values);
-    Arc::new(AnimationValue::from_computed_values(&property, computed_values)).into_strong()
+    Arc::new(AnimationValue::from_computed_values(&property, &computed_values)).into_strong()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool {
     use style::properties::animated_properties;
     animated_properties::nscsspropertyid_is_animatable(property)
 }
 
@@ -1521,17 +1520,17 @@ pub extern "C" fn Servo_ComputedValues_G
         cascade_flags.insert(IS_FIELDSET_CONTENT);
     }
     let metrics = get_metrics_provider_for_product();
     data.stylist.precomputed_values_for_pseudo(
         &guards,
         &pseudo,
         parent_style_or_null.map(|x| &*x),
         cascade_flags, &metrics
-    ).into_strong()
+    ).into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
                                            pseudo_type: CSSPseudoElementType,
                                            is_probe: bool,
                                            inherited_style: ServoStyleContextBorrowedOrNull,
                                            raw_data: RawServoStyleSetBorrowed)
@@ -1545,17 +1544,17 @@ pub extern "C" fn Servo_ResolvePseudoSty
            element, PseudoElement::from_pseudo_type(pseudo_type), is_probe);
 
     // FIXME(bholley): Assert against this.
     if !data.has_styles() {
         warn!("Calling Servo_ResolvePseudoStyle on unstyled element");
         return if is_probe {
             Strong::null()
         } else {
-            doc_data.default_computed_values().clone().into_strong()
+            doc_data.default_computed_values().clone().into()
         };
     }
 
     let pseudo = PseudoElement::from_pseudo_type(pseudo_type)
                     .expect("ResolvePseudoStyle with a non-pseudo?");
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
@@ -1566,36 +1565,35 @@ pub extern "C" fn Servo_ResolvePseudoSty
         RuleInclusion::All,
         &data.styles,
         inherited_style,
         &*doc_data,
         is_probe,
     );
 
     match style {
-        Some(s) => s.into_strong(),
+        Some(s) => s.into(),
         None => {
             debug_assert!(is_probe);
             Strong::null()
         }
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
                                          style: ServoStyleContextBorrowed)
 {
     let element = GeckoElement(element);
-    let style = ComputedValues::as_arc(&style);
     debug!("Servo_SetExplicitStyle: {:?}", element);
     // We only support this API for initial styling. There's no reason it couldn't
     // work for other things, we just haven't had a reason to do so.
     debug_assert!(element.get_data().is_none());
     let mut data = unsafe { element.ensure_data() };
-    data.styles.primary = Some(style.clone_arc());
+    data.styles.primary = Some(unsafe { ArcBorrow::from_ref(style) }.clone_arc());
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_HasAuthorSpecifiedRules(element: RawGeckoElementBorrowed,
                                                 rule_type_mask: u32,
                                                 author_colors_allowed: bool)
     -> bool
 {
@@ -1725,50 +1723,50 @@ pub extern "C" fn Servo_ComputedValues_I
         StyleBuilder::for_derived_style(
             data.stylist.device(),
             data.default_computed_values(),
             /* parent_style = */ None,
             Some(&pseudo),
         ).build()
     };
 
-    style.into_strong()
+    style.into()
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ServoComputedValuesBorrowed) -> u64 {
+pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ServoStyleContextBorrowed) -> u64 {
     use style::properties::computed_value_flags::*;
     let flags = values.flags;
     let mut result = 0;
     if flags.contains(HAS_TEXT_DECORATION_LINES) {
         result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64;
     }
     if flags.contains(SHOULD_SUPPRESS_LINEBREAK) {
         result |= structs::NS_STYLE_SUPPRESS_LINEBREAK as u64;
     }
     result
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(values: ServoComputedValuesBorrowed)
+pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(values: ServoStyleContextBorrowed)
                                                                         -> bool {
     let b = values.get_box();
     b.specifies_animations() || b.specifies_transitions()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputedValues_EqualCustomProperties(
     first: ServoComputedValuesBorrowed,
     second: ServoComputedValuesBorrowed
 ) -> bool {
     first.get_custom_properties() == second.get_custom_properties()
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoComputedValuesBorrowed,
+pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed,
                                                         rules: RawGeckoServoStyleRuleListBorrowedMut) {
     if let Some(ref rule_node) = values.rules {
         let mut result = vec![];
         for node in rule_node.self_and_ancestors() {
             if let &StyleSource::Style(ref rule) = node.style_source() {
                 result.push(rule);
             }
         }
@@ -2799,17 +2797,17 @@ pub extern "C" fn Servo_ResolveStyle(ele
     // restyle hints other than animation hints.
     let flags = if restyle_behavior == Restyle::ForThrottledAnimationFlush {
         ANIMATION_ONLY
     } else {
         TraversalFlags::empty()
     };
     debug_assert!(element.has_current_styles_for_traversal(&*data, flags),
                   "Resolving style on element without current styles");
-    data.styles.primary().clone().into_strong()
+    data.styles.primary().clone().into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
                                            pseudo_type: CSSPseudoElementType,
                                            rule_inclusion: StyleRuleInclusion,
                                            snapshots: *const ServoElementSnapshotTable,
                                            raw_data: RawServoStyleSetBorrowed)
@@ -2848,34 +2846,34 @@ pub extern "C" fn Servo_ResolveStyleLazi
         let styles = element.mutate_data().and_then(|d| {
             if d.has_styles() {
                 Some(finish(&d.styles))
             } else {
                 None
             }
         });
         if let Some(result) = styles {
-            return result.into_strong();
+            return result.into();
         }
     }
 
     // We don't have the style ready. Go ahead and compute it as necessary.
     let shared = create_shared_context(&global_style_data,
                                        &guard,
                                        &data,
                                        TraversalFlags::empty(),
                                        unsafe { &*snapshots });
     let mut tlc = ThreadLocalStyleContext::new(&shared);
     let mut context = StyleContext {
         shared: &shared,
         thread_local: &mut tlc,
     };
 
     let styles = resolve_style(&mut context, element, rule_inclusion);
-    finish(&styles).into_strong()
+    finish(&styles).into()
 }
 
 #[cfg(feature = "gecko_debug")]
 fn simulate_compute_values_failure(property: &PropertyValuePair) -> bool {
     let p = property.mProperty;
     let id = get_property_id_from_nscsspropertyid!(p, false);
     id.as_shorthand().is_ok() && property.mSimulateComputeValuesFailure
 }
@@ -2914,25 +2912,24 @@ pub extern "C" fn Servo_GetComputedKeyfr
                                                   raw_data: RawServoStyleSetBorrowed,
                                                   computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut)
 {
     use std::mem;
     use style::properties::LonghandIdSet;
 
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let metrics = get_metrics_provider_for_product();
-    let style = ComputedValues::as_arc(&style);
 
     let element = GeckoElement(element);
     let parent_element = element.inheritance_parent();
     let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
     let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
 
     let pseudo = style.pseudo();
-    let mut context = create_context(&data, &metrics, style, parent_style, pseudo.as_ref());
+    let mut context = create_context(&data, &metrics, &style, parent_style, pseudo.as_ref());
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
     let default_values = data.default_computed_values();
 
     for (index, keyframe) in keyframes.iter().enumerate() {
         let ref mut animation_values = computed_keyframes[index];
 
@@ -2996,25 +2993,24 @@ pub extern "C" fn Servo_GetComputedKeyfr
 #[no_mangle]
 pub extern "C" fn Servo_GetAnimationValues(declarations: RawServoDeclarationBlockBorrowed,
                                            element: RawGeckoElementBorrowed,
                                            style: ServoStyleContextBorrowed,
                                            raw_data: RawServoStyleSetBorrowed,
                                            animation_values: RawGeckoServoAnimationValueListBorrowedMut) {
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let metrics = get_metrics_provider_for_product();
-    let style = ComputedValues::as_arc(&style);
 
     let element = GeckoElement(element);
     let parent_element = element.inheritance_parent();
     let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
     let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
 
     let pseudo = style.pseudo();
-    let mut context = create_context(&data, &metrics, style, parent_style, pseudo.as_ref());
+    let mut context = create_context(&data, &metrics, &style, parent_style, pseudo.as_ref());
 
     let default_values = data.default_computed_values();
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
 
     let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
     let guard = declarations.read_with(&guard);
     for (index, anim) in guard.to_animation_value_iter(&mut context, &default_values).enumerate() {
@@ -3026,17 +3022,16 @@ pub extern "C" fn Servo_GetAnimationValu
 #[no_mangle]
 pub extern "C" fn Servo_AnimationValue_Compute(element: RawGeckoElementBorrowed,
                                                declarations: RawServoDeclarationBlockBorrowed,
                                                style: ServoStyleContextBorrowed,
                                                raw_data: RawServoStyleSetBorrowed)
                                                -> RawServoAnimationValueStrong {
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let metrics = get_metrics_provider_for_product();
-    let style = ComputedValues::as_arc(&style);
 
     let element = GeckoElement(element);
     let parent_element = element.inheritance_parent();
     let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
     let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
 
     let pseudo = style.pseudo();
     let mut context = create_context(&data, &metrics, style, parent_style, pseudo.as_ref());
@@ -3288,17 +3283,17 @@ pub extern "C" fn Servo_StyleSet_Resolve
     };
 
     let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
 
     doc_data.stylist.compute_for_declarations(
         &guards,
         parent_style,
         declarations.clone_arc(),
-    ).into_strong()
+    ).into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
     raw_data: RawServoStyleSetBorrowed,
     element: RawGeckoElementBorrowed,
     local_name: *mut nsIAtom,
 ) -> bool {
@@ -3345,17 +3340,17 @@ pub extern "C" fn Servo_StyleSet_HasStat
             has_dep = has_dep || stylist.might_have_state_dependency(state);
         });
     }
 
     has_dep
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_GetCustomPropertyValue(computed_values: ServoComputedValuesBorrowed,
+pub extern "C" fn Servo_GetCustomPropertyValue(computed_values: ServoStyleContextBorrowed,
                                                name: *const nsAString,
                                                value: *mut nsAString) -> bool {
     let custom_properties = match computed_values.custom_properties() {
         Some(p) => p,
         None => return false,
     };
 
     let name = unsafe { Atom::from((&*name)) };
@@ -3364,25 +3359,25 @@ pub extern "C" fn Servo_GetCustomPropert
         None => return false,
     };
 
     computed_value.to_css(unsafe { value.as_mut().unwrap() }).unwrap();
     true
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_GetCustomPropertiesCount(computed_values: ServoComputedValuesBorrowed) -> u32 {
+pub extern "C" fn Servo_GetCustomPropertiesCount(computed_values: ServoStyleContextBorrowed) -> u32 {
     match computed_values.custom_properties() {
         Some(p) => p.len() as u32,
         None => 0,
     }
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_GetCustomPropertyNameAt(computed_values: ServoComputedValuesBorrowed,
+pub extern "C" fn Servo_GetCustomPropertyNameAt(computed_values: ServoStyleContextBorrowed,
                                                 index: u32,
                                                 name: *mut nsAString) -> bool {
     let custom_properties = match computed_values.custom_properties() {
         Some(p) => p,
         None => return false,
     };
 
     let property_name = match custom_properties.get_name_at(index) {