Bug 1309109 part 5 - Store ServoDeclarationBlock rather than RawServoDeclarationBlock in nsAttrValue. r?heycam draft
authorXidorn Quan <me@upsuper.org>
Wed, 12 Oct 2016 15:23:02 +1100
changeset 426168 5ddf7f31447125e470f869e31496db79909634ad
parent 426167 660d4e1b274346aafa50d1c595891798227129af
child 426169 5f8c706d7361f0be2c27f90ad960237845efd238
push id32640
push userxquan@mozilla.com
push dateTue, 18 Oct 2016 00:25:47 +0000
reviewersheycam
bugs1309109
milestone52.0a1
Bug 1309109 part 5 - Store ServoDeclarationBlock rather than RawServoDeclarationBlock in nsAttrValue. r?heycam MozReview-Commit-ID: HWqgjwif1qF
dom/base/Element.cpp
dom/base/Element.h
dom/base/FragmentOrElement.h
dom/base/nsAttrValue.cpp
dom/base/nsAttrValue.h
dom/base/nsAttrValueInlines.h
dom/base/nsStyledElement.cpp
dom/base/nsStyledElement.h
dom/html/nsGenericHTMLElement.cpp
dom/svg/nsSVGElement.cpp
dom/xul/nsXULElement.cpp
editor/libeditor/CSSEditUtils.cpp
layout/style/ServoBindings.cpp
layout/style/nsDOMCSSAttrDeclaration.cpp
layout/style/nsDOMCSSDeclaration.cpp
layout/style/nsHTMLCSSStyleSheet.cpp
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2009,24 +2009,24 @@ Element::IsLabelable() const
 }
 
 bool
 Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return false;
 }
 
-css::Declaration*
+DeclarationBlock*
 Element::GetInlineStyleDeclaration()
 {
   return nullptr;
 }
 
 nsresult
-Element::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+Element::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                    const nsAString* aSerialized,
                                    bool aNotify)
 {
   NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP_(bool)
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -51,16 +51,17 @@ struct nsRect;
 class nsFocusManager;
 class nsGlobalWindow;
 class nsICSSDeclaration;
 class nsISMILAttr;
 class nsDocument;
 class nsDOMStringMap;
 
 namespace mozilla {
+class DeclarationBlock;
 namespace dom {
   struct AnimationFilter;
   struct ScrollIntoViewOptions;
   struct ScrollToOptions;
   class ElementOrCSSPseudoElement;
   class UnrestrictedDoubleOrKeyframeAnimationOptions;
 } // namespace dom
 } // namespace mozilla
@@ -250,23 +251,23 @@ public:
   /**
    * Clear all style state locks on this element.
    */
   void ClearStyleStateLocks();
 
   /**
    * Get the inline style declaration, if any, for this element.
    */
-  virtual css::Declaration* GetInlineStyleDeclaration();
+  virtual DeclarationBlock* GetInlineStyleDeclaration();
 
   /**
    * Set the inline style declaration for this element. This will send
    * an appropriate AttributeChanged notification if aNotify is true.
    */
-  virtual nsresult SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+  virtual nsresult SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                              const nsAString* aSerialized,
                                              bool aNotify);
 
   /**
    * Get the SMIL override style declaration for this element. If the
    * rule hasn't been created, this method simply returns null.
    */
   virtual css::Declaration* GetSMILOverrideStyleDeclaration();
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -28,16 +28,19 @@ class nsDOMAttributeMap;
 class nsDOMTokenList;
 class nsIControllers;
 class nsICSSDeclaration;
 class nsIDocument;
 class nsDOMStringMap;
 class nsIURI;
 
 namespace mozilla {
+namespace css {
+class Declaration;
+} // namespace css
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 /**
  * A class that implements nsIWeakReference
  */
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/HashFunctions.h"
 
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsIAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ServoBindingHelpers.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "prprf.h"
 #include "nsHTMLCSSStyleSheet.h"
 #include "nsCSSParser.h"
 #include "nsStyledElement.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
@@ -68,89 +68,59 @@ MiscContainer::GetString(nsAString& aStr
   atom->ToString(aString);
   return true;
 }
 
 void
 MiscContainer::Cache()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eGeckoCSSDeclaration ||
-             mType == nsAttrValue::eServoCSSDeclaration);
+  if (mType != nsAttrValue::eCSSDeclaration) {
+    MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
+    return;
+  }
+
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount > 0);
   MOZ_ASSERT(!mValue.mCached);
 
-  nsHTMLCSSStyleSheet* sheet;
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      sheet = mValue.mGeckoCSSDeclaration->GetHTMLCSSStyleSheet();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      sheet = Servo_DeclarationBlock_GetCache(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      sheet = nullptr;
-      break;
-  }
-
+  nsHTMLCSSStyleSheet* sheet = mValue.mCSSDeclaration->GetHTMLCSSStyleSheet();
   if (!sheet) {
     return;
   }
 
   nsString str;
   bool gotString = GetString(str);
   if (!gotString) {
     return;
   }
 
   sheet->CacheStyleAttr(str, this);
   mValue.mCached = 1;
 
   // This has to be immutable once it goes into the cache.
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      mValue.mGeckoCSSDeclaration->SetImmutable();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      Servo_DeclarationBlock_SetImmutable(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      break;
-  }
+  mValue.mCSSDeclaration->SetImmutable();
 }
 
 void
 MiscContainer::Evict()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eGeckoCSSDeclaration ||
-             mType == nsAttrValue::eServoCSSDeclaration);
+  if (mType != nsAttrValue::eCSSDeclaration) {
+    MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
+    return;
+  }
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount == 0);
 
   if (!mValue.mCached) {
     return;
   }
 
-  nsHTMLCSSStyleSheet* sheet;
-  switch (mType) {
-    case nsAttrValue::eGeckoCSSDeclaration:
-      sheet = mValue.mGeckoCSSDeclaration->GetHTMLCSSStyleSheet();
-      break;
-    case nsAttrValue::eServoCSSDeclaration:
-      sheet = Servo_DeclarationBlock_GetCache(mValue.mServoCSSDeclaration);
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-      sheet = nullptr;
-      break;
-  }
+  nsHTMLCSSStyleSheet* sheet = mValue.mCSSDeclaration->GetHTMLCSSStyleSheet();
   MOZ_ASSERT(sheet);
 
   nsString str;
   DebugOnly<bool> gotString = GetString(str);
   MOZ_ASSERT(gotString);
 
   sheet->EvictStyleAttr(str, this);
   mValue.mCached = 0;
@@ -176,20 +146,21 @@ nsAttrValue::nsAttrValue(const nsAString
 }
 
 nsAttrValue::nsAttrValue(nsIAtom* aValue)
     : mBits(0)
 {
   SetTo(aValue);
 }
 
-nsAttrValue::nsAttrValue(css::Declaration* aValue, const nsAString* aSerialized)
+nsAttrValue::nsAttrValue(already_AddRefed<DeclarationBlock> aValue,
+                         const nsAString* aSerialized)
     : mBits(0)
 {
-  SetTo(aValue, aSerialized);
+  SetTo(Move(aValue), aSerialized);
 }
 
 nsAttrValue::nsAttrValue(const nsIntMargin& aValue)
     : mBits(0)
 {
   SetTo(aValue);
 }
 
@@ -338,18 +309,17 @@ nsAttrValue::SetTo(const nsAttrValue& aO
       cont->mValue.mPercent = otherCont->mValue.mPercent;
       break;
     }
     case eColor:
     {
       cont->mValue.mColor = otherCont->mValue.mColor;
       break;
     }
-    case eGeckoCSSDeclaration:
-    case eServoCSSDeclaration:
+    case eCSSDeclaration:
     {
       MOZ_CRASH("These should be refcounted!");
     }
     case eURL:
     {
       NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
       break;
     }
@@ -446,35 +416,23 @@ nsAttrValue::SetTo(double aValue, const 
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mDoubleValue = aValue;
   cont->mType = eDoubleValue;
   SetMiscAtomOrString(aSerialized);
 }
 
 void
-nsAttrValue::SetTo(css::Declaration* aValue, const nsAString* aSerialized)
-{
-  MiscContainer* cont = EnsureEmptyMiscContainer();
-  MOZ_ASSERT(cont->mValue.mRefCount == 0);
-  NS_ADDREF(cont->mValue.mGeckoCSSDeclaration = aValue);
-  cont->mType = eGeckoCSSDeclaration;
-  NS_ADDREF(cont);
-  SetMiscAtomOrString(aSerialized);
-  MOZ_ASSERT(cont->mValue.mRefCount == 1);
-}
-
-void
-nsAttrValue::SetTo(already_AddRefed<RawServoDeclarationBlock> aValue,
+nsAttrValue::SetTo(already_AddRefed<DeclarationBlock> aValue,
                    const nsAString* aSerialized)
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   MOZ_ASSERT(cont->mValue.mRefCount == 0);
-  cont->mValue.mServoCSSDeclaration = aValue.take();
-  cont->mType = eServoCSSDeclaration;
+  cont->mValue.mCSSDeclaration = aValue.take();
+  cont->mType = eCSSDeclaration;
   NS_ADDREF(cont);
   SetMiscAtomOrString(aSerialized);
   MOZ_ASSERT(cont->mValue.mRefCount == 1);
 }
 
 void
 nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
 {
@@ -677,27 +635,25 @@ nsAttrValue::ToString(nsAString& aResult
     case ePercent:
     {
       nsAutoString intStr;
       intStr.AppendInt(cont ? cont->mValue.mPercent : GetIntInternal());
       aResult = intStr + NS_LITERAL_STRING("%");
 
       break;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      // XXXheycam Once we support CSSOM access to them, we should
-      // probably serialize eServoCSSDeclarations like this too.
-      // For now, we will return the string from the MiscContainer
-      // at the top of this function.
       aResult.Truncate();
       MiscContainer *container = GetMiscContainer();
-      css::Declaration *decl = container->mValue.mGeckoCSSDeclaration;
-      if (decl) {
-        decl->ToString(aResult);
+      DeclarationBlock* decl = container->mValue.mCSSDeclaration;
+      // XXXheycam Once we support CSSOM access to them, we should
+      // probably serialize ServoDeclarationBlock like this too.
+      if (decl && decl->IsGecko()) {
+        decl->AsGecko()->ToString(aResult);
       }
       const_cast<nsAttrValue*>(this)->SetMiscAtomOrString(&aResult);
 
       break;
     }
     case eDoubleValue:
     {
       aResult.Truncate();
@@ -930,23 +886,19 @@ nsAttrValue::HashValue() const
     case ePercent:
     {
       return cont->mValue.mPercent;
     }
     case eColor:
     {
       return cont->mValue.mColor;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      return NS_PTR_TO_INT32(cont->mValue.mGeckoCSSDeclaration);
-    }
-    case eServoCSSDeclaration:
-    {
-      return NS_PTR_TO_INT32(cont->mValue.mServoCSSDeclaration);
+      return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration);
     }
     // Intentionally identical, so that loading the image does not change the
     // hash code.
     case eURL:
     case eImage:
     {
       nsString str;
       ToString(str);
@@ -1043,20 +995,20 @@ nsAttrValue::Equals(const nsAttrValue& a
     }
     case eColor:
     {
       if (thisCont->mValue.mColor == otherCont->mValue.mColor) {
         needsStringComparison = true;
       }
       break;
     }
-    case eGeckoCSSDeclaration:
+    case eCSSDeclaration:
     {
-      return thisCont->mValue.mGeckoCSSDeclaration ==
-               otherCont->mValue.mGeckoCSSDeclaration;
+      return thisCont->mValue.mCSSDeclaration ==
+               otherCont->mValue.mCSSDeclaration;
     }
     case eURL:
     {
       return thisCont->mValue.mURL == otherCont->mValue.mURL;
     }
     case eImage:
     {
       return thisCont->mValue.mImage == otherCont->mValue.mImage;
@@ -1076,21 +1028,16 @@ nsAttrValue::Equals(const nsAttrValue& a
     case eDoubleValue:
     {
       return thisCont->mDoubleValue == otherCont->mDoubleValue;
     }
     case eIntMarginValue:
     {
       return thisCont->mValue.mIntMargin == otherCont->mValue.mIntMargin;
     }
-    case eServoCSSDeclaration:
-    {
-      return thisCont->mValue.mServoCSSDeclaration ==
-               otherCont->mValue.mServoCSSDeclaration;
-    }
     default:
     {
       if (IsSVGType(thisCont->mType)) {
         // Currently this method is never called for nsAttrValue objects that
         // point to SVG data types.
         // If that changes then we probably want to add methods to the
         // corresponding SVG types to compare their base values.
         // As a shortcut, however, we can begin by comparing the pointers.
@@ -1766,36 +1713,30 @@ nsAttrValue::ParseStyleAttribute(const n
     if (cont) {
       // Set our MiscContainer to the cached one.
       NS_ADDREF(cont);
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
+  RefPtr<DeclarationBlock> decl;
   if (ownerDoc->GetStyleBackendType() == StyleBackendType::Servo) {
-    NS_ConvertUTF16toUTF8 value(aString);
-    RefPtr<RawServoDeclarationBlock> decl = Servo_ParseStyleAttribute(
-        reinterpret_cast<const uint8_t*>(value.get()),
-        value.Length(), sheet).Consume();
-    MOZ_ASSERT(decl);
-    SetTo(decl.forget(), &aString);
+    decl = ServoDeclarationBlock::FromStyleAttribute(aString);
   } else {
     css::Loader* cssLoader = ownerDoc->CSSLoader();
     nsCSSParser cssParser(cssLoader);
-
-    RefPtr<css::Declaration> declaration =
-      cssParser.ParseStyleAttribute(aString, docURI, baseURI,
-                                    aElement->NodePrincipal());
-    if (!declaration) {
-      return false;
-    }
-    declaration->SetHTMLCSSStyleSheet(sheet);
-    SetTo(declaration, &aString);
+    decl = cssParser.ParseStyleAttribute(aString, docURI, baseURI,
+                                         aElement->NodePrincipal());
   }
+  if (!decl) {
+    return false;
+  }
+  decl->SetHTMLCSSStyleSheet(sheet);
+  SetTo(decl.forget(), &aString);
 
   if (cachingAllowed) {
     MiscContainer* cont = GetMiscContainer();
     cont->Cache();
   }
 
   return true;
 }
@@ -1803,25 +1744,24 @@ nsAttrValue::ParseStyleAttribute(const n
 void
 nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
 {
   NS_ASSERTION(GetMiscContainer(), "Must have MiscContainer!");
   NS_ASSERTION(!GetMiscContainer()->mStringBits,
                "Trying to re-set atom or string!");
   if (aValue) {
     uint32_t len = aValue->Length();
-    // * We're allowing eGeckoCSSDeclaration and eServoCSSDeclaration
-    //   attributes to store empty strings as it can be beneficial to store
-    //   an empty style attribute as a parsed rule.
+    // * We're allowing eCSSDeclaration attributes to store empty
+    //   strings as it can be beneficial to store an empty style
+    //   attribute as a parsed rule.
     // * We're allowing enumerated values because sometimes the empty
     //   string corresponds to a particular enumerated value, especially
     //   for enumerated values that are not limited enumerated.
     // Add other types as needed.
-    NS_ASSERTION(len || Type() == eGeckoCSSDeclaration ||
-                 Type() == eServoCSSDeclaration || Type() == eEnum,
+    NS_ASSERTION(len || Type() == eCSSDeclaration || Type() == eEnum,
                  "Empty string?");
     MiscContainer* cont = GetMiscContainer();
     if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
       nsCOMPtr<nsIAtom> atom = NS_Atomize(*aValue);
       if (atom) {
         cont->mStringBits =
           reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase;
       }
@@ -1875,27 +1815,22 @@ nsAttrValue::ClearMiscContainer()
       // This MiscContainer is shared, we need a new one.
       NS_RELEASE(cont);
 
       cont = new MiscContainer;
       SetPtrValueAndType(cont, eOtherBase);
     }
     else {
       switch (cont->mType) {
-        case eGeckoCSSDeclaration:
-        case eServoCSSDeclaration:
+        case eCSSDeclaration:
         {
           MOZ_ASSERT(cont->mValue.mRefCount == 1);
           cont->Release();
           cont->Evict();
-          if (cont->mType == eGeckoCSSDeclaration) {
-            NS_RELEASE(cont->mValue.mGeckoCSSDeclaration);
-          } else {
-            Servo_DeclarationBlock_Release(cont->mValue.mServoCSSDeclaration);
-          }
+          NS_RELEASE(cont->mValue.mCSSDeclaration);
           break;
         }
         case eURL:
         {
           NS_RELEASE(cont->mValue.mURL);
           break;
         }
         case eImage:
@@ -2015,26 +1950,22 @@ nsAttrValue::SizeOfExcludingThis(MallocS
       // We only count the size of the object pointed by otherPtr if it's a
       // string. When it's an atom, it's counted separatly.
       if (otherPtr &&
           static_cast<ValueBaseType>(container->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) {
         nsStringBuffer* str = static_cast<nsStringBuffer*>(otherPtr);
         n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
       }
 
-      if (Type() == eGeckoCSSDeclaration &&
-          container->mValue.mGeckoCSSDeclaration) {
-        // TODO: mGeckoCSSDeclaration might be owned by another object which
+      if (Type() == eCSSDeclaration && container->mValue.mCSSDeclaration) {
+        // TODO: mCSSDeclaration might be owned by another object which
         //       would make us count them twice, bug 677493.
-        //n += container->mGeckoCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf);
-      } else if (Type() == eServoCSSDeclaration &&
-                 container->mValue.mServoCSSDeclaration) {
-        // Bug 1281964: As with eGeckoCSSDeclaration, but if we do measure we'll
-        // need a way to call the Servo heap_size_of function for the
-        // declaration block.
+        // Bug 1281964: For ServoDeclarationBlock if we do measure we'll
+        // need a way to call the Servo heap_size_of function.
+        //n += container->mCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf);
       } else if (Type() == eAtomArray && container->mValue.mAtomArray) {
         // Don't measure each nsIAtom, they are measured separatly.
         n += container->mValue.mAtomArray->ShallowSizeOfIncludingThis(aMallocSizeOf);
       }
       break;
     }
     case eAtomBase:    // Atoms are counted separately.
     case eIntegerBase: // The value is in mBits, nothing to do.
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -30,21 +30,20 @@
 
 // Undefine LoadImage to prevent naming conflict with Windows.
 #undef LoadImage
 
 class nsAString;
 class nsIDocument;
 class nsStyledElement;
 struct MiscContainer;
-struct RawServoDeclarationBlock;
 
 namespace mozilla {
+class DeclarationBlock;
 namespace css {
-class Declaration;
 struct URLValue;
 struct ImageValue;
 } // namespace css
 } // namespace mozilla
 
 #define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
 
 #define NS_ATTRVALUE_BASETYPE_MASK (uintptr_t(3))
@@ -93,18 +92,17 @@ public:
                           //   01  this value indicates a 'misc' struct
     eAtom =         0x02, //   10
     eInteger =      0x03, // 0011
     eColor =        0x07, // 0111
     eEnum =         0x0B, // 1011  This should eventually die
     ePercent =      0x0F, // 1111
     // Values below here won't matter, they'll be always stored in the 'misc'
     // struct.
-    eGeckoCSSDeclaration = 0x10,
-    eServoCSSDeclaration,
+    eCSSDeclaration = 0x10,
     eURL,
     eImage,
     eAtomArray,
     eDoubleValue,
     eIntMarginValue,
     eSVGAngle,
     eSVGTypesBegin = eSVGAngle,
     eSVGIntegerPair,
@@ -120,17 +118,18 @@ public:
     eSVGViewBox,
     eSVGTypesEnd = eSVGViewBox,
   };
 
   nsAttrValue();
   nsAttrValue(const nsAttrValue& aOther);
   explicit nsAttrValue(const nsAString& aValue);
   explicit nsAttrValue(nsIAtom* aValue);
-  nsAttrValue(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
+  nsAttrValue(already_AddRefed<mozilla::DeclarationBlock> aValue,
+              const nsAString* aSerialized);
   explicit nsAttrValue(const nsIntMargin& aValue);
   ~nsAttrValue();
 
   inline const nsAttrValue& operator=(const nsAttrValue& aOther);
 
   static nsresult Init();
   static void Shutdown();
 
@@ -145,18 +144,17 @@ public:
   void Reset();
 
   void SetTo(const nsAttrValue& aOther);
   void SetTo(const nsAString& aValue);
   void SetTo(nsIAtom* aValue);
   void SetTo(int16_t aInt);
   void SetTo(int32_t aInt, const nsAString* aSerialized);
   void SetTo(double aValue, const nsAString* aSerialized);
-  void SetTo(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
-  void SetTo(already_AddRefed<RawServoDeclarationBlock> aDeclarationBlock,
+  void SetTo(already_AddRefed<mozilla::DeclarationBlock> aValue,
              const nsAString* aSerialized);
   void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
   void SetTo(const nsIntMargin& aValue);
   void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized);
   void SetTo(const mozilla::SVGLengthList& aValue,
              const nsAString* aSerialized);
@@ -198,18 +196,17 @@ public:
   inline bool IsEmptyString() const;
   const nsCheapString GetStringValue() const;
   inline nsIAtom* GetAtomValue() const;
   inline int32_t GetIntegerValue() const;
   bool GetColorValue(nscolor& aColor) const;
   inline int16_t GetEnumValue() const;
   inline float GetPercentValue() const;
   inline AtomArray* GetAtomArrayValue() const;
-  inline mozilla::css::Declaration* GetGeckoCSSDeclarationValue() const;
-  inline RawServoDeclarationBlock* GetServoCSSDeclarationValue() const;
+  inline mozilla::DeclarationBlock* GetCSSDeclarationValue() const;
   inline mozilla::css::URLValue* GetURLValue() const;
   inline mozilla::css::ImageValue* GetImageValue() const;
   inline double GetDoubleValue() const;
   bool GetIntMarginValue(nsIntMargin& aMargin) const;
 
   /**
    * Returns the string corresponding to the stored enum value.
    *
--- a/dom/base/nsAttrValueInlines.h
+++ b/dom/base/nsAttrValueInlines.h
@@ -15,29 +15,28 @@
 struct MiscContainer;
 
 struct MiscContainer final
 {
   typedef nsAttrValue::ValueType ValueType;
 
   ValueType mType;
   // mStringBits points to either nsIAtom* or nsStringBuffer* and is used when
-  // mType isn't eGeckoCSSDeclaration.
+  // mType isn't eCSSDeclaration.
   // Note eStringBase and eAtomBase is used also to handle the type of
   // mStringBits.
   uintptr_t mStringBits;
   union {
     struct {
       union {
         int32_t mInteger;
         nscolor mColor;
         uint32_t mEnumValue;
         int32_t mPercent;
-        mozilla::css::Declaration* mGeckoCSSDeclaration;
-        RawServoDeclarationBlock* mServoCSSDeclaration;
+        mozilla::DeclarationBlock* mCSSDeclaration;
         mozilla::css::URLValue* mURL;
         mozilla::css::ImageValue* mImage;
         nsAttrValue::AtomArray* mAtomArray;
         nsIntMargin* mIntMargin;
         const nsSVGAngle* mSVGAngle;
         const nsSVGIntegerPair* mSVGIntegerPair;
         const nsSVGLength2* mSVGLength;
         const mozilla::SVGLengthList* mSVGLengthList;
@@ -82,18 +81,17 @@ protected:
 public:
   bool GetString(nsAString& aString) const;
 
   inline bool IsRefCounted() const
   {
     // Nothing stops us from refcounting (and sharing) other types of
     // MiscContainer (except eDoubleValue types) but there's no compelling
     // reason to.
-    return mType == nsAttrValue::eGeckoCSSDeclaration ||
-           mType == nsAttrValue::eServoCSSDeclaration;
+    return mType == nsAttrValue::eCSSDeclaration;
   }
 
   inline int32_t AddRef() {
     MOZ_ASSERT(IsRefCounted());
     return ++mValue.mRefCount;
   }
 
   inline int32_t Release() {
@@ -143,28 +141,21 @@ nsAttrValue::GetPercentValue() const
 
 inline nsAttrValue::AtomArray*
 nsAttrValue::GetAtomArrayValue() const
 {
   NS_PRECONDITION(Type() == eAtomArray, "wrong type");
   return GetMiscContainer()->mValue.mAtomArray;
 }
 
-inline mozilla::css::Declaration*
-nsAttrValue::GetGeckoCSSDeclarationValue() const
+inline mozilla::DeclarationBlock*
+nsAttrValue::GetCSSDeclarationValue() const
 {
-  NS_PRECONDITION(Type() == eGeckoCSSDeclaration, "wrong type");
-  return GetMiscContainer()->mValue.mGeckoCSSDeclaration;
-}
-
-inline RawServoDeclarationBlock*
-nsAttrValue::GetServoCSSDeclarationValue() const
-{
-  NS_PRECONDITION(Type() == eServoCSSDeclaration, "wrong type");
-  return GetMiscContainer()->mValue.mServoCSSDeclaration;
+  NS_PRECONDITION(Type() == eCSSDeclaration, "wrong type");
+  return GetMiscContainer()->mValue.mCSSDeclaration;
 }
 
 inline mozilla::css::URLValue*
 nsAttrValue::GetURLValue() const
 {
   NS_PRECONDITION(Type() == eURL, "wrong type");
   return GetMiscContainer()->mValue.mURL;
 }
@@ -202,19 +193,17 @@ nsAttrValue::IsSVGType(ValueType aType) 
 
 inline bool
 nsAttrValue::StoresOwnData() const
 {
   if (BaseType() != eOtherBase) {
     return true;
   }
   ValueType t = Type();
-  return t != eGeckoCSSDeclaration &&
-         t != eServoCSSDeclaration &&
-         !IsSVGType(t);
+  return t != eCSSDeclaration && !IsSVGType(t);
 }
 
 inline void
 nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
 {
   NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK),
                "pointer not properly aligned, this will crash");
   mBits = reinterpret_cast<intptr_t>(aValue) | aType;
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -9,17 +9,17 @@
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsDOMCSSAttrDeclaration.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDocument.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsContentUtils.h"
 #include "nsStyleUtil.h"
 
 using namespace mozilla;
@@ -44,17 +44,17 @@ nsStyledElement::ParseAttribute(int32_t 
     return true;
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
 nsresult
-nsStyledElement::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                            const nsAString* aSerialized,
                                            bool aNotify)
 {
   SetMayHaveStyle();
   bool modification = false;
   nsAttrValue oldValue;
 
   bool hasListeners = aNotify &&
@@ -76,38 +76,38 @@ nsStyledElement::SetInlineStyleDeclarati
     if (modification) {
       oldValue.SetTo(oldValueStr);
     }
   }
   else if (aNotify && IsInUncomposedDoc()) {
     modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   }
 
-  nsAttrValue attrValue(aDeclaration, aSerialized);
+  nsAttrValue attrValue(do_AddRef(aDeclaration), aSerialized);
 
   // XXXbz do we ever end up with ADDITION here?  I doubt it.
   uint8_t modType = modification ?
     static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
     static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
 
   return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr,
                           oldValue, attrValue, modType, hasListeners,
                           aNotify, kDontCallAfterSetAttr);
 }
 
-css::Declaration*
+DeclarationBlock*
 nsStyledElement::GetInlineStyleDeclaration()
 {
   if (!MayHaveStyle()) {
     return nullptr;
   }
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
-  if (attrVal && attrVal->Type() == nsAttrValue::eGeckoCSSDeclaration) {
-    return attrVal->GetGeckoCSSDeclarationValue();
+  if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) {
+    return attrVal->GetCSSDeclarationValue();
   }
 
   return nullptr;
 }
 
 // ---------------------------------------------------------------
 // Others and helpers
 
@@ -129,23 +129,17 @@ nsStyledElement::Style()
 
 nsresult
 nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc)
 {
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
-  
-  nsAttrValue::ValueType desiredType =
-    OwnerDoc()->GetStyleBackendType() == StyleBackendType::Gecko ?
-      nsAttrValue::eGeckoCSSDeclaration :
-      nsAttrValue::eServoCSSDeclaration;
-
-  if (oldVal && oldVal->Type() != desiredType) {
+  if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) {
     nsAttrValue attrValue;
     nsAutoString stringValue;
     oldVal->ToString(stringValue);
     ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
     // Don't bother going through SetInlineStyleDeclaration; we don't
     // want to fire off mutation events or document notifications anyway
     nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsStyledElement.h
+++ b/dom/base/nsStyledElement.h
@@ -13,19 +13,17 @@
 #ifndef __NS_STYLEDELEMENT_H_
 #define __NS_STYLEDELEMENT_H_
 
 #include "mozilla/Attributes.h"
 #include "nsString.h"
 #include "mozilla/dom/Element.h"
 
 namespace mozilla {
-namespace css {
-class Declaration;
-} // namespace css
+class DeclarationBlock;
 } // namespace mozilla
 
 // IID for nsStyledElement interface
 #define NS_STYLED_ELEMENT_IID \
 { 0xacbd9ea6, 0x15aa, 0x4f37, \
  { 0x8c, 0xe0, 0x35, 0x1e, 0xd7, 0x21, 0xca, 0xe9 } }
 
 typedef mozilla::dom::Element nsStyledElementBase;
@@ -41,18 +39,18 @@ protected:
 
 public:
   // We don't want to implement AddRef/Release because that would add an extra
   // function call for those on pretty much all elements.  But we do need QI, so
   // we can QI to nsStyledElement.
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   // Element interface methods
-  virtual mozilla::css::Declaration* GetInlineStyleDeclaration() override;
-  virtual nsresult SetInlineStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+  virtual mozilla::DeclarationBlock* GetInlineStyleDeclaration() override;
+  virtual nsresult SetInlineStyleDeclaration(mozilla::DeclarationBlock* aDeclaration,
                                              const nsAString* aSerialized,
                                              bool aNotify) override;
 
   nsICSSDeclaration* Style();
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_STYLED_ELEMENT_IID)
 
 protected:
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Likely.h"
 
 #include "nscore.h"
@@ -183,22 +184,28 @@ nsGenericHTMLElement::CopyInnerTo(Elemen
   for (i = 0; i < count; ++i) {
     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
 
     nsAutoString valStr;
     value->ToString(valStr);
 
     if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
-        value->Type() == nsAttrValue::eGeckoCSSDeclaration) {
+        value->Type() == nsAttrValue::eCSSDeclaration) {
+      DeclarationBlock* decl = value->GetCSSDeclarationValue();
+      if (decl->IsServo()) {
+        MOZ_CRASH("stylo: clone not implemented");
+        continue;
+      }
+
       // We can't just set this as a string, because that will fail
       // to reparse the string into style data until the node is
       // inserted into the document.  Clone the Rule instead.
-      RefPtr<css::Declaration> declClone =
-        new css::Declaration(*value->GetGeckoCSSDeclarationValue());
+      RefPtr<css::Declaration>
+        declClone = new css::Declaration(*decl->AsGecko());
 
       rv = aDst->SetInlineStyleDeclaration(declClone, &valStr, false);
       NS_ENSURE_SUCCESS(rv, rv);
 
       continue;
     }
 
     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -253,17 +253,17 @@ nsSVGElement::BindToTree(nsIDocument* aD
                                              aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
-  if (oldVal && oldVal->Type() == nsAttrValue::eGeckoCSSDeclaration) {
+  if (oldVal && oldVal->Type() == nsAttrValue::eCSSDeclaration) {
     // we need to force a reparse because the baseURI of the document
     // may have changed, and in particular because we may be clones of
     // XBL anonymous content now being bound to the document we should
     // render in and due to the hacky way in which we implement the
     // interaction of XBL and SVG resources.  Once we have a sane
     // ownerDocument on XBL anonymous content, this can all go away.
     nsAttrValue attrValue;
     nsAutoString stringValue;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -33,16 +33,17 @@
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIDocument.h"
 #include "nsLayoutStylesheetCache.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsFocusManager.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsNameSpaceManager.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "nsIRDFCompositeDataSource.h"
@@ -369,24 +370,25 @@ nsXULElement::Clone(mozilla::dom::NodeIn
     uint32_t count = mAttrsAndChildren.AttrCount();
     nsresult rv = NS_OK;
     for (uint32_t i = 0; i < count; ++i) {
         const nsAttrName* originalName = mAttrsAndChildren.AttrNameAt(i);
         const nsAttrValue* originalValue = mAttrsAndChildren.AttrAt(i);
         nsAttrValue attrValue;
 
         // Style rules need to be cloned.
-        if (originalValue->Type() == nsAttrValue::eGeckoCSSDeclaration) {
-            RefPtr<css::Declaration> declClone = new css::Declaration(
-                *originalValue->GetGeckoCSSDeclarationValue());
+        if (originalValue->Type() == nsAttrValue::eCSSDeclaration) {
+            DeclarationBlock* decl = originalValue->GetCSSDeclarationValue();
+            RefPtr<css::Declaration>
+              declClone = new css::Declaration(*decl->AsGecko());
 
             nsString stringValue;
             originalValue->ToString(stringValue);
 
-            attrValue.SetTo(declClone, &stringValue);
+            attrValue.SetTo(declClone.forget(), &stringValue);
         } else {
             attrValue.SetTo(*originalValue);
         }
 
         if (originalName->IsAtom()) {
            rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
                                                           attrValue);
         } else {
@@ -1855,24 +1857,25 @@ nsXULElement::MakeHeavyweight(nsXULProto
 
     uint32_t i;
     nsresult rv;
     for (i = 0; i < aPrototype->mNumAttributes; ++i) {
         nsXULPrototypeAttribute* protoattr = &aPrototype->mAttributes[i];
         nsAttrValue attrValue;
 
         // Style rules need to be cloned.
-        if (protoattr->mValue.Type() == nsAttrValue::eGeckoCSSDeclaration) {
-            RefPtr<css::Declaration> declClone = new css::Declaration(
-              *protoattr->mValue.GetGeckoCSSDeclarationValue());
+        if (protoattr->mValue.Type() == nsAttrValue::eCSSDeclaration) {
+            DeclarationBlock* decl = protoattr->mValue.GetCSSDeclarationValue();
+            RefPtr<css::Declaration>
+              declClone = new css::Declaration(*decl->AsGecko());
 
             nsString stringValue;
             protoattr->mValue.ToString(stringValue);
 
-            attrValue.SetTo(declClone, &stringValue);
+            attrValue.SetTo(declClone.forget(), &stringValue);
         } else {
             attrValue.SetTo(protoattr->mValue);
         }
 
         // XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
         if (protoattr->mName.IsAtom()) {
             rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue);
         } else {
@@ -2445,17 +2448,17 @@ nsXULPrototypeElement::SetAttrAt(uint32_
         // inline styles are allowed to be applied.
         RefPtr<css::Declaration> declaration =
           parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
                                      // This is basically duplicating what
                                      // nsINode::NodePrincipal() does
                                      mNodeInfo->NodeInfoManager()->
                                        DocumentPrincipal());
         if (declaration) {
-            mAttributes[aPos].mValue.SetTo(declaration, &aValue);
+            mAttributes[aPos].mValue.SetTo(declaration.forget(), &aValue);
 
             return NS_OK;
         }
         // Don't abort if parsing failed, it could just be malformed css.
     }
 
     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
 
--- a/editor/libeditor/CSSEditUtils.cpp
+++ b/editor/libeditor/CSSEditUtils.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/CSSEditUtils.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/ChangeStyleTransaction.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
 #include "nsComputedDOMStyle.h"
 #include "nsDebug.h"
@@ -539,25 +539,29 @@ CSSEditUtils::GetCSSInlinePropertyBase(n
     // from these declarations, get the one we want and that one only
     MOZ_ALWAYS_SUCCEEDS(
       cssDecl->GetPropertyValue(nsDependentAtomString(aProperty), aValue));
 
     return NS_OK;
   }
 
   MOZ_ASSERT(aStyleType == eSpecified);
-  RefPtr<css::Declaration> decl = element->GetInlineStyleDeclaration();
+  RefPtr<DeclarationBlock> decl = element->GetInlineStyleDeclaration();
   if (!decl) {
     return NS_OK;
   }
+  if (decl->IsServo()) {
+    MOZ_CRASH("stylo: not implemented");
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
   nsCSSPropertyID prop =
     nsCSSProps::LookupProperty(nsDependentAtomString(aProperty),
                                CSSEnabledState::eForAllContent);
   MOZ_ASSERT(prop != eCSSProperty_UNKNOWN);
-  decl->GetValue(prop, aValue);
+  decl->AsGecko()->GetValue(prop, aValue);
 
   return NS_OK;
 }
 
 already_AddRefed<nsComputedDOMStyle>
 CSSEditUtils::GetComputedStyle(Element* aElement)
 {
   MOZ_ASSERT(aElement);
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -24,16 +24,17 @@
 #include "nsString.h"
 #include "nsStyleStruct.h"
 #include "nsStyleUtil.h"
 #include "nsTArray.h"
 
 #include "mozilla/EventStates.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define IMPL_STRONG_REF_TYPE_FOR(type_) \
   already_AddRefed<type_>               \
   type_##Strong::Consume() {            \
@@ -311,20 +312,24 @@ Gecko_StoreStyleDifference(RawGeckoNodeB
             "non-stylo build");
 #endif
 }
 
 RawServoDeclarationBlock*
 Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
 {
   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::style);
-  if (!attr || attr->Type() != nsAttrValue::eServoCSSDeclaration) {
+  if (!attr || attr->Type() != nsAttrValue::eCSSDeclaration) {
     return nullptr;
   }
-  return attr->GetServoCSSDeclarationValue();
+  DeclarationBlock* decl = attr->GetCSSDeclarationValue();
+  if (!decl || decl->IsGecko()) {
+    return nullptr;
+  }
+  return decl->AsServo()->Raw();
 }
 
 void
 Gecko_FillAllBackgroundLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
 {
   nsRuleNode::FillAllBackgroundLists(*aLayers, aMaxLen);
 }
 
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -87,20 +87,22 @@ nsDOMCSSAttributeDeclaration::DocToUpdat
 
 css::Declaration*
 nsDOMCSSAttributeDeclaration::GetCSSDeclaration(Operation aOperation)
 {
   if (!mElement)
     return nullptr;
 
   css::Declaration* declaration;
-  if (mIsSMILOverride)
+  if (mIsSMILOverride) {
     declaration = mElement->GetSMILOverrideStyleDeclaration();
-  else
-    declaration = mElement->GetInlineStyleDeclaration();
+  } else {
+    DeclarationBlock* decl = mElement->GetInlineStyleDeclaration();
+    declaration = decl && decl->IsGecko() ? decl->AsGecko() : nullptr;
+  }
 
   // Notify observers that our style="" attribute is going to change
   // unless:
   //   * this is a declaration that holds SMIL animation values (which
   //     aren't reflected in the DOM style="" attribute), or
   //   * we're getting the declaration for reading, or
   //   * we're getting it for property removal but we don't currently have
   //     a declaration.
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -5,17 +5,17 @@
 
 /* base class for DOM objects for element.style and cssStyleRule.style */
 
 #include "nsDOMCSSDeclaration.h"
 
 #include "nsCSSParser.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Rule.h"
-#include "mozilla/css/Declaration.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/CSS2PropertiesBinding.h"
 #include "nsCSSProps.h"
 #include "nsCOMPtr.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIURI.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsContentUtils.h"
 #include "nsQueryObject.h"
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -6,16 +6,17 @@
 
 /*
  * style sheet and style rule processor representing style attributes
  */
 
 #include "nsHTMLCSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/css/StyleRule.h"
+#include "mozilla/DeclarationBlockInlines.h"
 #include "nsIStyleRuleProcessor.h"
 #include "nsPresContext.h"
 #include "nsRuleWalker.h"
 #include "nsRuleProcessorData.h"
 #include "mozilla/dom/Element.h"
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsCSSPseudoElements.h"
@@ -33,31 +34,21 @@ nsHTMLCSSStyleSheet::~nsHTMLCSSStyleShee
 {
   // We may go away before all of our cached style attributes do,
   // so clean up any that are left.
   for (auto iter = mCachedStyleAttrs.Iter(); !iter.Done(); iter.Next()) {
     MiscContainer*& value = iter.Data();
 
     // Ideally we'd just call MiscContainer::Evict, but we can't do that since
     // we're iterating the hashtable.
-    switch (value->mType) {
-      case nsAttrValue::eGeckoCSSDeclaration: {
-        css::Declaration* declaration = value->mValue.mGeckoCSSDeclaration;
-        declaration->SetHTMLCSSStyleSheet(nullptr);
-        break;
-      }
-      case nsAttrValue::eServoCSSDeclaration: {
-        RawServoDeclarationBlock* declarations =
-          value->mValue.mServoCSSDeclaration;
-        Servo_DeclarationBlock_ClearCachePointer(declarations);
-        break;
-      }
-      default:
-        MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
-        break;
+    if (value->mType == nsAttrValue::eCSSDeclaration) {
+      DeclarationBlock* declaration = value->mValue.mCSSDeclaration;
+      declaration->SetHTMLCSSStyleSheet(nullptr);
+    } else {
+      MOZ_ASSERT_UNREACHABLE("unexpected cached nsAttrValue type");
     }
 
     value->mValue.mCached = 0;
     iter.Remove();
   }
 }
 
 NS_IMPL_ISUPPORTS(nsHTMLCSSStyleSheet, nsIStyleRuleProcessor)
@@ -70,23 +61,22 @@ nsHTMLCSSStyleSheet::RulesMatching(Eleme
 }
 
 void
 nsHTMLCSSStyleSheet::ElementRulesMatching(nsPresContext* aPresContext,
                                           Element* aElement,
                                           nsRuleWalker* aRuleWalker)
 {
   // just get the one and only style rule from the content's STYLE attribute
-  css::Declaration* declaration = aElement->GetInlineStyleDeclaration();
-  if (declaration) {
+  if (DeclarationBlock* declaration = aElement->GetInlineStyleDeclaration()) {
     declaration->SetImmutable();
-    aRuleWalker->Forward(declaration);
+    aRuleWalker->Forward(declaration->AsGecko());
   }
 
-  declaration = aElement->GetSMILOverrideStyleDeclaration();
+  css::Declaration* declaration = aElement->GetSMILOverrideStyleDeclaration();
   if (declaration) {
     MOZ_ASSERT(aPresContext->RestyleManager()->IsGecko(),
                "stylo: ElementRulesMatching must not be called when we have "
                "a Servo-backed style system");
     RestyleManager* restyleManager = aPresContext->RestyleManager()->AsGecko();
     if (!restyleManager->SkipAnimationRules()) {
       // Animation restyle (or non-restyle traversal of rules)
       // Now we can walk SMIL overrride style, without triggering transitions.
@@ -102,20 +92,20 @@ nsHTMLCSSStyleSheet::PseudoElementRulesM
                                                   aPseudoType,
                                                 nsRuleWalker* aRuleWalker)
 {
   MOZ_ASSERT(nsCSSPseudoElements::
                PseudoElementSupportsStyleAttribute(aPseudoType));
   MOZ_ASSERT(aPseudoElement);
 
   // just get the one and only style rule from the content's STYLE attribute
-  css::Declaration* declaration = aPseudoElement->GetInlineStyleDeclaration();
+  DeclarationBlock* declaration = aPseudoElement->GetInlineStyleDeclaration();
   if (declaration) {
     declaration->SetImmutable();
-    aRuleWalker->Forward(declaration);
+    aRuleWalker->Forward(declaration->AsGecko());
   }
 }
 
 /* virtual */ void
 nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
 {
   if (nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aData->mPseudoType) &&
       aData->mPseudoElement) {