Bug 1315601 part 9 - Split Gecko-specific GroupRule logic into a separate struct. r=heycam draft
authorXidorn Quan <me@upsuper.org>
Thu, 09 Mar 2017 22:02:26 +1100
changeset 497345 04cb9ea11e01a4f57497b4edf148adbd4fc1311b
parent 497344 6051886a6695e01f811fecdcdbf2274b2dd470e9
child 497346 a51c88fd19cf85376a52b4c61b3bd84df6356dab
push id48869
push userxquan@mozilla.com
push dateMon, 13 Mar 2017 06:50:23 +0000
reviewersheycam
bugs1315601
milestone55.0a1
Bug 1315601 part 9 - Split Gecko-specific GroupRule logic into a separate struct. r=heycam MozReview-Commit-ID: 7CkGO2KgJN3
layout/style/GroupRule.cpp
layout/style/GroupRule.h
layout/style/nsCSSRules.cpp
--- a/layout/style/GroupRule.cpp
+++ b/layout/style/GroupRule.cpp
@@ -13,16 +13,22 @@
 
 #include "mozilla/dom/CSSRuleList.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace css {
 
+// TODO The other branch should be changed to Servo rule.
+#define CALL_INNER(inner_, call_)               \
+  ((inner_).is<GeckoGroupRuleRules>()           \
+    ? (inner_).as<GeckoGroupRuleRules>().call_  \
+    : (inner_).as<GeckoGroupRuleRules>().call_)
+
 // -------------------------------
 // Style Rule List for group rules
 //
 
 class GroupRuleRuleList final : public dom::CSSRuleList
 {
 public:
   explicit GroupRuleRuleList(GroupRule *aGroupRule);
@@ -86,209 +92,242 @@ GroupRuleRuleList::IndexedGetter(uint32_
       return rule;
     }
   }
 
   return nullptr;
 }
 
 // -------------------------------
-// GroupRule
+// GeckoGroupRuleRules
 //
 
-GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
-  : Rule(aLineNumber, aColumnNumber)
+GeckoGroupRuleRules::GeckoGroupRuleRules()
 {
 }
 
-GroupRule::GroupRule(const GroupRule& aCopy)
-  : Rule(aCopy)
+GeckoGroupRuleRules::GeckoGroupRuleRules(GeckoGroupRuleRules&& aOther)
+  : mRules(Move(aOther.mRules))
+  , mRuleCollection(Move(aOther.mRuleCollection))
+{
+}
+
+GeckoGroupRuleRules::GeckoGroupRuleRules(const GeckoGroupRuleRules& aCopy)
 {
   for (const Rule* rule : aCopy.mRules) {
     RefPtr<Rule> clone = rule->Clone();
     mRules.AppendObject(clone);
-    clone->SetParentRule(this);
   }
 }
 
-GroupRule::~GroupRule()
+GeckoGroupRuleRules::~GeckoGroupRuleRules()
 {
-  MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
   for (Rule* rule : mRules) {
     rule->SetParentRule(nullptr);
   }
   if (mRuleCollection) {
     mRuleCollection->DropReference();
   }
 }
 
+void
+GeckoGroupRuleRules::Clear()
+{
+  mRules.Clear();
+  if (mRuleCollection) {
+    mRuleCollection->DropReference();
+    mRuleCollection = nullptr;
+  }
+}
+
+void
+GeckoGroupRuleRules::Traverse(nsCycleCollectionTraversalCallback& cb)
+{
+  IncrementalClearCOMRuleArray& rules = mRules;
+  for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
+    if (!rules[i]->IsCCLeaf()) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
+      cb.NoteXPCOMChild(rules[i]);
+    }
+  }
+  ImplCycleCollectionTraverse(cb, mRuleCollection, "mRuleCollection");
+}
+
+#ifdef DEBUG
+void
+GeckoGroupRuleRules::List(FILE* out, int32_t aIndent) const
+{
+  for (const Rule* rule : mRules) {
+    rule->List(out, aIndent + 1);
+  }
+}
+#endif
+
+nsresult
+GeckoGroupRuleRules::DeleteStyleRuleAt(uint32_t aIndex)
+{
+  Rule* rule = mRules.SafeObjectAt(aIndex);
+  if (rule) {
+    rule->SetStyleSheet(nullptr);
+    rule->SetParentRule(nullptr);
+  }
+  return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
+}
+
+CSSRuleList*
+GeckoGroupRuleRules::CssRules(GroupRule* aParentRule)
+{
+  if (!mRuleCollection) {
+    mRuleCollection = new GroupRuleRuleList(aParentRule);
+  }
+  return mRuleCollection;
+}
+
+size_t
+GeckoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (const Rule* rule : mRules) {
+    n += rule->SizeOfIncludingThis(aMallocSizeOf);
+  }
+
+  // Measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - mRuleCollection
+  return n;
+}
+
+// -------------------------------
+// GroupRule
+//
+
+GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
+  : Rule(aLineNumber, aColumnNumber)
+  , mInner(GeckoGroupRuleRules())
+{
+}
+
+GroupRule::GroupRule(const GroupRule& aCopy)
+  : Rule(aCopy)
+  , mInner(aCopy.mInner)
+{
+  CALL_INNER(mInner, SetParentRule(this));
+}
+
+GroupRule::~GroupRule()
+{
+  MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
+}
+
 NS_IMPL_ADDREF_INHERITED(GroupRule, Rule)
 NS_IMPL_RELEASE_INHERITED(GroupRule, Rule)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GroupRule)
 NS_INTERFACE_MAP_END_INHERITING(Rule)
 
 bool
 GroupRule::IsCCLeaf() const
 {
   // Let's not worry for now about sorting out whether we're a leaf or not.
   return false;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GroupRule, Rule)
-  for (Rule* rule : tmp->mRules) {
-    rule->SetParentRule(nullptr);
-  }
+  CALL_INNER(tmp->mInner, SetParentRule(nullptr));
   // If tmp does not have a stylesheet, neither do its descendants.  In that
   // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
   // depth of group rule nesting.  But if tmp _does_ have a stylesheet (which
   // can happen if it gets unlinked earlier than its owning stylesheet), then we
   // need to null out the stylesheet pointer on descendants now, before we clear
   // tmp->mRules.
   if (tmp->GetStyleSheet()) {
-    for (Rule* rule : tmp->mRules) {
-      rule->SetStyleSheet(nullptr);
-    }
+    CALL_INNER(tmp->mInner, SetStyleSheet(nullptr));
   }
-  tmp->mRules.Clear();
-  if (tmp->mRuleCollection) {
-    tmp->mRuleCollection->DropReference();
-    tmp->mRuleCollection = nullptr;
-  }
+  CALL_INNER(tmp->mInner, Clear());
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GroupRule, Rule)
-  const nsCOMArray<Rule>& rules = tmp->mRules;
-  for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
-    if (!rules[i]->IsCCLeaf()) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
-      cb.NoteXPCOMChild(rules[i]);
-    }
-  }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection)
+  CALL_INNER(tmp->mInner, Traverse(cb));
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 /* virtual */ void
 GroupRule::SetStyleSheet(StyleSheet* aSheet)
 {
   // Don't set the sheet on the kids if it's already the same as the sheet we
   // already have.  This is needed to avoid O(N^2) behavior in group nesting
   // depth when seting the sheet to null during unlink, if we happen to unlin in
   // order from most nested rule up to least nested rule.
   if (aSheet != GetStyleSheet()) {
-    for (Rule* rule : mRules) {
-      rule->SetStyleSheet(aSheet);
-    }
+    CALL_INNER(mInner, SetStyleSheet(aSheet));
     Rule::SetStyleSheet(aSheet);
   }
 }
 
-#ifdef DEBUG
-/* virtual */ void
-GroupRule::List(FILE* out, int32_t aIndent) const
-{
-  for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
-    mRules.ObjectAt(index)->List(out, aIndent + 1);
-  }
-}
-#endif
-
 void
 GroupRule::AppendStyleRule(Rule* aRule)
 {
-  mRules.AppendObject(aRule);
+  GeckoRules().AppendObject(aRule);
   StyleSheet* sheet = GetStyleSheet();
   aRule->SetStyleSheet(sheet);
   aRule->SetParentRule(this);
   if (sheet) {
     sheet->AsGecko()->SetModifiedByChildRule();
   }
 }
 
-Rule*
-GroupRule::GetStyleRuleAt(int32_t aIndex) const
-{
-  return mRules.SafeObjectAt(aIndex);
-}
-
 bool
 GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
 {
-  for (const Rule* rule : mRules) {
+  for (const Rule* rule : GeckoRules()) {
     if (!aFunc(const_cast<Rule*>(rule), aData)) {
       return false;
     }
   }
   return true;
 }
 
-/*
- * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
- * should never be called unless you have first called WillDirty() on
- * the parents stylesheet.  After they are called, DidDirty() needs to
- * be called on the sheet
- */
-nsresult
-GroupRule::DeleteStyleRuleAt(uint32_t aIndex)
-{
-  Rule* rule = mRules.SafeObjectAt(aIndex);
-  if (rule) {
-    rule->SetStyleSheet(nullptr);
-    rule->SetParentRule(nullptr);
-  }
-  return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
-}
-
 nsresult
 GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
 {
   aRule->SetStyleSheet(GetStyleSheet());
   aRule->SetParentRule(this);
-  if (! mRules.InsertObjectAt(aRule, aIndex)) {
+  if (!GeckoRules().InsertObjectAt(aRule, aIndex)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 void
 GroupRule::AppendRulesToCssText(nsAString& aCssText) const
 {
   aCssText.AppendLiteral(" {\n");
-
-  // get all the rules
-  for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
-    Rule* rule = mRules.ObjectAt(index);
+  for (const Rule* rule : GeckoRules()) {
     nsAutoString cssText;
     rule->GetCssText(cssText);
     aCssText.AppendLiteral("  ");
     aCssText.Append(cssText);
     aCssText.Append('\n');
   }
-
   aCssText.Append('}');
 }
 
 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
 nsresult
 GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
 {
   NS_ADDREF(*aRuleList = CssRules());
   return NS_OK;
 }
 
 CSSRuleList*
 GroupRule::CssRules()
 {
-  if (!mRuleCollection) {
-    mRuleCollection = new css::GroupRuleRuleList(this);
-  }
-
-  return mRuleCollection;
+  return CALL_INNER(mInner, CssRules(this));
 }
 
 nsresult
 GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
 {
   ErrorResult rv;
   *_retval = InsertRule(aRule, aIndex, rv);
   return rv.StealNSResult();
@@ -298,23 +337,23 @@ uint32_t
 GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex, ErrorResult& aRv)
 {
   StyleSheet* sheet = GetStyleSheet();
   if (NS_WARN_IF(!sheet)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return 0;
   }
 
-  if (aIndex > uint32_t(mRules.Count())) {
+  uint32_t count = StyleRuleCount();
+  if (aIndex > count) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return 0;
   }
 
-  NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
-               "Too many style rules!");
+  NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
 
   uint32_t retval;
   nsresult rv =
     sheet->AsGecko()->InsertRuleIntoGroup(aRule, this, aIndex, &retval);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return 0;
   }
@@ -333,39 +372,26 @@ void
 GroupRule::DeleteRule(uint32_t aIndex, ErrorResult& aRv)
 {
   StyleSheet* sheet = GetStyleSheet();
   if (NS_WARN_IF(!sheet)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  if (aIndex >= uint32_t(mRules.Count())) {
+  uint32_t count = StyleRuleCount();
+  if (aIndex >= count) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
-  NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
-               "Too many style rules!");
+  NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
 
   nsresult rv = sheet->AsGecko()->DeleteRuleFromGroup(this, aIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
-/* virtual */ size_t
-GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
-{
-  size_t n = mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  for (size_t i = 0; i < mRules.Length(); i++) {
-    n += mRules[i]->SizeOfIncludingThis(aMallocSizeOf);
-  }
-
-  // Measurement of the following members may be added later if DMD finds it is
-  // worthwhile:
-  // - mRuleCollection
-  return n;
-}
-
+#undef CALL_INNER
 
 } // namespace css
-} // namespace mozill
+} // namespace mozilla
--- a/layout/style/GroupRule.h
+++ b/layout/style/GroupRule.h
@@ -10,75 +10,130 @@
 
 #ifndef mozilla_css_GroupRule_h__
 #define mozilla_css_GroupRule_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/IncrementalClearCOMRuleArray.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Variant.h"
 #include "mozilla/css/Rule.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsPresContext;
 class nsMediaQueryResultCacheKey;
 
 namespace mozilla {
 
 class StyleSheet;
 
 namespace dom {
 class CSSRuleList;
 } // namespace dom
 
 namespace css {
 
+class GroupRule;
 class GroupRuleRuleList;
 
+struct GeckoGroupRuleRules
+{
+  GeckoGroupRuleRules();
+  GeckoGroupRuleRules(GeckoGroupRuleRules&& aOther);
+  GeckoGroupRuleRules(const GeckoGroupRuleRules& aCopy);
+  ~GeckoGroupRuleRules();
+
+  void SetParentRule(GroupRule* aParentRule) {
+    for (Rule* rule : mRules) {
+      rule->SetParentRule(aParentRule);
+    }
+  }
+  void SetStyleSheet(StyleSheet* aSheet) {
+    for (Rule* rule : mRules) {
+      rule->SetStyleSheet(aSheet);
+    }
+  }
+
+  void Clear();
+  void Traverse(nsCycleCollectionTraversalCallback& cb);
+
+#ifdef DEBUG
+  void List(FILE* out, int32_t aIndent) const;
+#endif
+
+  int32_t StyleRuleCount() const { return mRules.Count(); }
+  Rule* GetStyleRuleAt(int32_t aIndex) const {
+    return mRules.SafeObjectAt(aIndex);
+  }
+
+  nsresult DeleteStyleRuleAt(uint32_t aIndex);
+
+  dom::CSSRuleList* CssRules(GroupRule* aParentRule);
+
+  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
+
+  IncrementalClearCOMRuleArray mRules;
+  RefPtr<GroupRuleRuleList> mRuleCollection; // lazily constructed
+};
+
+#define REDIRECT_TO_INNER(call_) \
+  return mInner.as<GeckoGroupRuleRules>().call_;
+
 // inherits from Rule so it can be shared between
 // MediaRule and DocumentRule
 class GroupRule : public Rule
 {
 protected:
   GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber);
   GroupRule(const GroupRule& aCopy);
   virtual ~GroupRule();
 public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(GroupRule, Rule)
   NS_DECL_ISUPPORTS_INHERITED
   virtual bool IsCCLeaf() const override;
 
 #ifdef DEBUG
-  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
+  void List(FILE* out = stdout, int32_t aIndent = 0) const override {
+    REDIRECT_TO_INNER(List(out, aIndent))
+  }
 #endif
   virtual void SetStyleSheet(StyleSheet* aSheet) override;
 
 public:
   void AppendStyleRule(Rule* aRule);
 
-  int32_t StyleRuleCount() const { return mRules.Count(); }
-  Rule* GetStyleRuleAt(int32_t aIndex) const;
+  int32_t StyleRuleCount() const {
+    REDIRECT_TO_INNER(StyleRuleCount())
+  }
+  Rule* GetStyleRuleAt(uint32_t aIndex) const {
+    REDIRECT_TO_INNER(GetStyleRuleAt(aIndex))
+  }
 
   typedef bool (*RuleEnumFunc)(Rule* aElement, void* aData);
   bool EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const;
 
   /*
-   * The next three methods should never be called unless you have first
+   * The next two methods should never be called unless you have first
    * called WillDirty() on the parent stylesheet.  After they are
    * called, DidDirty() needs to be called on the sheet.
    */
-  nsresult DeleteStyleRuleAt(uint32_t aIndex);
+  nsresult DeleteStyleRuleAt(uint32_t aIndex) {
+    REDIRECT_TO_INNER(DeleteStyleRuleAt(aIndex));
+  }
   nsresult InsertStyleRuleAt(uint32_t aIndex, Rule* aRule);
 
   virtual bool UseForPresentation(nsPresContext* aPresContext,
                                     nsMediaQueryResultCacheKey& aKey) = 0;
 
   // non-virtual -- it is only called by subclasses
-  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+    REDIRECT_TO_INNER(SizeOfExcludingThis(aMallocSizeOf))
+  }
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override = 0;
 
   // WebIDL API
   dom::CSSRuleList* CssRules();
   uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
                       ErrorResult& aRv);
   void DeleteRule(uint32_t aIndex, ErrorResult& aRv);
 
@@ -88,20 +143,30 @@ protected:
 
   // to implement common methods on nsIDOMCSSMediaRule and
   // nsIDOMCSSMozDocumentRule
   nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList);
   nsresult InsertRule(const nsAString & aRule, uint32_t aIndex,
                       uint32_t* _retval);
   nsresult DeleteRule(uint32_t aIndex);
 
-  IncrementalClearCOMRuleArray mRules;
-  RefPtr<GroupRuleRuleList> mRuleCollection; // lazily constructed
+  // Must only be called if this is a Gecko GroupRule.
+  IncrementalClearCOMRuleArray& GeckoRules() {
+    return mInner.as<GeckoGroupRuleRules>().mRules;
+  }
+  const IncrementalClearCOMRuleArray& GeckoRules() const {
+    return mInner.as<GeckoGroupRuleRules>().mRules;
+  }
+
+private:
+  Variant<GeckoGroupRuleRules> mInner;
 };
 
+#undef REDIRECT_TO_INNER
+
 // Implementation of WebIDL CSSConditionRule.
 class ConditionRule : public GroupRule
 {
 protected:
   using GroupRule::GroupRule;
 
 public:
   // GetConditionText signature matches nsIDOMCSSConditionRule, so subclasses
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -1993,18 +1993,18 @@ nsCSSKeyframesRule::Type() const
 
 void
 nsCSSKeyframesRule::GetCssTextImpl(nsAString& aCssText) const
 {
   aCssText.AssignLiteral("@keyframes ");
   aCssText.Append(mName);
   aCssText.AppendLiteral(" {\n");
   nsAutoString tmp;
-  for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) {
-    static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp);
+  for (const Rule* rule : GeckoRules()) {
+    static_cast<const nsCSSKeyframeRule*>(rule)->GetCssText(tmp);
     aCssText.Append(tmp);
     aCssText.Append('\n');
   }
   aCssText.Append('}');
 }
 
 NS_IMETHODIMP
 nsCSSKeyframesRule::GetName(nsAString& aName)
@@ -2074,23 +2074,24 @@ static const uint32_t RULE_NOT_FOUND = u
 uint32_t
 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
 {
   nsCSSParser parser;
 
   InfallibleTArray<float> keys;
   // FIXME: pass filename and line number
   if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
+    IncrementalClearCOMRuleArray& rules = GeckoRules();
     // The spec isn't clear, but we'll match on the key list, which
     // mostly matches what WebKit does, except we'll do last-match
     // instead of first-match, and handling parsing differences better.
     // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
     // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
-    for (uint32_t i = mRules.Count(); i-- != 0; ) {
-      if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) {
+    for (uint32_t i = rules.Count(); i-- != 0; ) {
+      if (static_cast<nsCSSKeyframeRule*>(rules[i])->GetKeys() == keys) {
         return i;
       }
     }
   }
 
   return RULE_NOT_FOUND;
 }
 
@@ -2125,17 +2126,17 @@ nsCSSKeyframesRule::FindRule(const nsASt
 
 nsCSSKeyframeRule*
 nsCSSKeyframesRule::FindRule(const nsAString& aKey)
 {
   uint32_t index = FindRuleIndexForKey(aKey);
   if (index == RULE_NOT_FOUND) {
     return nullptr;
   }
-  return static_cast<nsCSSKeyframeRule*>(mRules[index]);
+  return static_cast<nsCSSKeyframeRule*>(GeckoRules()[index]);
 }
 
 // GroupRule interface
 /* virtual */ bool
 nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
                                        nsMediaQueryResultCacheKey& aKey)
 {
   MOZ_ASSERT(false, "should not be called");