Bug 1221436 patch 2 - For style attributes, only store a css::Declaration instead of a css::StyleRule. r=heycam
authorL. David Baron <dbaron@dbaron.org>
Mon, 09 Nov 2015 15:57:16 +0800
changeset 271737 84c5d7320a5ccc49dff580d78486d29443e25259
parent 271736 2894f200ed038736e06851432e01fbb1e3311bce
child 271738 2638966229a846861165805fe550fa332398d895
push id29650
push usercbook@mozilla.com
push dateMon, 09 Nov 2015 13:56:12 +0000
treeherdermozilla-central@e1ef2be156de [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1221436
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1221436 patch 2 - For style attributes, only store a css::Declaration instead of a css::StyleRule. r=heycam Now that Declaration implements nsIStyleRule, we don't need the memory overhead of storing a StyleRule object for style attributes. We also need to change this prior to patch 5, because the changes in patch 5 that will allow rules to change (but declarations not) would otherwise break due to style attribute object merging done by nsAttrValue::ParseStyleAttribute.
dom/base/Element.cpp
dom/base/Element.h
dom/base/FragmentOrElement.cpp
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/base/nsTreeSanitizer.cpp
dom/base/nsTreeSanitizer.h
dom/canvas/CanvasRenderingContext2D.cpp
dom/html/nsGenericHTMLElement.cpp
dom/smil/nsSMILAnimationController.cpp
dom/svg/nsSVGElement.cpp
dom/xul/nsXULElement.cpp
editor/libeditor/nsHTMLCSSUtils.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSParser.h
layout/style/nsDOMCSSAttrDeclaration.cpp
layout/style/nsHTMLCSSStyleSheet.cpp
layout/style/nsHTMLCSSStyleSheet.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1871,30 +1871,30 @@ Element::GetSMILOverrideStyle()
 
   if (!slots->mSMILOverrideStyle) {
     slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
   }
 
   return slots->mSMILOverrideStyle;
 }
 
-css::StyleRule*
-Element::GetSMILOverrideStyleRule()
+css::Declaration*
+Element::GetSMILOverrideStyleDeclaration()
 {
   Element::nsDOMSlots *slots = GetExistingDOMSlots();
-  return slots ? slots->mSMILOverrideStyleRule.get() : nullptr;
+  return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
 }
 
 nsresult
-Element::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
-                                           bool aNotify)
+Element::SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
+                                         bool aNotify)
 {
   Element::nsDOMSlots *slots = DOMSlots();
 
-  slots->mSMILOverrideStyleRule = aStyleRule;
+  slots->mSMILOverrideStyleDeclaration = aDeclaration;
 
   if (aNotify) {
     nsIDocument* doc = GetComposedDoc();
     // Only need to request a restyle if we're in a document.  (We might not
     // be in a document, if we're clearing animation effects on a target node
     // that's been detached since the previous animation sample.)
     if (doc) {
       nsCOMPtr<nsIPresShell> shell = doc->GetShell();
@@ -1919,28 +1919,28 @@ Element::IsLabelable() const
 }
 
 bool
 Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
 {
   return false;
 }
 
-css::StyleRule*
-Element::GetInlineStyleRule()
+css::Declaration*
+Element::GetInlineStyleDeclaration()
 {
   return nullptr;
 }
 
 nsresult
-Element::SetInlineStyleRule(css::StyleRule* aStyleRule,
-                            const nsAString* aSerialized,
-                            bool aNotify)
+Element::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+                                   const nsAString* aSerialized,
+                                   bool aNotify)
 {
-  NS_NOTYETIMPLEMENTED("Element::SetInlineStyleRule");
+  NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP_(bool)
 Element::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   return false;
 }
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -217,41 +217,41 @@ public:
   void UnlockStyleStates(EventStates aStates);
 
   /**
    * Clear all style state locks on this element.
    */
   void ClearStyleStateLocks();
 
   /**
-   * Get the inline style rule, if any, for this element.
+   * Get the inline style declaration, if any, for this element.
    */
-  virtual css::StyleRule* GetInlineStyleRule();
+  virtual css::Declaration* GetInlineStyleDeclaration();
 
   /**
-   * Set the inline style rule for this element. This will send an appropriate
-   * AttributeChanged notification if aNotify is true.
+   * Set the inline style declaration for this element. This will send
+   * an appropriate AttributeChanged notification if aNotify is true.
    */
-  virtual nsresult SetInlineStyleRule(css::StyleRule* aStyleRule,
-                                      const nsAString* aSerialized,
-                                      bool aNotify);
+  virtual nsresult SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+                                             const nsAString* aSerialized,
+                                             bool aNotify);
 
   /**
-   * Get the SMIL override style rule for this element. If the rule hasn't been
-   * created, this method simply returns null.
+   * Get the SMIL override style declaration for this element. If the
+   * rule hasn't been created, this method simply returns null.
    */
-  virtual css::StyleRule* GetSMILOverrideStyleRule();
+  virtual css::Declaration* GetSMILOverrideStyleDeclaration();
 
   /**
-   * Set the SMIL override style rule for this element. If aNotify is true, this
-   * method will notify the document's pres context, so that the style changes
-   * will be noticed.
+   * Set the SMIL override style declaration for this element. If
+   * aNotify is true, this method will notify the document's pres
+   * context, so that the style changes will be noticed.
    */
-  virtual nsresult SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
-                                            bool aNotify);
+  virtual nsresult SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
+                                                   bool aNotify);
 
   /**
    * Returns a new nsISMILAttr that allows the caller to animate the given
    * attribute on this element.
    *
    * The CALLER OWNS the result and is responsible for deleting it.
    */
   virtual nsISMILAttr* GetAnimatedAttr(int32_t aNamespaceID, nsIAtom* aName)
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -609,17 +609,17 @@ FragmentOrElement::nsDOMSlots::SizeOfInc
   }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - Superclass members (nsINode::nsSlots)
   // - mStyle
   // - mDataSet
   // - mSMILOverrideStyle
-  // - mSMILOverrideStyleRule
+  // - mSMILOverrideStyleDeclaration
   // - mChildrenList
   // - mClassList
 
   // The following members are not measured:
   // - mBindingParent / mControllers: because they're   non-owning
   return n;
 }
 
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -281,19 +281,19 @@ public:
 
     /**
      * SMIL Overridde style rules (for SMIL animation of CSS properties)
      * @see nsIContent::GetSMILOverrideStyle
      */
     nsCOMPtr<nsICSSDeclaration> mSMILOverrideStyle;
 
     /**
-     * Holds any SMIL override style rules for this element.
+     * Holds any SMIL override style declaration for this element.
      */
-    RefPtr<mozilla::css::StyleRule> mSMILOverrideStyleRule;
+    RefPtr<mozilla::css::Declaration> mSMILOverrideStyleDeclaration;
 
     /**
      * An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
      * @see FragmentOrElement::GetAttributes
      */
     RefPtr<nsDOMAttributeMap> mAttributeMap;
 
     union {
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -12,17 +12,16 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/HashFunctions.h"
 
 #include "nsAttrValue.h"
 #include "nsAttrValueInlines.h"
 #include "nsIAtom.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/MemoryReporting.h"
-#include "mozilla/css/StyleRule.h"
 #include "mozilla/css/Declaration.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "prprf.h"
 #include "nsHTMLCSSStyleSheet.h"
 #include "nsCSSParser.h"
 #include "nsStyledElement.h"
 #include "nsIURI.h"
@@ -68,57 +67,54 @@ MiscContainer::GetString(nsAString& aStr
   atom->ToString(aString);
   return true;
 }
 
 void
 MiscContainer::Cache()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule);
+  MOZ_ASSERT(mType == nsAttrValue::eCSSDeclaration);
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount > 0);
   MOZ_ASSERT(!mValue.mCached);
 
-  css::StyleRule* rule = mValue.mCSSStyleRule;
-  nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet();
+  css::Declaration* declaration = mValue.mCSSDeclaration;
+  nsHTMLCSSStyleSheet* sheet = declaration->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.
-  css::Declaration* decl = rule->GetDeclaration();
-  if (decl) {
-    decl->SetImmutable();
-  }
+  declaration->SetImmutable();
 }
 
 void
 MiscContainer::Evict()
 {
   // Not implemented for anything else yet.
-  MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule);
+  MOZ_ASSERT(mType == nsAttrValue::eCSSDeclaration);
   MOZ_ASSERT(IsRefCounted());
   MOZ_ASSERT(mValue.mRefCount == 0);
 
   if (!mValue.mCached) {
     return;
   }
 
-  css::StyleRule* rule = mValue.mCSSStyleRule;
-  nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet();
+  css::Declaration* declaration = mValue.mCSSDeclaration;
+  nsHTMLCSSStyleSheet* sheet = declaration->GetHTMLCSSStyleSheet();
   MOZ_ASSERT(sheet);
 
   nsString str;
   DebugOnly<bool> gotString = GetString(str);
   MOZ_ASSERT(gotString);
 
   sheet->EvictStyleAttr(str, this);
   mValue.mCached = 0;
@@ -144,17 +140,17 @@ nsAttrValue::nsAttrValue(const nsAString
 }
 
 nsAttrValue::nsAttrValue(nsIAtom* aValue)
     : mBits(0)
 {
   SetTo(aValue);
 }
 
-nsAttrValue::nsAttrValue(css::StyleRule* aValue, const nsAString* aSerialized)
+nsAttrValue::nsAttrValue(css::Declaration* aValue, const nsAString* aSerialized)
     : mBits(0)
 {
   SetTo(aValue, aSerialized);
 }
 
 nsAttrValue::nsAttrValue(const nsIntMargin& aValue)
     : mBits(0)
 {
@@ -309,17 +305,17 @@ nsAttrValue::SetTo(const nsAttrValue& aO
       cont->mValue.mPercent = otherCont->mValue.mPercent;
       break;
     }
     case eColor:
     {
       cont->mValue.mColor = otherCont->mValue.mColor;
       break;
     }
-    case eCSSStyleRule:
+    case eCSSDeclaration:
     {
       MOZ_CRASH("These should be refcounted!");
     }
     case eURL:
     {
       NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
       break;
     }
@@ -416,22 +412,22 @@ nsAttrValue::SetTo(double aValue, const 
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mDoubleValue = aValue;
   cont->mType = eDoubleValue;
   SetMiscAtomOrString(aSerialized);
 }
 
 void
-nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized)
+nsAttrValue::SetTo(css::Declaration* aValue, const nsAString* aSerialized)
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   MOZ_ASSERT(cont->mValue.mRefCount == 0);
-  NS_ADDREF(cont->mValue.mCSSStyleRule = aValue);
-  cont->mType = eCSSStyleRule;
+  NS_ADDREF(cont->mValue.mCSSDeclaration = aValue);
+  cont->mType = eCSSDeclaration;
   NS_ADDREF(cont);
   SetMiscAtomOrString(aSerialized);
   MOZ_ASSERT(cont->mValue.mRefCount == 1);
 }
 
 void
 nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
 {
@@ -634,22 +630,21 @@ nsAttrValue::ToString(nsAString& aResult
     case ePercent:
     {
       nsAutoString intStr;
       intStr.AppendInt(cont ? cont->mValue.mPercent : GetIntInternal());
       aResult = intStr + NS_LITERAL_STRING("%");
 
       break;
     }
-    case eCSSStyleRule:
+    case eCSSDeclaration:
     {
       aResult.Truncate();
       MiscContainer *container = GetMiscContainer();
-      css::Declaration *decl =
-        container->mValue.mCSSStyleRule->GetDeclaration();
+      css::Declaration *decl = container->mValue.mCSSDeclaration;
       if (decl) {
         decl->ToString(aResult);
       }
       const_cast<nsAttrValue*>(this)->SetMiscAtomOrString(&aResult);
 
       break;
     }
     case eDoubleValue:
@@ -884,19 +879,19 @@ nsAttrValue::HashValue() const
     case ePercent:
     {
       return cont->mValue.mPercent;
     }
     case eColor:
     {
       return cont->mValue.mColor;
     }
-    case eCSSStyleRule:
+    case eCSSDeclaration:
     {
-      return NS_PTR_TO_INT32(cont->mValue.mCSSStyleRule);
+      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);
@@ -993,19 +988,20 @@ nsAttrValue::Equals(const nsAttrValue& a
     }
     case eColor:
     {
       if (thisCont->mValue.mColor == otherCont->mValue.mColor) {
         needsStringComparison = true;
       }
       break;
     }
-    case eCSSStyleRule:
+    case eCSSDeclaration:
     {
-      return thisCont->mValue.mCSSStyleRule == otherCont->mValue.mCSSStyleRule;
+      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;
@@ -1685,24 +1681,22 @@ nsAttrValue::ParseStyleAttribute(const n
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
   css::Loader* cssLoader = ownerDoc->CSSLoader();
   nsCSSParser cssParser(cssLoader);
 
-  RefPtr<css::StyleRule> rule;
-  cssParser.ParseStyleAttribute(aString, docURI, baseURI,
-                                aElement->NodePrincipal(),
-                                getter_AddRefs(rule));
-  if (rule) {
-    rule->SetHTMLCSSStyleSheet(sheet);
-    rule->GetDeclaration()->SetHTMLCSSStyleSheet(sheet);
-    SetTo(rule, &aString);
+  RefPtr<css::Declaration> declaration =
+    cssParser.ParseStyleAttribute(aString, docURI, baseURI,
+                                  aElement->NodePrincipal());
+  if (declaration) {
+    declaration->SetHTMLCSSStyleSheet(sheet);
+    SetTo(declaration, &aString);
     if (cachingAllowed) {
       MiscContainer* cont = GetMiscContainer();
       cont->Cache();
     }
 
     return true;
   }
 
@@ -1712,23 +1706,23 @@ 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 eCSSStyleRule attributes to store empty strings as it
+    // * 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() == eCSSStyleRule || 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_NewAtom(*aValue);
       if (atom) {
         cont->mStringBits =
           reinterpret_cast<uintptr_t>(atom.forget().take()) | eAtomBase;
       }
@@ -1782,22 +1776,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 eCSSStyleRule:
+        case eCSSDeclaration:
         {
           MOZ_ASSERT(cont->mValue.mRefCount == 1);
           cont->Release();
           cont->Evict();
-          NS_RELEASE(cont->mValue.mCSSStyleRule);
+          NS_RELEASE(cont->mValue.mCSSDeclaration);
           break;
         }
         case eURL:
         {
           NS_RELEASE(cont->mValue.mURL);
           break;
         }
         case eImage:
@@ -1923,20 +1917,20 @@ 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() == eCSSStyleRule && container->mValue.mCSSStyleRule) {
-        // TODO: mCSSStyleRule might be owned by another object which would
+      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->mCSSStyleRule->SizeOfIncludingThis(aMallocSizeOf);
+        //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,17 +30,17 @@
 
 class nsAString;
 class nsIDocument;
 class nsStyledElementNotElementCSSInlineStyle;
 struct MiscContainer;
 
 namespace mozilla {
 namespace css {
-class StyleRule;
+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))
@@ -89,17 +89,17 @@ public:
                           //   01  this value indicates an '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.
-    eCSSStyleRule =            0x10
+    eCSSDeclaration =          0x10
     ,eURL =                    0x11
     ,eImage =                  0x12
     ,eAtomArray =              0x13
     ,eDoubleValue  =           0x14
     ,eIntMarginValue =         0x15
     ,eSVGAngle =               0x16
     ,eSVGTypesBegin =          eSVGAngle
     ,eSVGIntegerPair =         0x17
@@ -115,17 +115,17 @@ public:
     ,eSVGViewBox =             0x21
     ,eSVGTypesEnd =            eSVGViewBox
   };
 
   nsAttrValue();
   nsAttrValue(const nsAttrValue& aOther);
   explicit nsAttrValue(const nsAString& aValue);
   explicit nsAttrValue(nsIAtom* aValue);
-  nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
+  nsAttrValue(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
   explicit nsAttrValue(const nsIntMargin& aValue);
   ~nsAttrValue();
 
   inline const nsAttrValue& operator=(const nsAttrValue& aOther);
 
   static nsresult Init();
   static void Shutdown();
 
@@ -140,17 +140,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::StyleRule* aValue, const nsAString* aSerialized);
+  void SetTo(mozilla::css::Declaration* 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);
   void SetTo(const mozilla::SVGNumberList& aValue,
@@ -191,17 +191,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::StyleRule* GetCSSStyleRuleValue() const;
+  inline mozilla::css::Declaration* 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,28 +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 mCSSStyleRule.
+  // 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::StyleRule* mCSSStyleRule;
+        mozilla::css::Declaration* 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;
@@ -81,17 +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::eCSSStyleRule;
+    return mType == nsAttrValue::eCSSDeclaration;
   }
 
   inline int32_t AddRef() {
     MOZ_ASSERT(IsRefCounted());
     return ++mValue.mRefCount;
   }
 
   inline int32_t Release() {
@@ -141,21 +141,21 @@ nsAttrValue::GetPercentValue() const
 
 inline nsAttrValue::AtomArray*
 nsAttrValue::GetAtomArrayValue() const
 {
   NS_PRECONDITION(Type() == eAtomArray, "wrong type");
   return GetMiscContainer()->mValue.mAtomArray;
 }
 
-inline mozilla::css::StyleRule*
-nsAttrValue::GetCSSStyleRuleValue() const
+inline mozilla::css::Declaration*
+nsAttrValue::GetCSSDeclarationValue() const
 {
-  NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type");
-  return GetMiscContainer()->mValue.mCSSStyleRule;
+  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;
 }
@@ -193,17 +193,17 @@ nsAttrValue::IsSVGType(ValueType aType) 
 
 inline bool
 nsAttrValue::StoresOwnData() const
 {
   if (BaseType() != eOtherBase) {
     return true;
   }
   ValueType t = Type();
-  return t != eCSSStyleRule && !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/StyleRule.h"
+#include "mozilla/css/Declaration.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsContentUtils.h"
 #include "nsStyleUtil.h"
 
 using namespace mozilla;
@@ -40,19 +40,19 @@ nsStyledElementNotElementCSSInlineStyle:
     return true;
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
 nsresult
-nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule,
-                                                            const nsAString* aSerialized,
-                                                            bool aNotify)
+nsStyledElementNotElementCSSInlineStyle::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
+                                                                   const nsAString* aSerialized,
+                                                                   bool aNotify)
 {
   SetMayHaveStyle();
   bool modification = false;
   nsAttrValue oldValue;
 
   bool hasListeners = aNotify &&
     nsContentUtils::HasMutationListeners(this,
                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
@@ -72,38 +72,38 @@ nsStyledElementNotElementCSSInlineStyle:
     if (modification) {
       oldValue.SetTo(oldValueStr);
     }
   }
   else if (aNotify && IsInDoc()) {
     modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   }
 
-  nsAttrValue attrValue(aStyleRule, aSerialized);
+  nsAttrValue attrValue(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::StyleRule*
-nsStyledElementNotElementCSSInlineStyle::GetInlineStyleRule()
+css::Declaration*
+nsStyledElementNotElementCSSInlineStyle::GetInlineStyleDeclaration()
 {
   if (!MayHaveStyle()) {
     return nullptr;
   }
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
 
-  if (attrVal && attrVal->Type() == nsAttrValue::eCSSStyleRule) {
-    return attrVal->GetCSSStyleRuleValue();
+  if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) {
+    return attrVal->GetCSSDeclarationValue();
   }
 
   return nullptr;
 }
 
 // ---------------------------------------------------------------
 // Others and helpers
 
@@ -126,23 +126,23 @@ nsStyledElementNotElementCSSInlineStyle:
 nsresult
 nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(bool aForceInDataDoc)
 {
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   
-  if (oldVal && oldVal->Type() != nsAttrValue::eCSSStyleRule) {
+  if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) {
     nsAttrValue attrValue;
     nsAutoString stringValue;
     oldVal->ToString(stringValue);
     ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
-    // Don't bother going through SetInlineStyleRule, we don't want to fire off
-    // mutation events or document notifications anyway
+    // 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);
   }
   
   return NS_OK;
 }
 
 void
--- a/dom/base/nsStyledElement.h
+++ b/dom/base/nsStyledElement.h
@@ -14,37 +14,37 @@
 #define __NS_STYLEDELEMENT_H_
 
 #include "mozilla/Attributes.h"
 #include "nsString.h"
 #include "mozilla/dom/Element.h"
 
 namespace mozilla {
 namespace css {
-class StyleRule;
+class Declaration;
 } // namespace css
 } // namespace mozilla
 
 typedef mozilla::dom::Element nsStyledElementBase;
 
 class nsStyledElementNotElementCSSInlineStyle : public nsStyledElementBase
 {
 
 protected:
 
   inline explicit nsStyledElementNotElementCSSInlineStyle(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsStyledElementBase(aNodeInfo)
   {}
 
 public:
-  // nsIContent interface methods
-  virtual mozilla::css::StyleRule* GetInlineStyleRule() override;
-  virtual nsresult SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
-                                      const nsAString* aSerialized,
-                                      bool aNotify) override;
+  // Element interface methods
+  virtual mozilla::css::Declaration* GetInlineStyleDeclaration() override;
+  virtual nsresult SetInlineStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+                                             const nsAString* aSerialized,
+                                             bool aNotify) override;
 
   nsICSSDeclaration* Style();
 
 protected:
 
   /**
    * Parse a style attr value into a CSS rulestruct (or, if there is no
    * document, leave it as a string) and return as nsAttrValue.
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1061,27 +1061,22 @@ nsTreeSanitizer::MustPrune(int32_t aName
   }
   if (nsGkAtoms::style == aLocal) {
     return true;
   }
   return false;
 }
 
 bool
-nsTreeSanitizer::SanitizeStyleRule(mozilla::css::StyleRule *aRule,
-                                   nsAutoString &aRuleText)
+nsTreeSanitizer::SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+                                          nsAutoString& aRuleText)
 {
-  bool didSanitize = false;
-  aRuleText.Truncate();
-  mozilla::css::Declaration* style = aRule->GetDeclaration();
-  if (style) {
-    didSanitize = style->HasProperty(eCSSProperty_binding);
-    style->RemoveProperty(eCSSProperty_binding);
-    style->ToString(aRuleText);
-  }
+  bool didSanitize = aDeclaration->HasProperty(eCSSProperty_binding);
+  aDeclaration->RemoveProperty(eCSSProperty_binding);
+  aDeclaration->ToString(aRuleText);
   return didSanitize;
 }
 
 bool
 nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
                                     nsAString& aSanitized,
                                     nsIDocument* aDocument,
                                     nsIURI* aBaseURI)
@@ -1130,17 +1125,18 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
         break;
       }
       case mozilla::css::Rule::STYLE_RULE: {
         // For style rules, we will just look for and remove the
         // -moz-binding properties.
         RefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
         NS_ASSERTION(styleRule, "Must be a style rule");
         nsAutoString decl;
-        bool sanitized = SanitizeStyleRule(styleRule, decl);
+        bool sanitized =
+          SanitizeStyleDeclaration(styleRule->GetDeclaration(), decl);
         didSanitize = sanitized || didSanitize;
         if (!sanitized) {
           styleRule->GetCssText(decl);
         }
         aSanitized.Append(decl);
       }
     }
   }
@@ -1152,42 +1148,36 @@ nsTreeSanitizer::SanitizeAttributes(mozi
                                     nsTHashtable<nsISupportsHashKey>* aAllowed,
                                     nsIAtom*** aURLs,
                                     bool aAllowXLink,
                                     bool aAllowStyle,
                                     bool aAllowDangerousSrc)
 {
   uint32_t ac = aElement->GetAttrCount();
 
-  nsresult rv;
-
   for (int32_t i = ac - 1; i >= 0; --i) {
-    rv = NS_OK;
     const nsAttrName* attrName = aElement->GetAttrNameAt(i);
     int32_t attrNs = attrName->NamespaceID();
     nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
 
     if (kNameSpaceID_None == attrNs) {
       if (aAllowStyle && nsGkAtoms::style == attrLocal) {
         nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
         nsIDocument* document = aElement->OwnerDoc();
         // Pass the CSS Loader object to the parser, to allow parser error
         // reports to include the outer window ID.
         nsCSSParser parser(document->CSSLoader());
-        RefPtr<mozilla::css::StyleRule> rule;
         nsAutoString value;
         aElement->GetAttr(attrNs, attrLocal, value);
-        rv = parser.ParseStyleAttribute(value,
-                                        document->GetDocumentURI(),
-                                        baseURI,
-                                        document->NodePrincipal(),
-                                        getter_AddRefs(rule));
-        if (NS_SUCCEEDED(rv)) {
+        RefPtr<mozilla::css::Declaration> decl =
+          parser.ParseStyleAttribute(value, document->GetDocumentURI(),
+                                     baseURI, document->NodePrincipal());
+        if (decl) {
           nsAutoString cleanValue;
-          if (SanitizeStyleRule(rule, cleanValue)) {
+          if (SanitizeStyleDeclaration(decl, cleanValue)) {
             aElement->SetAttr(kNameSpaceID_None,
                               nsGkAtoms::style,
                               cleanValue,
                               false);
           }
         }
         continue;
       }
--- a/dom/base/nsTreeSanitizer.h
+++ b/dom/base/nsTreeSanitizer.h
@@ -149,22 +149,22 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
                        int32_t aNamespace,
                        nsIAtom* aLocalName);
 
     /**
      * Checks a style rule for the presence of the 'binding' CSS property and
      * removes that property from the rule and reserializes in case the
      * property was found.
      *
-     * @param aRule The style rule to check
+     * @param aDeclaration The style declaration to check
      * @param aRuleText the serialized mutated rule if the method returns true
      * @return true if the rule was modified and false otherwise
      */
-    bool SanitizeStyleRule(mozilla::css::StyleRule* aRule,
-                             nsAutoString &aRuleText);
+    bool SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+                                  nsAutoString& aRuleText);
 
     /**
      * Parses a style sheet and reserializes it with the 'binding' property
      * removed if it was present.
      *
      * @param aOrigin the original style sheet source
      * @param aSanitized the reserialization without 'binding'; only valid if
      *                   this method return true
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2133,63 +2133,54 @@ CanvasRenderingContext2D::SetShadowColor
 
 //
 // filters
 //
 
 static already_AddRefed<Declaration>
 CreateDeclaration(nsINode* aNode,
   const nsCSSProperty aProp1, const nsAString& aValue1, bool* aChanged1,
-  const nsCSSProperty aProp2, const nsAString& aValue2, bool* aChanged2,
-  ErrorResult& error)
-{
-  RefPtr<StyleRule> rule;
-
+  const nsCSSProperty aProp2, const nsAString& aValue2, bool* aChanged2)
+{
   nsIPrincipal* principal = aNode->NodePrincipal();
   nsIDocument* document = aNode->OwnerDoc();
 
   nsIURI* docURL = document->GetDocumentURI();
   nsIURI* baseURL = document->GetDocBaseURI();
 
   // Pass the CSS Loader object to the parser, to allow parser error reports
   // to include the outer window ID.
   nsCSSParser parser(document->CSSLoader());
 
-  error = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
-                                     principal, getter_AddRefs(rule));
-  if (error.Failed()) {
-    return nullptr;
-  }
+  RefPtr<Declaration> declaration =
+    parser.ParseStyleAttribute(EmptyString(), docURL, baseURL, principal);
 
   if (aProp1 != eCSSProperty_UNKNOWN) {
     parser.ParseProperty(aProp1, aValue1, docURL, baseURL, principal,
-                         rule->GetDeclaration(), aChanged1, false);
+                         declaration, aChanged1, false);
   }
 
   if (aProp2 != eCSSProperty_UNKNOWN) {
     parser.ParseProperty(aProp2, aValue2, docURL, baseURL, principal,
-                         rule->GetDeclaration(), aChanged2, false);
-  }
-
-  RefPtr<Declaration> declaration = rule->GetDeclaration();
+                         declaration, aChanged2, false);
+  }
+
   declaration->SetImmutable();
   return declaration.forget();
 }
 
 static already_AddRefed<Declaration>
 CreateFontDeclaration(const nsAString& aFont,
                       nsINode* aNode,
-                      bool* aOutFontChanged,
-                      ErrorResult& error)
+                      bool* aOutFontChanged)
 {
   bool lineHeightChanged;
   return CreateDeclaration(aNode,
     eCSSProperty_font, aFont, aOutFontChanged,
-    eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged,
-    error);
+    eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged);
 }
 
 static already_AddRefed<nsStyleContext>
 GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
                           ErrorResult& error)
 {
   if (aElement && aElement->IsInDoc()) {
     // Inherit from the canvas element.
@@ -2202,21 +2193,17 @@ GetFontParentStyleContext(Element* aElem
     }
     return result.forget();
   }
 
   // otherwise inherit from default (10px sans-serif)
   bool changed;
   RefPtr<css::Declaration> parentRule =
     CreateFontDeclaration(NS_LITERAL_STRING("10px sans-serif"),
-                          presShell->GetDocument(), &changed, error);
-
-  if (error.Failed()) {
-    return nullptr;
-  }
+                          presShell->GetDocument(), &changed);
 
   nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
   parentRules.AppendElement(parentRule);
   RefPtr<nsStyleContext> result =
     presShell->StyleSet()->ResolveStyleForRules(nullptr, parentRules);
 
   if (!result) {
     error.Throw(NS_ERROR_FAILURE);
@@ -2241,21 +2228,17 @@ static already_AddRefed<nsStyleContext>
 GetFontStyleContext(Element* aElement, const nsAString& aFont,
                     nsIPresShell* presShell,
                     nsAString& aOutUsedFont,
                     ErrorResult& error)
 {
   bool fontParsedSuccessfully = false;
   RefPtr<css::Declaration> decl =
     CreateFontDeclaration(aFont, presShell->GetDocument(),
-                          &fontParsedSuccessfully, error);
-
-  if (error.Failed()) {
-    return nullptr;
-  }
+                          &fontParsedSuccessfully);
 
   if (!fontParsedSuccessfully) {
     // We got a syntax error.  The spec says this value must be ignored.
     return nullptr;
   }
 
   // In addition to unparseable values, the spec says we need to reject
   // 'inherit' and 'initial'. The easiest way to check for this is to look
@@ -2297,40 +2280,34 @@ GetFontStyleContext(Element* aElement, c
   decl->GetValue(eCSSProperty_font, aOutUsedFont);
 
   return sc.forget();
 }
 
 static already_AddRefed<Declaration>
 CreateFilterDeclaration(const nsAString& aFilter,
                         nsINode* aNode,
-                        bool* aOutFilterChanged,
-                        ErrorResult& error)
+                        bool* aOutFilterChanged)
 {
   bool dummy;
   return CreateDeclaration(aNode,
     eCSSProperty_filter, aFilter, aOutFilterChanged,
-    eCSSProperty_UNKNOWN, EmptyString(), &dummy,
-    error);
+    eCSSProperty_UNKNOWN, EmptyString(), &dummy);
 }
 
 static already_AddRefed<nsStyleContext>
 ResolveStyleForFilter(const nsAString& aFilterString,
                       nsIPresShell* aPresShell,
                       nsStyleContext* aParentContext,
                       ErrorResult& error)
 {
   nsIDocument* document = aPresShell->GetDocument();
   bool filterChanged = false;
   RefPtr<css::Declaration> decl =
-    CreateFilterDeclaration(aFilterString, document, &filterChanged, error);
-
-  if (error.Failed()) {
-    return nullptr;
-  }
+    CreateFilterDeclaration(aFilterString, document, &filterChanged);
 
   if (!filterChanged) {
     // Refuse to accept the filter, but do not throw an error.
     return nullptr;
   }
 
   // In addition to unparseable values, the spec says we need to reject
   // 'inherit' and 'initial'.
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -15,32 +15,31 @@
 #include "nscore.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsQueryObject.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
-#include "mozilla/css/StyleRule.h"
+#include "mozilla/css/Declaration.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMAttr.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLMenuElement.h"
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLDocument.h"
 #include "nsPIDOMWindow.h"
-#include "nsIStyleRule.h"
 #include "nsIURL.h"
 #include "nsEscape.h"
 #include "nsIFrameInlines.h"
 #include "nsIScrollableFrame.h"
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsIWidget.h"
 #include "nsRange.h"
@@ -221,25 +220,24 @@ 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::eCSSStyleRule) {
+        value->Type() == nsAttrValue::eCSSDeclaration) {
       // 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<mozilla::css::Rule> ruleClone = value->GetCSSStyleRuleValue()->Clone();
-      RefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(ruleClone);
-      NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
-
-      rv = aDst->SetInlineStyleRule(styleRule, &valStr, false);
+      RefPtr<css::Declaration> declClone =
+        new css::Declaration(*value->GetCSSDeclarationValue());
+
+      rv = aDst->SetInlineStyleDeclaration(declClone, &valStr, false);
       NS_ENSURE_SUCCESS(rv, rv);
 
       continue;
     }
 
     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
                        name->GetPrefix(), valStr, false);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -714,17 +714,17 @@ nsSMILAnimationController::AddStyleUpdat
 
     nsSMILTargetIdentifier key;
     if (!GetTargetIdentifierForAnimation(animElement, key)) {
       // Something's wrong/missing about animation's target; skip this animation
       continue;
     }
 
     // mIsCSS true means that the rules are the ones returned from
-    // Element::GetSMILOverrideStyleRule (via nsSMILCSSProperty objects),
+    // Element::GetSMILOverrideStyleDeclaration (via nsSMILCSSProperty objects),
     // and mIsCSS false means the rules are nsSMILMappedAttribute objects
     // returned from nsSVGElement::GetAnimatedContentStyleRule.
     nsRestyleHint rshint = key.mIsCSS ? eRestyle_StyleAttribute_Animations
                                       : eRestyle_SVGAttrAnimations;
     aTracker.AddPendingRestyle(key.mElement, rshint, nsChangeHint(0));
   }
 
   mMightHavePendingStyleUpdates = false;
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -252,30 +252,30 @@ 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::eCSSStyleRule) {
+  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;
     oldVal->ToString(stringValue);
     // Force in data doc, since we already have a style rule
     ParseStyleAttribute(stringValue, attrValue, true);
-    // Don't bother going through SetInlineStyleRule, we don't want to fire off
-    // mutation events or document notifications anyway
+    // Don't bother going through SetInlineStyleDeclaration; we don't
+    // want to fire off mutation events or document notifications anyway
     rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -380,25 +380,24 @@ 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::eCSSStyleRule) {
-            RefPtr<css::Rule> ruleClone =
-                originalValue->GetCSSStyleRuleValue()->Clone();
+        if (originalValue->Type() == nsAttrValue::eCSSDeclaration) {
+            RefPtr<css::Declaration> declClone =
+              new css::Declaration(*originalValue->GetCSSDeclarationValue());
 
             nsString stringValue;
             originalValue->ToString(stringValue);
 
-            RefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
-            attrValue.SetTo(styleRule, &stringValue);
+            attrValue.SetTo(declClone, &stringValue);
         } else {
             attrValue.SetTo(*originalValue);
         }
 
         if (originalName->IsAtom()) {
            rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
                                                           attrValue);
         } else {
@@ -1858,25 +1857,24 @@ 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::eCSSStyleRule) {
-            RefPtr<css::Rule> ruleClone =
-                protoattr->mValue.GetCSSStyleRuleValue()->Clone();
+        if (protoattr->mValue.Type() == nsAttrValue::eCSSDeclaration) {
+            RefPtr<css::Declaration> declClone = new css::Declaration(
+              *protoattr->mValue.GetCSSDeclarationValue());
 
             nsString stringValue;
             protoattr->mValue.ToString(stringValue);
 
-            RefPtr<css::StyleRule> styleRule = do_QueryObject(ruleClone);
-            attrValue.SetTo(styleRule, &stringValue);
+            attrValue.SetTo(declClone, &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 {
@@ -2433,32 +2431,31 @@ nsXULPrototypeElement::SetAttrAt(uint32_
         mHasClassAttribute = true;
         // Compute the element's class list
         mAttributes[aPos].mValue.ParseAtomArray(aValue);
 
         return NS_OK;
     } else if (mAttributes[aPos].mName.Equals(nsGkAtoms::style)) {
         mHasStyleAttribute = true;
         // Parse the element's 'style' attribute
-        RefPtr<css::StyleRule> rule;
 
         nsCSSParser parser;
 
         // XXX Get correct Base URI (need GetBaseURI on *prototype* element)
         // TODO: If we implement Content Security Policy for chrome documents
         // as has been discussed, the CSP should be checked here to see if
         // inline styles are allowed to be applied.
-        parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
-                                   // This is basically duplicating what
-                                   // nsINode::NodePrincipal() does
-                                   mNodeInfo->NodeInfoManager()->
-                                     DocumentPrincipal(),
-                                   getter_AddRefs(rule));
-        if (rule) {
-            mAttributes[aPos].mValue.SetTo(rule, &aValue);
+        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);
 
             return NS_OK;
         }
         // Don't abort if parsing failed, it could just be malformed css.
     }
 
     mAttributes[aPos].mValue.ParseStringOrAtom(aValue);
 
--- a/editor/libeditor/nsHTMLCSSUtils.cpp
+++ b/editor/libeditor/nsHTMLCSSUtils.cpp
@@ -511,25 +511,25 @@ nsHTMLCSSUtils::GetCSSInlinePropertyBase
     // from these declarations, get the one we want and that one only
     MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
       cssDecl->GetPropertyValue(nsDependentAtomString(aProperty), aValue)));
 
     return NS_OK;
   }
 
   MOZ_ASSERT(aStyleType == eSpecified);
-  RefPtr<css::StyleRule> rule = element->GetInlineStyleRule();
-  if (!rule) {
+  RefPtr<css::Declaration> decl = element->GetInlineStyleDeclaration();
+  if (!decl) {
     return NS_OK;
   }
   nsCSSProperty prop =
     nsCSSProps::LookupProperty(nsDependentAtomString(aProperty),
                                nsCSSProps::eEnabledForAllContent);
   MOZ_ASSERT(prop != eCSSProperty_UNKNOWN);
-  rule->GetDeclaration()->GetValue(prop, aValue);
+  decl->GetValue(prop, aValue);
 
   return NS_OK;
 }
 
 already_AddRefed<nsComputedDOMStyle>
 nsHTMLCSSUtils::GetComputedStyle(dom::Element* aElement)
 {
   MOZ_ASSERT(aElement);
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -135,21 +135,21 @@ public:
   nsresult ParseSheet(const nsAString& aInput,
                       nsIURI*          aSheetURI,
                       nsIURI*          aBaseURI,
                       nsIPrincipal*    aSheetPrincipal,
                       uint32_t         aLineNumber,
                       SheetParsingMode aParsingMode,
                       LoaderReusableStyleSheets* aReusableSheets);
 
-  nsresult ParseStyleAttribute(const nsAString&  aAttributeValue,
+  already_AddRefed<css::Declaration>
+           ParseStyleAttribute(const nsAString&  aAttributeValue,
                                nsIURI*           aDocURL,
                                nsIURI*           aBaseURL,
-                               nsIPrincipal*     aNodePrincipal,
-                               css::StyleRule**  aResult);
+                               nsIPrincipal*     aNodePrincipal);
 
   nsresult ParseDeclarations(const nsAString&  aBuffer,
                              nsIURI*           aSheetURL,
                              nsIURI*           aBaseURL,
                              nsIPrincipal*     aSheetPrincipal,
                              css::Declaration* aDeclaration,
                              bool*           aChanged);
 
@@ -1622,64 +1622,55 @@ CSSParserImpl::ParseSheet(const nsAStrin
     }
   }
   ReleaseScanner();
 
   mParsingMode = eAuthorSheetFeatures;
   mIsChrome = false;
   mReusableSheets = nullptr;
 
-  // XXX check for low level errors
   return NS_OK;
 }
 
 /**
  * Determines whether the identifier contained in the given string is a
  * vendor-specific identifier, as described in CSS 2.1 section 4.1.2.1.
  */
 static bool
 NonMozillaVendorIdentifier(const nsAString& ident)
 {
   return (ident.First() == char16_t('-') &&
           !StringBeginsWith(ident, NS_LITERAL_STRING("-moz-"))) ||
          ident.First() == char16_t('_');
 
 }
 
-nsresult
+already_AddRefed<css::Declaration>
 CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue,
                                    nsIURI*          aDocURI,
                                    nsIURI*          aBaseURI,
-                                   nsIPrincipal*    aNodePrincipal,
-                                   css::StyleRule** aResult)
+                                   nsIPrincipal*    aNodePrincipal)
 {
   NS_PRECONDITION(aNodePrincipal, "Must have principal here!");
   NS_PRECONDITION(aBaseURI, "need base URI");
 
   // XXX line number?
   nsCSSScanner scanner(aAttributeValue, 0);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aDocURI);
   InitScanner(scanner, reporter, aDocURI, aBaseURI, aNodePrincipal);
 
   mSection = eCSSSection_General;
 
   uint32_t parseFlags = eParseDeclaration_AllowImportant;
 
   RefPtr<css::Declaration> declaration = ParseDeclarationBlock(parseFlags);
-  if (declaration) {
-    // Create a style rule for the declaration
-    NS_ADDREF(*aResult = new css::StyleRule(nullptr, declaration, 0, 0));
-  } else {
-    *aResult = nullptr;
-  }
 
   ReleaseScanner();
 
-  // XXX check for low level errors
-  return NS_OK;
+  return declaration.forget();
 }
 
 nsresult
 CSSParserImpl::ParseDeclarations(const nsAString&  aBuffer,
                                  nsIURI*           aSheetURI,
                                  nsIURI*           aBaseURI,
                                  nsIPrincipal*     aSheetPrincipal,
                                  css::Declaration* aDeclaration,
@@ -16252,26 +16243,24 @@ nsCSSParser::ParseSheet(const nsAString&
                         SheetParsingMode aParsingMode,
                         LoaderReusableStyleSheets* aReusableSheets)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
     ParseSheet(aInput, aSheetURI, aBaseURI, aSheetPrincipal, aLineNumber,
                aParsingMode, aReusableSheets);
 }
 
-nsresult
+already_AddRefed<css::Declaration>
 nsCSSParser::ParseStyleAttribute(const nsAString&  aAttributeValue,
                                  nsIURI*           aDocURI,
                                  nsIURI*           aBaseURI,
-                                 nsIPrincipal*     aNodePrincipal,
-                                 css::StyleRule**  aResult)
+                                 nsIPrincipal*     aNodePrincipal)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
-    ParseStyleAttribute(aAttributeValue, aDocURI, aBaseURI,
-                        aNodePrincipal, aResult);
+    ParseStyleAttribute(aAttributeValue, aDocURI, aBaseURI, aNodePrincipal);
 }
 
 nsresult
 nsCSSParser::ParseDeclarations(const nsAString&  aBuffer,
                                nsIURI*           aSheetURI,
                                nsIURI*           aBaseURI,
                                nsIPrincipal*     aSheetPrincipal,
                                css::Declaration* aDeclaration,
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -88,21 +88,21 @@ public:
                       uint32_t         aLineNumber,
                       mozilla::css::SheetParsingMode aParsingMode,
                       mozilla::css::LoaderReusableStyleSheets* aReusableSheets =
                         nullptr);
 
   // Parse HTML style attribute or its equivalent in other markup
   // languages.  aBaseURL is the base url to use for relative links in
   // the declaration.
-  nsresult ParseStyleAttribute(const nsAString&  aAttributeValue,
+  already_AddRefed<mozilla::css::Declaration>
+           ParseStyleAttribute(const nsAString&  aAttributeValue,
                                nsIURI*           aDocURL,
                                nsIURI*           aBaseURL,
-                               nsIPrincipal*     aNodePrincipal,
-                               mozilla::css::StyleRule** aResult);
+                               nsIPrincipal*     aNodePrincipal);
 
   // Parse the body of a declaration block.  Very similar to
   // ParseStyleAttribute, but used under different circumstances.
   // The contents of aDeclaration will be erased and replaced with the
   // results of parsing; aChanged will be set true if the aDeclaration
   // argument was modified.
   nsresult ParseDeclarations(const nsAString&  aBuffer,
                              nsIURI*           aSheetURL,
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -67,92 +67,80 @@ NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDe
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCSSAttributeDeclaration)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCSSAttributeDeclaration)
 
 nsresult
 nsDOMCSSAttributeDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
 {
   NS_ASSERTION(mElement, "Must have Element to set the declaration!");
-  css::StyleRule* oldRule =
-    mIsSMILOverride ? mElement->GetSMILOverrideStyleRule() :
-    mElement->GetInlineStyleRule();
-  NS_ASSERTION(oldRule, "Element must have rule");
-
-  RefPtr<css::StyleRule> newRule =
-    oldRule->DeclarationChanged(aDecl, false);
-  if (!newRule) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   return
-    mIsSMILOverride ? mElement->SetSMILOverrideStyleRule(newRule, true) :
-    mElement->SetInlineStyleRule(newRule, nullptr, true);
+    mIsSMILOverride ? mElement->SetSMILOverrideStyleDeclaration(aDecl, true) :
+    mElement->SetInlineStyleDeclaration(aDecl, nullptr, true);
 }
 
 nsIDocument*
 nsDOMCSSAttributeDeclaration::DocToUpdate()
 {
   // We need OwnerDoc() rather than GetCurrentDoc() because it might
   // be the BeginUpdate call that inserts mElement into the document.
   return mElement->OwnerDoc();
 }
 
 css::Declaration*
 nsDOMCSSAttributeDeclaration::GetCSSDeclaration(Operation aOperation)
 {
   if (!mElement)
     return nullptr;
 
-  css::StyleRule* cssRule;
+  css::Declaration* declaration;
   if (mIsSMILOverride)
-    cssRule = mElement->GetSMILOverrideStyleRule();
+    declaration = mElement->GetSMILOverrideStyleDeclaration();
   else
-    cssRule = mElement->GetInlineStyleRule();
+    declaration = mElement->GetInlineStyleDeclaration();
 
   // 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.
 
   // XXXbz this is a bit of a hack, especially doing it before the
   // BeginUpdate(), but this is a good chokepoint where we know we
   // plan to modify the CSSDeclaration, so need to notify
   // AttributeWillChange if this is inline style.
   if (!mIsSMILOverride &&
       ((aOperation == eOperation_Modify) ||
-       (aOperation == eOperation_RemoveProperty && cssRule))) {
+       (aOperation == eOperation_RemoveProperty && declaration))) {
     nsNodeUtils::AttributeWillChange(mElement, kNameSpaceID_None,
                                      nsGkAtoms::style,
                                      nsIDOMMutationEvent::MODIFICATION,
                                      nullptr);
   }
 
-  if (cssRule) {
-    return cssRule->GetDeclaration();
+  if (declaration) {
+    return declaration;
   }
 
   if (aOperation != eOperation_Modify) {
     return nullptr;
   }
 
   // cannot fail
   RefPtr<css::Declaration> decl = new css::Declaration();
   decl->InitializeEmpty();
-  RefPtr<css::StyleRule> newRule = new css::StyleRule(nullptr, decl, 0, 0);
 
   // this *can* fail (inside SetAttrAndNotify, at least).
   nsresult rv;
   if (mIsSMILOverride)
-    rv = mElement->SetSMILOverrideStyleRule(newRule, false);
+    rv = mElement->SetSMILOverrideStyleDeclaration(decl, false);
   else
-    rv = mElement->SetInlineStyleRule(newRule, nullptr, false);
+    rv = mElement->SetInlineStyleDeclaration(decl, nullptr, false);
 
   if (NS_FAILED(rv)) {
     return nullptr; // the decl will be destroyed along with the style rule
   }
 
   return decl;
 }
 
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -24,24 +24,20 @@ using namespace mozilla::dom;
 
 namespace {
 
 PLDHashOperator
 ClearAttrCache(const nsAString& aKey, MiscContainer*& aValue, void*)
 {
   // Ideally we'd just call MiscContainer::Evict, but we can't do that since
   // we're iterating the hashtable.
-  MOZ_ASSERT(aValue->mType == nsAttrValue::eCSSStyleRule);
+  MOZ_ASSERT(aValue->mType == nsAttrValue::eCSSDeclaration);
 
-  css::StyleRule* styleRule = aValue->mValue.mCSSStyleRule;
-  styleRule->SetHTMLCSSStyleSheet(nullptr);
-  css::Declaration* declaration = styleRule->GetDeclaration();
-  if (declaration) {
-    declaration->SetHTMLCSSStyleSheet(nullptr);
-  }
+  css::Declaration* declaration = aValue->mValue.mCSSDeclaration;
+  declaration->SetHTMLCSSStyleSheet(nullptr);
   aValue->mValue.mCached = 0;
 
   return PL_DHASH_REMOVE;
 }
 
 } // namespace
 
 nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet()
@@ -65,30 +61,28 @@ 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::StyleRule* rule = aElement->GetInlineStyleRule();
-  if (rule) {
-    css::Declaration* declaration = rule->GetDeclaration();
+  css::Declaration* declaration = aElement->GetInlineStyleDeclaration();
+  if (declaration) {
     declaration->SetImmutable();
     aRuleWalker->Forward(declaration);
   }
 
-  rule = aElement->GetSMILOverrideStyleRule();
-  if (rule) {
+  declaration = aElement->GetSMILOverrideStyleDeclaration();
+  if (declaration) {
     RestyleManager* restyleManager = aPresContext->RestyleManager();
     if (!restyleManager->SkipAnimationRules()) {
       // Animation restyle (or non-restyle traversal of rules)
       // Now we can walk SMIL overrride style, without triggering transitions.
-      css::Declaration* declaration = rule->GetDeclaration();
       declaration->SetImmutable();
       aRuleWalker->Forward(declaration);
     }
   }
 }
 
 void
 nsHTMLCSSStyleSheet::PseudoElementRulesMatching(Element* aPseudoElement,
@@ -96,19 +90,18 @@ 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::StyleRule* rule = aPseudoElement->GetInlineStyleRule();
-  if (rule) {
-    css::Declaration* declaration = rule->GetDeclaration();
+  css::Declaration* declaration = aPseudoElement->GetInlineStyleDeclaration();
+  if (declaration) {
     declaration->SetImmutable();
     aRuleWalker->Forward(declaration);
   }
 }
 
 /* virtual */ void
 nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
 {
--- a/layout/style/nsHTMLCSSStyleSheet.h
+++ b/layout/style/nsHTMLCSSStyleSheet.h
@@ -8,16 +8,17 @@
  */
 
 #ifndef nsHTMLCSSStyleSheet_h_
 #define nsHTMLCSSStyleSheet_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 
+#include "nsCSSPseudoElements.h"
 #include "nsDataHashtable.h"
 #include "nsIStyleRuleProcessor.h"
 
 class nsRuleWalker;
 struct MiscContainer;
 
 namespace mozilla {
 namespace dom {