Bug 978833 patch 12 - Use the css::Declaration instead of the css::StyleRule as the matching rule. r=heycam
authorL. David Baron <dbaron@dbaron.org>
Thu, 05 Nov 2015 16:44:10 +0800
changeset 271350 f340cdf67edb870645ddf499da690e60eff7f73f
parent 271349 e69922893211b78e5593fbd1c795e66248a357a1
child 271351 9f2470877279bdaeed2128a527b81183a3d71bbd
push id29638
push userkwierso@gmail.com
push dateFri, 06 Nov 2015 02:44:30 +0000
treeherdermozilla-central@cc48981c026c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs978833
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 978833 patch 12 - Use the css::Declaration instead of the css::StyleRule as the matching rule. r=heycam This is the key change in this patch series; it changes the object we use for style data (currently nsIStyleRule) identity. It allows removing some hacks we have to deal with that for StyleRule, and avoids having to write similar hacks for nsCSSKeyframeRule and nsCSSPageRule (which are broken without this). I confirmed locally that it is this patch that fixes both of the todo_is mochitests, by building and testing with the patch queue through patch 11, and again through patch 12.
dom/canvas/CanvasRenderingContext2D.cpp
dom/svg/nsSVGElement.cpp
layout/inspector/inDOMUtils.cpp
layout/style/StyleAnimationValue.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLCSSStyleSheet.cpp
layout/style/nsRuleWalker.h
layout/style/nsStyleSet.cpp
layout/style/test/test_animations_dynamic_changes.html
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2130,18 +2130,18 @@ CanvasRenderingContext2D::SetShadowColor
 
   CurrentState().shadowColor = color;
 }
 
 //
 // filters
 //
 
-static already_AddRefed<StyleRule>
-CreateStyleRule(nsINode* aNode,
+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;
 
   nsIPrincipal* principal = aNode->NodePrincipal();
   nsIDocument* document = aNode->OwnerDoc();
@@ -2166,27 +2166,28 @@ CreateStyleRule(nsINode* aNode,
 
   if (aProp2 != eCSSProperty_UNKNOWN) {
     parser.ParseProperty(aProp2, aValue2, docURL, baseURL, principal,
                          rule->GetDeclaration(), aChanged2, false);
   }
 
   rule->RuleMatched();
 
-  return rule.forget();
+  RefPtr<Declaration> declaration = rule->GetDeclaration();
+  return declaration.forget();
 }
 
-static already_AddRefed<StyleRule>
-CreateFontStyleRule(const nsAString& aFont,
-                    nsINode* aNode,
-                    bool* aOutFontChanged,
-                    ErrorResult& error)
+static already_AddRefed<Declaration>
+CreateFontDeclaration(const nsAString& aFont,
+                      nsINode* aNode,
+                      bool* aOutFontChanged,
+                      ErrorResult& error)
 {
   bool lineHeightChanged;
-  return CreateStyleRule(aNode,
+  return CreateDeclaration(aNode,
     eCSSProperty_font, aFont, aOutFontChanged,
     eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged,
     error);
 }
 
 static already_AddRefed<nsStyleContext>
 GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
                           ErrorResult& error)
@@ -2200,19 +2201,19 @@ GetFontParentStyleContext(Element* aElem
       error.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
     return result.forget();
   }
 
   // otherwise inherit from default (10px sans-serif)
   bool changed;
-  RefPtr<css::StyleRule> parentRule =
-    CreateFontStyleRule(NS_LITERAL_STRING("10px sans-serif"),
-                        presShell->GetDocument(), &changed, error);
+  RefPtr<css::Declaration> parentRule =
+    CreateFontDeclaration(NS_LITERAL_STRING("10px sans-serif"),
+                          presShell->GetDocument(), &changed, error);
 
   if (error.Failed()) {
     return nullptr;
   }
 
   nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
   parentRules.AppendElement(parentRule);
   RefPtr<nsStyleContext> result =
@@ -2221,53 +2222,52 @@ GetFontParentStyleContext(Element* aElem
   if (!result) {
     error.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   return result.forget();
 }
 
 static bool
-PropertyIsInheritOrInitial(StyleRule* aRule, const nsCSSProperty aProperty)
-{
-  css::Declaration* declaration = aRule->GetDeclaration();
+PropertyIsInheritOrInitial(Declaration* aDeclaration, const nsCSSProperty aProperty)
+{
   // We know the declaration is not !important, so we can use
   // GetNormalBlock().
   const nsCSSValue* filterVal =
-    declaration->GetNormalBlock()->ValueFor(aProperty);
+    aDeclaration->GetNormalBlock()->ValueFor(aProperty);
   return (!filterVal || (filterVal->GetUnit() == eCSSUnit_Unset ||
                          filterVal->GetUnit() == eCSSUnit_Inherit ||
                          filterVal->GetUnit() == eCSSUnit_Initial));
 }
 
 static already_AddRefed<nsStyleContext>
 GetFontStyleContext(Element* aElement, const nsAString& aFont,
                     nsIPresShell* presShell,
                     nsAString& aOutUsedFont,
                     ErrorResult& error)
 {
   bool fontParsedSuccessfully = false;
-  RefPtr<css::StyleRule> rule =
-    CreateFontStyleRule(aFont, presShell->GetDocument(),
-                        &fontParsedSuccessfully, error);
+  RefPtr<css::Declaration> decl =
+    CreateFontDeclaration(aFont, presShell->GetDocument(),
+                          &fontParsedSuccessfully, error);
 
   if (error.Failed()) {
     return nullptr;
   }
 
   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
   // at font-size-adjust, which the font shorthand resets to either 'none' or
   // '-moz-system-font'.
-  if (PropertyIsInheritOrInitial(rule, eCSSProperty_font_size_adjust)) {
+  if (PropertyIsInheritOrInitial(decl, eCSSProperty_font_size_adjust)) {
     return nullptr;
   }
 
   // have to get a parent style context for inherit-like relative
   // values (2em, bolder, etc.)
   RefPtr<nsStyleContext> parentContext =
     GetFontParentStyleContext(aElement, presShell, error);
 
@@ -2278,74 +2278,74 @@ GetFontStyleContext(Element* aElement, c
 
   MOZ_RELEASE_ASSERT(parentContext,
                      "GetFontParentStyleContext should have returned an error if it couldn't get a parent context.");
 
   MOZ_ASSERT(!presShell->IsDestroying(),
              "GetFontParentStyleContext should have returned an error if the presshell is being destroyed.");
 
   nsTArray<nsCOMPtr<nsIStyleRule>> rules;
-  rules.AppendElement(rule);
+  rules.AppendElement(decl);
   // add a rule to prevent text zoom from affecting the style
   rules.AppendElement(new nsDisableTextZoomStyleRule);
 
   nsStyleSet* styleSet = presShell->StyleSet();
   RefPtr<nsStyleContext> sc =
     styleSet->ResolveStyleForRules(parentContext, rules);
 
   // The font getter is required to be reserialized based on what we
   // parsed (including having line-height removed).  (Older drafts of
   // the spec required font sizes be converted to pixels, but that no
   // longer seems to be required.)
-  rule->GetDeclaration()->GetValue(eCSSProperty_font, aOutUsedFont);
+  decl->GetValue(eCSSProperty_font, aOutUsedFont);
 
   return sc.forget();
 }
 
-static already_AddRefed<StyleRule>
-CreateFilterStyleRule(const nsAString& aFilter,
-                      nsINode* aNode,
-                      bool* aOutFilterChanged,
-                      ErrorResult& error)
+static already_AddRefed<Declaration>
+CreateFilterDeclaration(const nsAString& aFilter,
+                        nsINode* aNode,
+                        bool* aOutFilterChanged,
+                        ErrorResult& error)
 {
   bool dummy;
-  return CreateStyleRule(aNode,
+  return CreateDeclaration(aNode,
     eCSSProperty_filter, aFilter, aOutFilterChanged,
     eCSSProperty_UNKNOWN, EmptyString(), &dummy,
     error);
 }
 
 static already_AddRefed<nsStyleContext>
-ResolveStyleForFilterRule(const nsAString& aFilterString,
-                          nsIPresShell* aPresShell,
-                          nsStyleContext* aParentContext,
-                          ErrorResult& error)
+ResolveStyleForFilter(const nsAString& aFilterString,
+                      nsIPresShell* aPresShell,
+                      nsStyleContext* aParentContext,
+                      ErrorResult& error)
 {
   nsIDocument* document = aPresShell->GetDocument();
   bool filterChanged = false;
-  RefPtr<css::StyleRule> rule =
-    CreateFilterStyleRule(aFilterString, document, &filterChanged, error);
+  RefPtr<css::Declaration> decl =
+    CreateFilterDeclaration(aFilterString, document, &filterChanged, error);
 
   if (error.Failed()) {
     return nullptr;
   }
 
   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'.
-  if (PropertyIsInheritOrInitial(rule, eCSSProperty_filter)) {
+  if (PropertyIsInheritOrInitial(decl, eCSSProperty_filter)) {
     return nullptr;
   }
 
   nsTArray<nsCOMPtr<nsIStyleRule>> rules;
-  rules.AppendElement(rule);
+  rules.AppendElement(decl);
 
   RefPtr<nsStyleContext> sc =
     aPresShell->StyleSet()->ResolveStyleForRules(aParentContext, rules);
 
   return sc.forget();
 }
 
 bool
@@ -2370,17 +2370,17 @@ CanvasRenderingContext2D::ParseFilter(co
     GetFontStyleContext(mCanvasElement, GetFont(),
                         presShell, usedFont, error);
   if (!parentContext) {
     error.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   RefPtr<nsStyleContext> sc =
-    ResolveStyleForFilterRule(aString, presShell, parentContext, error);
+    ResolveStyleForFilter(aString, presShell, parentContext, error);
 
   if (!sc) {
     return false;
   }
 
   aFilterChain = sc->StyleSVGReset()->mFilters;
   return true;
 }
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -899,17 +899,17 @@ nsSVGElement::WalkContentStyleRules(nsRu
 #ifdef DEBUG
 //  printf("nsSVGElement(%p)::WalkContentStyleRules()\n", this);
 #endif
   if (!mContentStyleRule)
     UpdateContentStyleRule();
 
   if (mContentStyleRule) {
     mContentStyleRule->RuleMatched();
-    aRuleWalker->Forward(mContentStyleRule);
+    aRuleWalker->Forward(mContentStyleRule->GetDeclaration());
   }
 
   return NS_OK;
 }
 
 void
 nsSVGElement::WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker)
 {
@@ -923,17 +923,17 @@ nsSVGElement::WalkAnimatedContentStyleRu
     // update/walk the animated content style rule.
     css::StyleRule* animContentStyleRule = GetAnimatedContentStyleRule();
     if (!animContentStyleRule) {
       UpdateAnimatedContentStyleRule();
       animContentStyleRule = GetAnimatedContentStyleRule();
     }
     if (animContentStyleRule) {
       animContentStyleRule->RuleMatched();
-      aRuleWalker->Forward(animContentStyleRule);
+      aRuleWalker->Forward(animContentStyleRule->GetDeclaration());
     }
   }
 }
 
 NS_IMETHODIMP_(bool)
 nsSVGElement::IsAttributeMapped(const nsIAtom* name) const
 {
   if (name == nsGkAtoms::lang) {
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -233,23 +233,27 @@ inDOMUtils::GetCSSStyleRules(nsIDOMEleme
     // if the document they're in doesn't have a presshell.  Bail out.
     return NS_OK;
   }
 
   nsCOMPtr<nsISupportsArray> rules;
   NS_NewISupportsArray(getter_AddRefs(rules));
   if (!rules) return NS_ERROR_OUT_OF_MEMORY;
 
-  RefPtr<mozilla::css::StyleRule> cssRule;
   for ( ; !ruleNode->IsRoot(); ruleNode = ruleNode->GetParent()) {
-    cssRule = do_QueryObject(ruleNode->GetRule());
-    if (cssRule) {
-      nsCOMPtr<nsIDOMCSSRule> domRule = cssRule->GetDOMRule();
-      if (domRule)
-        rules->InsertElementAt(domRule, 0);
+    RefPtr<Declaration> decl = do_QueryObject(ruleNode->GetRule());
+    if (decl) {
+      RefPtr<mozilla::css::StyleRule> styleRule =
+        do_QueryObject(decl->GetOwningRule());
+      if (styleRule) {
+        nsCOMPtr<nsIDOMCSSRule> domRule = styleRule->GetDOMRule();
+        if (domRule) {
+          rules->InsertElementAt(domRule, 0);
+        }
+      }
     }
   }
 
   rules.forget(_retval);
 
   return NS_OK;
 }
 
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -2626,17 +2626,17 @@ StyleAnimationValue::ComputeValues(
   RefPtr<nsStyleContext> tmpStyleContext;
   if (aIsContextSensitive) {
     MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty),
                "to correctly set aIsContextSensitive for shorthand properties, "
                "this code must be adjusted");
 
     nsCOMArray<nsIStyleRule> ruleArray;
     ruleArray.AppendObject(styleSet->InitialStyleRule());
-    ruleArray.AppendObject(aStyleRule);
+    ruleArray.AppendObject(aStyleRule->GetDeclaration());
     aStyleRule->RuleMatched();
     tmpStyleContext =
       styleSet->ResolveStyleByAddingRules(styleContext, ruleArray);
     if (!tmpStyleContext) {
       return false;
     }
 
     // Force walk of rule tree
@@ -2653,17 +2653,17 @@ StyleAnimationValue::ComputeValues(
   // If we're not concerned whether the property is context sensitive then just
   // add the rule to a new temporary style context alongside the target
   // element's style context.
   // Also, if we previously discovered that this property IS context-sensitive
   // then we need to throw the temporary style context out since the property's
   // value may have been biased by the 'initial' values supplied.
   if (!aIsContextSensitive || *aIsContextSensitive) {
     nsCOMArray<nsIStyleRule> ruleArray;
-    ruleArray.AppendObject(aStyleRule);
+    ruleArray.AppendObject(aStyleRule->GetDeclaration());
     aStyleRule->RuleMatched();
     tmpStyleContext =
       styleSet->ResolveStyleByAddingRules(styleContext, ruleArray);
     if (!tmpStyleContext) {
       return false;
     }
   }
 
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -627,17 +627,17 @@ ResolvedStyleCache::Get(nsPresContext *a
   if (!result) {
     Declaration* declaration = aKeyframe->Declaration();
     declaration->SetImmutable();
     // The spec says that !important declarations should just be ignored
     MOZ_ASSERT(!declaration->HasImportantData(),
                "Keyframe rule has !important data");
 
     nsCOMArray<nsIStyleRule> rules;
-    rules.AppendObject(aKeyframe);
+    rules.AppendObject(declaration);
     RefPtr<nsStyleContext> resultStrong = aPresContext->StyleSet()->
       ResolveStyleByAddingRules(aParentStyleContext, rules);
     mCache.Put(aKeyframe, resultStrong);
     result = resultStrong;
   }
   return result;
 }
 
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2615,17 +2615,17 @@ void ContentEnumFunc(const RuleValue& va
     if (!next ||
         SelectorMatchesTree(data->mElement, next,
                             data->mTreeMatchContext,
                             nodeContext.mIsRelevantLink ?
                               SelectorMatchesTreeFlags(0) :
                               eLookForRelevantLink)) {
       css::StyleRule *rule = value.mRule;
       rule->RuleMatched();
-      data->mRuleWalker->Forward(rule);
+      data->mRuleWalker->Forward(rule->GetDeclaration());
       // nsStyleSet will deal with the !important rule
     }
   }
 }
 
 /* virtual */ void
 nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
 {
@@ -2661,17 +2661,17 @@ nsCSSRuleProcessor::RulesMatching(AnonBo
   if (cascade && cascade->mAnonBoxRules.EntryCount()) {
     auto entry = static_cast<RuleHashTagTableEntry*>
                             (cascade->mAnonBoxRules.Search(aData->mPseudoTag));
     if (entry) {
       nsTArray<RuleValue>& rules = entry->mRules;
       for (RuleValue *value = rules.Elements(), *end = value + rules.Length();
            value != end; ++value) {
         value->mRule->RuleMatched();
-        aData->mRuleWalker->Forward(value->mRule);
+        aData->mRuleWalker->Forward(value->mRule->GetDeclaration());
       }
     }
   }
 }
 
 #ifdef MOZ_XUL
 /* virtual */ void
 nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -63,27 +63,27 @@ 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) {
     rule->RuleMatched();
-    aRuleWalker->Forward(rule);
+    aRuleWalker->Forward(rule->GetDeclaration());
   }
 
   rule = aElement->GetSMILOverrideStyleRule();
   if (rule) {
     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.
       rule->RuleMatched();
-      aRuleWalker->Forward(rule);
+      aRuleWalker->Forward(rule->GetDeclaration());
     }
   }
 }
 
 void
 nsHTMLCSSStyleSheet::PseudoElementRulesMatching(Element* aPseudoElement,
                                                 nsCSSPseudoElements::Type
                                                   aPseudoType,
@@ -92,17 +92,17 @@ nsHTMLCSSStyleSheet::PseudoElementRulesM
   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) {
     rule->RuleMatched();
-    aRuleWalker->Forward(rule);
+    aRuleWalker->Forward(rule->GetDeclaration());
   }
 }
 
 /* virtual */ void
 nsHTMLCSSStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
 {
   if (nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aData->mPseudoType) &&
       aData->mPseudoElement) {
--- a/layout/style/nsRuleWalker.h
+++ b/layout/style/nsRuleWalker.h
@@ -8,17 +8,17 @@
  * rules are matched
  */
 
 #ifndef nsRuleWalker_h_
 #define nsRuleWalker_h_
 
 #include "nsRuleNode.h"
 #include "nsIStyleRule.h"
-#include "StyleRule.h"
+#include "Declaration.h"
 #include "nsQueryObject.h"
 
 class nsRuleWalker {
 public:
   nsRuleNode* CurrentNode() { return mCurrent; }
   void SetCurrentNode(nsRuleNode* aNode) {
     NS_ASSERTION(aNode, "Must have node here!");
     mCurrent = aNode;
@@ -29,24 +29,24 @@ public:
 protected:
   void DoForward(nsIStyleRule* aRule) {
     mCurrent = mCurrent->Transition(aRule, mLevel, mImportance);
     NS_POSTCONDITION(mCurrent, "Transition messed up");
   }
 
 public:
   void Forward(nsIStyleRule* aRule) {
-    NS_PRECONDITION(!RefPtr<mozilla::css::StyleRule>(do_QueryObject(aRule)),
+    NS_PRECONDITION(!RefPtr<mozilla::css::Declaration>(do_QueryObject(aRule)),
                     "Calling the wrong Forward() overload");
     DoForward(aRule);
   }
-  void Forward(mozilla::css::StyleRule* aRule) {
+  void Forward(mozilla::css::Declaration* aRule) {
     DoForward(aRule);
     mCheckForImportantRules =
-      mCheckForImportantRules && !aRule->GetImportantRule();
+      mCheckForImportantRules && !aRule->HasImportantData();
   }
   // ForwardOnPossiblyCSSRule should only be used by callers that have
   // an explicit list of rules they need to walk, with the list
   // already containing any important rules they care about.
   void ForwardOnPossiblyCSSRule(nsIStyleRule* aRule) {
     DoForward(aRule);
   }
 
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -1034,21 +1034,21 @@ nsStyleSet::AddImportantRules(nsRuleNode
   NS_ASSERTION(aCurrLevelNode &&
                aCurrLevelNode != aLastPrevLevelNode, "How did we get here?");
 
   nsAutoTArray<nsIStyleRule*, 16> importantRules;
   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
        node = node->GetParent()) {
     // We guarantee that we never walk the root node here, so no need
     // to null-check GetRule().  Furthermore, it must be a CSS rule.
-    NS_ASSERTION(RefPtr<css::StyleRule>(do_QueryObject(node->GetRule())),
+    NS_ASSERTION(RefPtr<css::Declaration>(do_QueryObject(node->GetRule())),
                  "Unexpected non-CSS rule");
 
     nsIStyleRule* impRule =
-      static_cast<css::StyleRule*>(node->GetRule())->GetImportantRule();
+      static_cast<css::Declaration*>(node->GetRule())->GetImportantStyleData();
     if (impRule)
       importantRules.AppendElement(impRule);
   }
 
   NS_ASSERTION(importantRules.Length() != 0,
                "Why did we think there were important rules?");
 
   for (uint32_t i = importantRules.Length(); i-- != 0; ) {
@@ -1061,35 +1061,41 @@ void
 nsStyleSet::AssertNoImportantRules(nsRuleNode* aCurrLevelNode,
                                    nsRuleNode* aLastPrevLevelNode)
 {
   if (!aCurrLevelNode)
     return;
 
   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
        node = node->GetParent()) {
-    RefPtr<css::StyleRule> rule(do_QueryObject(node->GetRule()));
-    NS_ASSERTION(rule, "Unexpected non-CSS rule");
+    RefPtr<css::Declaration> declaration(do_QueryObject(node->GetRule()));
+    NS_ASSERTION(declaration, "Unexpected non-CSS rule");
 
-    NS_ASSERTION(!rule->GetImportantRule(), "Unexpected important rule");
+    NS_ASSERTION(!declaration->GetImportantStyleData(),
+                 "Unexpected important style source");
   }
 }
 
 void
 nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
                              nsRuleNode* aLastPrevLevelNode)
 {
   if (!aCurrLevelNode)
     return;
 
   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
        node = node->GetParent()) {
     nsIStyleRule *rule = node->GetRule();
-    RefPtr<css::StyleRule> cssRule(do_QueryObject(rule));
-    NS_ASSERTION(!cssRule || !cssRule->Selector(), "Unexpected CSS rule");
+    RefPtr<css::Declaration> declaration(do_QueryObject(rule));
+    if (declaration) {
+      RefPtr<css::StyleRule> cssRule =
+        do_QueryObject(declaration->GetOwningRule());
+      NS_ASSERTION(!cssRule || !cssRule->Selector(),
+                   "Unexpected CSS rule");
+    }
   }
 }
 #endif
 
 // Enumerate the rules in a way that cares about the order of the rules.
 void
 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, 
                       RuleProcessorData* aData, Element* aElement,
@@ -1958,19 +1964,21 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsI
             &ruleWalker);
 
   if (aPseudoTag == nsCSSAnonBoxes::pageContent) {
     // Add any @page rules that are specified.
     nsTArray<nsCSSPageRule*> rules;
     nsTArray<css::ImportantStyleData*> importantRules;
     PresContext()->StyleSet()->AppendPageRules(rules);
     for (uint32_t i = 0, i_end = rules.Length(); i != i_end; ++i) {
-      rules[i]->Declaration()->SetImmutable();
-      ruleWalker.Forward(rules[i]);
-      css::ImportantStyleData* importantRule = rules[i]->GetImportantRule();
+      css::Declaration* declaration = rules[i]->Declaration();
+      declaration->SetImmutable();
+      ruleWalker.Forward(declaration);
+      css::ImportantStyleData* importantRule =
+        declaration->GetImportantStyleData();
       if (importantRule) {
         importantRules.AppendElement(importantRule);
       }
     }
     for (uint32_t i = 0, i_end = importantRules.Length(); i != i_end; ++i) {
       ruleWalker.Forward(importantRules[i]);
     }
   }
--- a/layout/style/test/test_animations_dynamic_changes.html
+++ b/layout/style/test/test_animations_dynamic_changes.html
@@ -41,24 +41,24 @@ function test_bug978833() {
   // Temporarily remove the animation style, since we resolve keyframes
   // on top of current animation styles (although maybe we shouldn't),
   // so we need to remove those styles to hit the rule tree cache.
   p.classList.remove("alwaysa");
   is(cs.marginLeft, "0px", "p margin-left should be 0px without animation");
 
   p.classList.add("alwaysa");
   kf.style.marginLeft = "100px";
-  todo_is(cs.marginLeft, "100px", "p margin-left should be 100px after change");
+  is(cs.marginLeft, "100px", "p margin-left should be 100px after change");
 
   // Try the same thing a second time, just to make sure it works again.
   p.classList.remove("alwaysa");
   is(cs.marginLeft, "0px", "p margin-left should be 0px without animation");
   p.classList.add("alwaysa");
   kf.style.marginLeft = "150px";
-  todo_is(cs.marginLeft, "150px", "p margin-left should be 150px after second change");
+  is(cs.marginLeft, "150px", "p margin-left should be 150px after second change");
 
   p.style.animation = "";
 }
 test_bug978833();
 
 </script>
 </pre>
 </body>