Bug 1359217 part 4 - Add ServoStyleRuleMap to handle style rule mapping. r?heycam draft
authorXidorn Quan <me@upsuper.org>
Sat, 10 Jun 2017 09:58:04 +1000
changeset 593008 294911431d45834d300a750852bce55245049ed8
parent 593001 561a4afe27245b2d914c275b1d27665553e954b3
child 633000 b334a55643ef12767c148d8b584c9f13c17ca43c
push id63576
push userxquan@mozilla.com
push dateTue, 13 Jun 2017 04:26:14 +0000
reviewersheycam
bugs1359217
milestone56.0a1
Bug 1359217 part 4 - Add ServoStyleRuleMap to handle style rule mapping. r?heycam This commit adds class ServoStyleRuleMap which caches the mapping from raw Servo style rule to Gecko's wrapper object. It is a per-document object, and is added as an observer of document when constructed, so that it updates data inside when possible. MozReview-Commit-ID: YxBnZ88tjf
layout/inspector/ServoStyleRuleMap.cpp
layout/inspector/ServoStyleRuleMap.h
layout/inspector/inDOMUtils.cpp
layout/inspector/moz.build
layout/style/ServoCSSRuleList.cpp
layout/style/ServoCSSRuleList.h
layout/style/ServoStyleRule.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
layout/style/StyleSheet.cpp
new file mode 100644
--- /dev/null
+++ b/layout/inspector/ServoStyleRuleMap.cpp
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ServoStyleRuleMap.h"
+
+#include "mozilla/css/GroupRule.h"
+#include "mozilla/IntegerRange.h"
+#include "mozilla/ServoStyleRule.h"
+#include "mozilla/ServoStyleSet.h"
+#include "mozilla/ServoImportRule.h"
+
+#include "nsDocument.h"
+#include "nsStyleSheetService.h"
+
+namespace mozilla {
+
+ServoStyleRuleMap::ServoStyleRuleMap(ServoStyleSet* aStyleSet)
+  : mStyleSet(aStyleSet)
+{
+}
+
+ServoStyleRuleMap::~ServoStyleRuleMap()
+{
+}
+
+NS_IMPL_ISUPPORTS(ServoStyleRuleMap, nsIDocumentObserver)
+
+void
+ServoStyleRuleMap::EnsureTable()
+{
+  if (!IsEmpty()) {
+    return;
+  }
+  mStyleSet->EnumerateStyleSheetArrays(
+    [this](const nsTArray<RefPtr<ServoStyleSheet>>& aArray) {
+      for (auto& sheet : aArray) {
+        FillTableFromStyleSheet(sheet);
+      }
+    });
+}
+
+void
+ServoStyleRuleMap::StyleSheetAdded(StyleSheet* aStyleSheet,
+                                   bool aDocumentSheet)
+{
+  if (!IsEmpty()) {
+    FillTableFromStyleSheet(aStyleSheet->AsServo());
+  }
+}
+
+void
+ServoStyleRuleMap::StyleSheetRemoved(StyleSheet* aStyleSheet,
+                                     bool aDocumentSheet)
+{
+  // Invalidate all data inside. This isn't strictly necessary since
+  // we should always get update from document before new queries come.
+  // But it is probably still safer if we try to avoid having invalid
+  // pointers inside. Also if the document keep adding and removing
+  // stylesheets, this would also prevent us from infinitely growing
+  // memory usage.
+  mTable.Clear();
+}
+
+void
+ServoStyleRuleMap::StyleSheetApplicableStateChanged(StyleSheet* aStyleSheet)
+{
+  // We don't care if the stylesheet is disabled. Not removing no longer
+  // applicable stylesheets wouldn't make anything wrong.
+  if (!IsEmpty() && aStyleSheet->IsApplicable()) {
+    FillTableFromStyleSheet(aStyleSheet->AsServo());
+  }
+}
+
+void
+ServoStyleRuleMap::StyleRuleAdded(StyleSheet* aStyleSheet,
+                                  css::Rule* aStyleRule)
+{
+  if (!IsEmpty()) {
+    FillTableFromRule(aStyleRule);
+  }
+}
+
+void
+ServoStyleRuleMap::StyleRuleRemoved(StyleSheet* aStyleSheet,
+                                    css::Rule* aStyleRule)
+{
+  if (IsEmpty()) {
+    return;
+  }
+
+  auto type = aStyleRule->Type();
+  switch (aStyleRule->Type()) {
+    case nsIDOMCSSRule::STYLE_RULE: {
+      auto rule = static_cast<ServoStyleRule*>(aStyleRule);
+      mTable.Remove(rule->Raw());
+      break;
+    }
+    case nsIDOMCSSRule::IMPORT_RULE:
+    case nsIDOMCSSRule::MEDIA_RULE:
+    case nsIDOMCSSRule::SUPPORTS_RULE:
+    case nsIDOMCSSRule::DOCUMENT_RULE: {
+      // See the comment in StyleSheetRemoved.
+      mTable.Clear();
+      break;
+    }
+  }
+}
+
+size_t
+ServoStyleRuleMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+  n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  return n;
+}
+
+void
+ServoStyleRuleMap::FillTableFromRule(css::Rule* aRule)
+{
+  switch (aRule->Type()) {
+    case nsIDOMCSSRule::STYLE_RULE: {
+      auto rule = static_cast<ServoStyleRule*>(aRule);
+      mTable.Put(rule->Raw(), rule);
+      break;
+    }
+    case nsIDOMCSSRule::MEDIA_RULE:
+    case nsIDOMCSSRule::SUPPORTS_RULE:
+    case nsIDOMCSSRule::DOCUMENT_RULE: {
+      auto rule = static_cast<css::GroupRule*>(aRule);
+      auto ruleList = static_cast<ServoCSSRuleList*>(rule->CssRules());
+      FillTableFromRuleList(ruleList);
+      break;
+    }
+    case nsIDOMCSSRule::IMPORT_RULE: {
+      auto rule = static_cast<ServoImportRule*>(aRule);
+      FillTableFromStyleSheet(rule->GetStyleSheet()->AsServo());
+      break;
+    }
+  }
+}
+
+void
+ServoStyleRuleMap::FillTableFromRuleList(ServoCSSRuleList* aRuleList)
+{
+  for (uint32_t i : IntegerRange(aRuleList->Length())) {
+    FillTableFromRule(aRuleList->GetRule(i));
+  }
+}
+
+void
+ServoStyleRuleMap::FillTableFromStyleSheet(ServoStyleSheet* aSheet)
+{
+  nsAutoCString url;
+  aSheet->GetSheetURI()->GetSpec(url);
+  FillTableFromRuleList(aSheet->GetCssRulesInternal());
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/inspector/ServoStyleRuleMap.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ServoStyleRuleMap_h
+#define mozilla_ServoStyleRuleMap_h
+
+#include "nsDataHashtable.h"
+#include "nsStubDocumentObserver.h"
+
+struct RawServoStyleRule;
+
+namespace mozilla {
+class ServoCSSRuleList;
+class ServoStyleRule;
+class ServoStyleSet;
+namespace css {
+class Rule;
+} // namespace css
+
+class ServoStyleRuleMap final : public nsStubDocumentObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit ServoStyleRuleMap(ServoStyleSet* aStyleSet);
+
+  void EnsureTable();
+  ServoStyleRule* Lookup(const RawServoStyleRule* aRawRule) const {
+    return mTable.Get(aRawRule);
+  }
+
+  // nsIDocumentObserver methods
+  void StyleSheetAdded(StyleSheet* aStyleSheet, bool aDocumentSheet) final;
+  void StyleSheetRemoved(StyleSheet* aStyleSheet, bool aDocumentSheet) final;
+  void StyleSheetApplicableStateChanged(StyleSheet* aStyleSheet) final;
+  void StyleRuleAdded(StyleSheet* aStyleSheet, css::Rule* aStyleRule) final;
+  void StyleRuleRemoved(StyleSheet* aStyleSheet, css::Rule* aStyleRule) final;
+
+  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+
+private:
+  ~ServoStyleRuleMap();
+
+  bool IsEmpty() const { return mTable.Count() == 0; }
+
+  void FillTableFromRule(css::Rule* aRule);
+  void FillTableFromRuleList(ServoCSSRuleList* aRuleList);
+  void FillTableFromStyleSheet(ServoStyleSheet* aSheet);
+
+  typedef nsDataHashtable<nsPtrHashKey<const RawServoStyleRule>,
+                          ServoStyleRule*> Hashtable;
+  Hashtable mTable;
+  ServoStyleSet* mStyleSet;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoStyleRuleMap_h
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -46,18 +46,18 @@
 #include "nsCSSParser.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsColor.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "nsStyleUtil.h"
 #include "nsQueryObject.h"
 #include "mozilla/ServoBindings.h"
-#include "mozilla/ServoCSSRuleList.h"
 #include "mozilla/ServoStyleRule.h"
+#include "mozilla/ServoStyleRuleMap.h"
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 
 ///////////////////////////////////////////////////////////////////////////////
 
 inDOMUtils::inDOMUtils()
@@ -267,49 +267,35 @@ inDOMUtils::GetCSSStyleRules(nsIDOMEleme
         }
       }
     }
   } else {
     // It's a Servo source, so use some servo methods on the element to get
     // the rule list.
     nsTArray<const RawServoStyleRule*> rawRuleList;
     Servo_Element_GetStyleRuleList(element, &rawRuleList);
-    size_t rawRuleCount = rawRuleList.Length();
 
-    // We have RawServoStyleRules, and now we'll map them to ServoStyleRules
-    // by looking them up in the ServoStyleSheets owned by this document.
-    ServoCSSRuleList::StyleRuleHashtable rawRulesToRules;
-
-    nsIDocument* document = element->GetOwnerDocument();
-    int32_t sheetCount = document->GetNumberOfStyleSheets();
-
-    for (int32_t i = 0; i < sheetCount; i++) {
-      StyleSheet* sheet = document->GetStyleSheetAt(i);
-      MOZ_ASSERT(sheet->IsServo());
-
-      ErrorResult ignored;
-      ServoCSSRuleList* ruleList = static_cast<ServoCSSRuleList*>(
-        sheet->GetCssRules(*nsContentUtils::SubjectPrincipal(), ignored));
-      if (ruleList) {
-        // Generate the map from raw rules to rules.
-        ruleList->FillStyleRuleHashtable(rawRulesToRules);
-      }
+    nsIDocument* doc = element->GetOwnerDocument();
+    nsIPresShell* shell = doc->GetShell();
+    if (!shell) {
+      return NS_OK;
     }
 
+    ServoStyleSet* styleSet = shell->StyleSet()->AsServo();
+    ServoStyleRuleMap* map = styleSet->StyleRuleMap();
+    map->EnsureTable();
+
     // Find matching rules in the table.
-    for (size_t j = 0; j < rawRuleCount; j++) {
-      const RawServoStyleRule* rawRule = rawRuleList.ElementAt(j);
-      ServoStyleRule* rule = nullptr;
-      if (rawRulesToRules.Get(rawRule, &rule)) {
-        MOZ_ASSERT(rule, "rule should not be null");
-        RefPtr<css::Rule> ruleObj(rule);
-        rules->AppendElement(ruleObj, false);
+    for (const RawServoStyleRule* rawRule : Reversed(rawRuleList)) {
+      nsAutoCString text;
+      Servo_StyleRule_Debug(rawRule, &text);
+      if (ServoStyleRule* rule = map->Lookup(rawRule)) {
+        rules->AppendElement(static_cast<css::Rule*>(rule), false);
       } else {
-        // FIXME (bug 1359217): Need a reliable way to map raw rules to rules.
-        NS_WARNING("stylo: Could not map raw rule to a rule.");
+        MOZ_ASSERT_UNREACHABLE("We should be able to map a raw rule to a rule");
       }
     }
   }
 
   rules.forget(_retval);
 
   return NS_OK;
 }
--- a/layout/inspector/moz.build
+++ b/layout/inspector/moz.build
@@ -21,23 +21,28 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'inspector'
 
 EXPORTS += [
     'nsFontFace.h',
     'nsFontFaceList.h',
 ]
 
+EXPORTS.mozilla += [
+    'ServoStyleRuleMap.h',
+]
+
 UNIFIED_SOURCES += [
     'inCSSValueSearch.cpp',
     'inDeepTreeWalker.cpp',
     'inDOMUtils.cpp',
     'inLayoutUtils.cpp',
     'nsFontFace.cpp',
     'nsFontFaceList.cpp',
+    'ServoStyleRuleMap.cpp',
 ]
 
 if CONFIG['MOZ_XUL']:
     UNIFIED_SOURCES += [
         'inDOMView.cpp',
     ]
 
 FINAL_LIBRARY = 'xul'
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -304,36 +304,14 @@ ServoCSSRuleList::GetRuleType(uint32_t a
 {
   uintptr_t rule = mRules[aIndex];
   if (rule <= kMaxRuleType) {
     return rule;
   }
   return CastToPtr(rule)->Type();
 }
 
-void
-ServoCSSRuleList::FillStyleRuleHashtable(StyleRuleHashtable& aTable)
-{
-  for (uint32_t i = 0; i < mRules.Length(); i++) {
-    uint16_t type = GetRuleType(i);
-    if (type == nsIDOMCSSRule::STYLE_RULE) {
-      ServoStyleRule* castedRule = static_cast<ServoStyleRule*>(GetRule(i));
-      RawServoStyleRule* rawRule = castedRule->Raw();
-      aTable.Put(rawRule, castedRule);
-    } else if (type == nsIDOMCSSRule::MEDIA_RULE ||
-               type == nsIDOMCSSRule::SUPPORTS_RULE ||
-               type == nsIDOMCSSRule::DOCUMENT_RULE) {
-      auto castedRule = static_cast<css::GroupRule*>(GetRule(i));
-
-      // Call this method recursively on the ServoCSSRuleList in the rule.
-      ServoCSSRuleList* castedRuleList = static_cast<ServoCSSRuleList*>(
-        castedRule->CssRules());
-      castedRuleList->FillStyleRuleHashtable(aTable);
-    }
-  }
-}
-
 ServoCSSRuleList::~ServoCSSRuleList()
 {
   DropAllRules();
 }
 
 } // namespace mozilla
--- a/layout/style/ServoCSSRuleList.h
+++ b/layout/style/ServoCSSRuleList.h
@@ -46,20 +46,16 @@ public:
   void DropReference();
 
   css::Rule* GetRule(uint32_t aIndex);
   nsresult InsertRule(const nsAString& aRule, uint32_t aIndex);
   nsresult DeleteRule(uint32_t aIndex);
 
   uint16_t GetRuleType(uint32_t aIndex) const;
 
-  typedef nsDataHashtable<nsPtrHashKey<const RawServoStyleRule>,
-                          ServoStyleRule*> StyleRuleHashtable;
-  void FillStyleRuleHashtable(StyleRuleHashtable& aTable);
-
 private:
   virtual ~ServoCSSRuleList();
 
   // XXX Is it possible to have an address lower than or equal to 255?
   //     Is it possible to have more than 255 CSS rule types?
   static const uintptr_t kMaxRuleType = UINT8_MAX;
 
   static uintptr_t CastToUint(css::Rule* aPtr) {
--- a/layout/style/ServoStyleRule.h
+++ b/layout/style/ServoStyleRule.h
@@ -7,16 +7,17 @@
 /* representation of CSSStyleRule for stylo */
 
 #ifndef mozilla_ServoStyleRule_h
 #define mozilla_ServoStyleRule_h
 
 #include "mozilla/BindingStyleRule.h"
 #include "mozilla/ServoBindingTypes.h"
 
+#include "nsICSSStyleRuleDOMWrapper.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsDOMCSSDeclaration.h"
 
 namespace mozilla {
 
 class ServoDeclarationBlock;
 class ServoStyleRule;
 
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoStyleSet.h"
 
 #include "gfxPlatformFontList.h"
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/ServoStyleRuleMap.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/RestyleManagerInlines.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSRuleProcessor.h"
@@ -86,16 +87,22 @@ ServoStyleSet::Init(nsPresContext* aPres
   // mRawSet, so there was nothing to flush.
 }
 
 void
 ServoStyleSet::BeginShutdown()
 {
   nsIDocument* doc = mPresContext->Document();
 
+  // Remove the style rule map from document's observer and drop it.
+  if (mStyleRuleMap) {
+    doc->RemoveObserver(mStyleRuleMap);
+    mStyleRuleMap = nullptr;
+  }
+
   // It's important to do this before mRawSet is released, since that will cause
   // a RuleTree GC, which needs to happen after we have dropped all of the
   // document's strong references to RuleNodes.  We also need to do it here,
   // in BeginShutdown, and not in Shutdown, since Shutdown happens after the
   // frame tree has been destroyed, but before the script runners that delete
   // native anonymous content (which also could be holding on the RuleNodes)
   // have run.  By clearing style here, before the frame tree is destroyed,
   // the AllChildrenIterator will find the anonymous content.
@@ -139,16 +146,20 @@ ServoStyleSet::MediumFeaturesChanged() c
   return Servo_StyleSet_MediumFeaturesChanged(mRawSet.get());
 }
 
 size_t
 ServoStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
+  if (mStyleRuleMap) {
+    n += mStyleRuleMap->SizeOfIncludingThis(aMallocSizeOf);
+  }
+
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mRawSet
   // - mSheets
   // - mNonInheritingStyleContexts
   //
   // The following members are not measured:
   // - mPresContext, because it a non-owning pointer
@@ -1310,9 +1321,19 @@ ServoStyleSet::RunPostTraversalTasks()
   nsTArray<PostTraversalTask> tasks;
   tasks.SwapElements(mPostTraversalTasks);
 
   for (auto& task : tasks) {
     task.Run();
   }
 }
 
+ServoStyleRuleMap*
+ServoStyleSet::StyleRuleMap()
+{
+  if (!mStyleRuleMap) {
+    mStyleRuleMap = new ServoStyleRuleMap(this);
+    mPresContext->Document()->AddObserver(mStyleRuleMap);
+  }
+  return mStyleRuleMap;
+}
+
 ServoStyleSet* ServoStyleSet::sInServoTraversal = nullptr;
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -28,16 +28,17 @@ namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 class CSSStyleSheet;
 class ServoRestyleManager;
 class ServoStyleSheet;
 struct Keyframe;
 class ServoElementSnapshotTable;
+class ServoStyleRuleMap;
 } // namespace mozilla
 class nsCSSCounterStyleRule;
 class nsIContent;
 class nsIDocument;
 class nsStyleContext;
 class nsPresContext;
 struct nsTimingFunction;
 struct RawServoRuleNode;
@@ -243,16 +244,23 @@ public:
                          const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets);
   nsresult InsertStyleSheetBefore(SheetType aType,
                                   ServoStyleSheet* aNewSheet,
                                   ServoStyleSheet* aReferenceSheet);
 
   int32_t SheetCount(SheetType aType) const;
   ServoStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
 
+  template<typename Func>
+  void EnumerateStyleSheetArrays(Func aCallback) const {
+    for (const auto& sheetArray : mSheets) {
+      aCallback(sheetArray);
+    }
+  }
+
   nsresult RemoveDocStyleSheet(ServoStyleSheet* aSheet);
   nsresult AddDocStyleSheet(ServoStyleSheet* aSheet, nsIDocument* aDocument);
 
   // check whether there is ::before/::after style for an element
   already_AddRefed<nsStyleContext>
   ProbePseudoElementStyle(dom::Element* aOriginatingElement,
                           mozilla::CSSPseudoElementType aType,
                           nsStyleContext* aParentContext,
@@ -413,16 +421,19 @@ public:
   bool EnsureUniqueInnerOnCSSSheets();
 
   // Called by StyleSheet::EnsureUniqueInner to let us know it cloned
   // its inner.
   void SetNeedsRestyleAfterEnsureUniqueInner() {
     mNeedsRestyleAfterEnsureUniqueInner = true;
   }
 
+  // Returns the style rule map.
+  ServoStyleRuleMap* StyleRuleMap();
+
 private:
   // On construction, sets sInServoTraversal to the given ServoStyleSet.
   // On destruction, clears sInServoTraversal and calls RunPostTraversalTasks.
   class MOZ_STACK_CLASS AutoSetInServoTraversal
   {
   public:
     explicit AutoSetInServoTraversal(ServoStyleSet* aSet)
       : mSet(aSet)
@@ -564,14 +575,18 @@ private:
                   RefPtr<nsStyleContext>> mNonInheritingStyleContexts;
 
   // Tasks to perform after a traversal, back on the main thread.
   //
   // These are similar to Servo's SequentialTasks, except that they are
   // posted by C++ code running on style worker threads.
   nsTArray<PostTraversalTask> mPostTraversalTasks;
 
+  // Map from raw Servo style rule to Gecko's wrapper object.
+  // Constructed lazily when requested by devtools.
+  RefPtr<ServoStyleRuleMap> mStyleRuleMap;
+
   static ServoStyleSet* sInServoTraversal;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoStyleSet_h
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -275,17 +275,17 @@ ServoStyleSheet::Clone(StyleSheet* aClon
   RefPtr<StyleSheet> clone = new ServoStyleSheet(*this,
     static_cast<ServoStyleSheet*>(aCloneParent),
     aCloneOwnerRule,
     aCloneDocument,
     aCloneOwningNode);
   return clone.forget();
 }
 
-CSSRuleList*
+ServoCSSRuleList*
 ServoStyleSheet::GetCssRulesInternal()
 {
   if (!mRuleList) {
     EnsureUniqueInner();
 
     RefPtr<ServoCssRules> rawRules =
       Servo_StyleSheet_GetRules(Inner()->mSheet).Consume();
     MOZ_ASSERT(rawRules);
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -113,26 +113,29 @@ public:
     dom::CSSImportRule* aCloneOwnerRule,
     nsIDocument* aCloneDocument,
     nsINode* aCloneOwningNode) const final;
 
   // nsICSSLoaderObserver interface
   NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
                               nsresult aStatus) final;
 
+  // Internal GetCssRules method which do not have security check and
+  // completelness check.
+  ServoCSSRuleList* GetCssRulesInternal();
+
 protected:
   virtual ~ServoStyleSheet();
 
   ServoStyleSheetInner* Inner() const
   {
     return static_cast<ServoStyleSheetInner*>(mInner);
   }
 
   // Internal methods which do not have security check and completeness check.
-  dom::CSSRuleList* GetCssRulesInternal();
   uint32_t InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, ErrorResult& aRv);
   void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
   nsresult InsertRuleIntoGroupInternal(const nsAString& aRule,
                                        css::GroupRule* aGroup,
                                        uint32_t aIndex);
 
   void EnabledStateChangedInternal() {}
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/StyleSheet.h"
 
 #include "mozilla/dom/CSSImportRule.h"
 #include "mozilla/dom/CSSRuleList.h"
 #include "mozilla/dom/MediaList.h"
 #include "mozilla/dom/ShadowRoot.h"
+#include "mozilla/ServoCSSRuleList.h"
 #include "mozilla/ServoStyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/CSSStyleSheet.h"
 
 #include "mozAutoDocUpdate.h"
 #include "NullPrincipal.h"
 
 namespace mozilla {