Bug 1244074 - Part 4: Use StyleSheetHandle instead of concrete style sheet class in most places. r=dholbert
authorCameron McCormack <cam@mcc.id.au>
Wed, 24 Feb 2016 18:01:12 +1100
changeset 285357 51b6a0ea1b61c90a6b757d9a2d0e2589cc9e8a77
parent 285356 edbcfc242e24861a2404c09deaee0cf8626e5a6a
child 285358 12e4449dd3d1afc725f84059677bf1087f0be369
push id30030
push usercbook@mozilla.com
push dateThu, 25 Feb 2016 10:58:04 +0000
treeherdermozilla-central@c1e0d1890cfe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1244074
milestone47.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 1244074 - Part 4: Use StyleSheetHandle instead of concrete style sheet class in most places. r=dholbert
chrome/nsChromeRegistry.cpp
dom/base/ShadowRoot.cpp
dom/base/ShadowRoot.h
dom/base/nsContentSink.cpp
dom/base/nsContentSink.h
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
dom/base/nsIDocumentObserver.h
dom/base/nsIStyleSheetLinkingElement.h
dom/base/nsStyleLinkElement.cpp
dom/base/nsStyleLinkElement.h
dom/html/nsHTMLDocument.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/mathml/nsMathMLElement.cpp
dom/svg/SVGDocument.cpp
dom/svg/SVGSVGElement.cpp
dom/xbl/nsBindingManager.cpp
dom/xbl/nsBindingManager.h
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
dom/xbl/nsXBLPrototypeResources.cpp
dom/xbl/nsXBLPrototypeResources.h
dom/xbl/nsXBLResourceLoader.cpp
dom/xbl/nsXBLResourceLoader.h
dom/xml/nsXMLContentSink.cpp
dom/xml/nsXMLContentSink.h
dom/xslt/xslt/txMozillaXMLOutput.cpp
dom/xslt/xslt/txMozillaXMLOutput.h
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/nsXULElement.cpp
editor/libeditor/nsEditor.cpp
editor/libeditor/nsEditor.h
editor/libeditor/nsHTMLEditor.cpp
editor/libeditor/nsHTMLEditor.h
editor/libeditor/nsStyleSheetTxns.cpp
editor/libeditor/nsStyleSheetTxns.h
editor/nsIEditorStyleSheets.idl
layout/base/nsDocumentViewer.cpp
layout/base/nsIPresShell.h
layout/base/nsPresContext.cpp
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/base/nsStyleSheetService.cpp
layout/base/nsStyleSheetService.h
layout/inspector/inDOMUtils.cpp
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
layout/style/FontFaceSet.cpp
layout/style/FontFaceSet.h
layout/style/Loader.cpp
layout/style/Loader.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/StyleSetHandle.h
layout/style/StyleSetHandleInlines.h
layout/style/nsICSSLoaderObserver.h
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
layout/style/nsMediaFeatures.cpp
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
--- a/chrome/nsChromeRegistry.cpp
+++ b/chrome/nsChromeRegistry.cpp
@@ -12,35 +12,36 @@
 
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsEscape.h"
 #include "nsNetUtil.h"
 #include "nsString.h"
 #include "nsQueryObject.h"
 
-#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/dom/URL.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMLocation.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDOMWindow.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsIWindowMediator.h"
 #include "nsIPrefService.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
 
 // DO NOT use namespace mozilla; it'll break due to a naming conflict between
 // mozilla::TextRange and a TextRange in OSX headers.
-using mozilla::CSSStyleSheet;
+using mozilla::StyleSheetHandle;
 using mozilla::dom::IsChromeURI;
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void
 nsChromeRegistry::LogMessage(const char* aMsg, ...)
 {
   nsCOMPtr<nsIConsoleService> console 
@@ -396,29 +397,28 @@ nsresult nsChromeRegistry::RefreshWindow
   nsCOMPtr<nsIDocument> document = aWindow->GetDoc();
   if (!document)
     return NS_OK;
 
   // Deal with the agent sheets first.  Have to do all the style sets by hand.
   nsCOMPtr<nsIPresShell> shell = document->GetShell();
   if (shell) {
     // Reload only the chrome URL agent style sheets.
-    nsTArray<RefPtr<CSSStyleSheet>> agentSheets;
+    nsTArray<StyleSheetHandle::RefPtr> agentSheets;
     rv = shell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsTArray<RefPtr<CSSStyleSheet>> newAgentSheets;
-    for (CSSStyleSheet* sheet : agentSheets) {
+    nsTArray<StyleSheetHandle::RefPtr> newAgentSheets;
+    for (StyleSheetHandle sheet : agentSheets) {
       nsIURI* uri = sheet->GetSheetURI();
 
       if (IsChromeURI(uri)) {
         // Reload the sheet.
-        RefPtr<CSSStyleSheet> newSheet;
-        rv = document->LoadChromeSheetSync(uri, true,
-                                           getter_AddRefs(newSheet));
+        StyleSheetHandle::RefPtr newSheet;
+        rv = document->LoadChromeSheetSync(uri, true, &newSheet);
         if (NS_FAILED(rv)) return rv;
         if (newSheet) {
           rv = newAgentSheets.AppendElement(newSheet) ? NS_OK : NS_ERROR_FAILURE;
           if (NS_FAILED(rv)) return rv;
         }
       }
       else {  // Just use the same sheet.
         rv = newAgentSheets.AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
@@ -428,37 +428,37 @@ nsresult nsChromeRegistry::RefreshWindow
 
     rv = shell->SetAgentStyleSheets(newAgentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   int32_t count = document->GetNumberOfStyleSheets();
 
   // Build an array of style sheets we need to reload.
-  nsTArray<RefPtr<CSSStyleSheet>> oldSheets(count);
-  nsTArray<RefPtr<CSSStyleSheet>> newSheets(count);
+  nsTArray<StyleSheetHandle::RefPtr> oldSheets(count);
+  nsTArray<StyleSheetHandle::RefPtr> newSheets(count);
 
   // Iterate over the style sheets.
   for (int32_t i = 0; i < count; i++) {
     // Get the style sheet
-    CSSStyleSheet* styleSheet = document->GetStyleSheetAt(i);
+    StyleSheetHandle styleSheet = document->GetStyleSheetAt(i);
     oldSheets.AppendElement(styleSheet);
   }
 
   // Iterate over our old sheets and kick off a sync load of the new
   // sheet if and only if it's a chrome URL.
-  for (CSSStyleSheet* sheet : oldSheets) {
+  for (StyleSheetHandle sheet : oldSheets) {
     nsIURI* uri = sheet ? sheet->GetOriginalURI() : nullptr;
 
     if (uri && IsChromeURI(uri)) {
       // Reload the sheet.
-      RefPtr<CSSStyleSheet> newSheet;
+      StyleSheetHandle::RefPtr newSheet;
       // XXX what about chrome sheets that have a title or are disabled?  This
       // only works by sheer dumb luck.
-      document->LoadChromeSheetSync(uri, false, getter_AddRefs(newSheet));
+      document->LoadChromeSheetSync(uri, false, &newSheet);
       // Even if it's null, we put in in there.
       newSheets.AppendElement(newSheet);
     } else {
       // Just use the same sheet.
       newSheets.AppendElement(sheet);
     }
   }
 
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -12,16 +12,18 @@
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLContentElement.h"
 #include "mozilla/dom/HTMLShadowElement.h"
 #include "nsXBLPrototypeBinding.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot,
                                                   DocumentFragment)
@@ -125,17 +127,17 @@ ShadowRoot::StyleSheetChanged()
   if (shell) {
     OwnerDoc()->BeginUpdate(UPDATE_STYLE);
     shell->RecordShadowStyleChange(this);
     OwnerDoc()->EndUpdate(UPDATE_STYLE);
   }
 }
 
 void
-ShadowRoot::InsertSheet(CSSStyleSheet* aSheet,
+ShadowRoot::InsertSheet(StyleSheetHandle aSheet,
                         nsIContent* aLinkingContent)
 {
   nsCOMPtr<nsIStyleSheetLinkingElement>
     linkingElement = do_QueryInterface(aLinkingContent);
   MOZ_ASSERT(linkingElement, "The only styles in a ShadowRoot should come "
                              "from <style>.");
 
   linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
@@ -143,30 +145,30 @@ ShadowRoot::InsertSheet(CSSStyleSheet* a
   // Find the correct position to insert into the style sheet list (must
   // be in tree order).
   for (size_t i = 0; i <= mProtoBinding->SheetCount(); i++) {
     if (i == mProtoBinding->SheetCount()) {
       mProtoBinding->AppendStyleSheet(aSheet);
       break;
     }
 
-    nsINode* sheetOwnerNode = mProtoBinding->StyleSheetAt(i)->GetOwnerNode();
-    if (nsContentUtils::PositionIsBefore(aLinkingContent, sheetOwnerNode)) {
+    nsINode* sheetOwningNode = mProtoBinding->StyleSheetAt(i)->GetOwnerNode();
+    if (nsContentUtils::PositionIsBefore(aLinkingContent, sheetOwningNode)) {
       mProtoBinding->InsertStyleSheetAt(i, aSheet);
       break;
     }
   }
 
   if (aSheet->IsApplicable()) {
     StyleSheetChanged();
   }
 }
 
 void
-ShadowRoot::RemoveSheet(CSSStyleSheet* aSheet)
+ShadowRoot::RemoveSheet(StyleSheetHandle aSheet)
 {
   mProtoBinding->RemoveStyleSheet(aSheet);
 
   if (aSheet->IsApplicable()) {
     StyleSheetChanged();
   }
 }
 
@@ -747,17 +749,24 @@ CSSStyleSheet*
 ShadowRootStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = aIndex < mShadowRoot->mProtoBinding->SheetCount();
 
   if (!aFound) {
     return nullptr;
   }
 
-  return mShadowRoot->mProtoBinding->StyleSheetAt(aIndex);
+  // XXXheycam Return null until ServoStyleSheet implements the right
+  // DOM interfaces.
+  StyleSheetHandle sheet = mShadowRoot->mProtoBinding->StyleSheetAt(aIndex);
+  if (sheet->IsServo()) {
+    NS_ERROR("stylo: can't return ServoStyleSheets to script yet");
+    return nullptr;
+  }
+  return sheet->AsGecko();
 }
 
 uint32_t
 ShadowRootStyleSheetList::Length()
 {
   return mShadowRoot->mProtoBinding->SheetCount();
 }
 
--- a/dom/base/ShadowRoot.h
+++ b/dom/base/ShadowRoot.h
@@ -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/. */
 
 #ifndef mozilla_dom_shadowroot_h__
 #define mozilla_dom_shadowroot_h__
 
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/StyleSheetList.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsTHashtable.h"
 #include "nsDocument.h"
 
 class nsIAtom;
 class nsIContent;
 class nsXBLPrototypeBinding;
@@ -40,18 +41,18 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   ShadowRoot(nsIContent* aContent, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
              nsXBLPrototypeBinding* aProtoBinding);
 
   void AddToIdTable(Element* aElement, nsIAtom* aId);
   void RemoveFromIdTable(Element* aElement, nsIAtom* aId);
-  void InsertSheet(CSSStyleSheet* aSheet, nsIContent* aLinkingContent);
-  void RemoveSheet(CSSStyleSheet* aSheet);
+  void InsertSheet(StyleSheetHandle aSheet, nsIContent* aLinkingContent);
+  void RemoveSheet(StyleSheetHandle aSheet);
   bool ApplyAuthorStyles();
   void SetApplyAuthorStyles(bool aApplyAuthorStyles);
   StyleSheetList* StyleSheets();
   HTMLShadowElement* GetShadowElement() { return mShadowElement; }
 
   /**
    * Sets the current shadow insertion point where the older
    * ShadowRoot will be projected.
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -208,17 +208,17 @@ nsContentSink::Init(nsIDocument* aDoc,
     mDynamicLowerValue = sEnablePerfMode == 1;
     FavorPerformanceHint(!mDynamicLowerValue, 0);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsContentSink::StyleSheetLoaded(CSSStyleSheet* aSheet,
+nsContentSink::StyleSheetLoaded(StyleSheetHandle aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus)
 {
   NS_ASSERTION(!mRunsToCompletion, "How come a fragment parser observed sheets?");
   if (!aWasAlternate) {
     NS_ASSERTION(mPendingSheetCount > 0, "How'd that happen?");
     --mPendingSheetCount;
 
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -80,17 +80,17 @@ class nsContentSink : public nsICSSLoade
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
                                            nsICSSLoaderObserver)
     // nsITimerCallback
   NS_DECL_NSITIMERCALLBACK
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) override;
 
   virtual nsresult ProcessMETATag(nsIContent* aContent);
 
   // nsIContentSink implementation helpers
   nsresult WillParseImpl(void);
   nsresult WillInterruptImpl(void);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -240,16 +240,18 @@
 #include "nsLocation.h"
 #include "mozilla/dom/FontFaceSet.h"
 #include "mozilla/dom/BoxObject.h"
 #include "gfxVR.h"
 #include "gfxPrefs.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #include "mozilla/DocLoadingTimelineMarker.h"
 
 #include "nsISpeculativeConnect.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "mozilla/MediaManager.h"
 #endif // MOZ_MEDIA_NAVIGATOR
@@ -728,39 +730,45 @@ CSSStyleSheet*
 nsDOMStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   if (!mDocument || aIndex >= (uint32_t)mDocument->GetNumberOfStyleSheets()) {
     aFound = false;
     return nullptr;
   }
 
   aFound = true;
-  CSSStyleSheet* sheet = mDocument->GetStyleSheetAt(aIndex);
+  StyleSheetHandle sheet = mDocument->GetStyleSheetAt(aIndex);
   NS_ASSERTION(sheet, "Must have a sheet");
 
-  return static_cast<CSSStyleSheet*>(sheet);
+  // XXXheycam Return null until ServoStyleSheet implements the right DOM
+  // interfaces.
+  if (sheet->IsServo()) {
+    NS_ERROR("stylo: can't return a ServoStyleSheet to the DOM yet");
+    return nullptr;
+  }
+  return sheet->AsGecko();
 }
 
 void
 nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
 {
   mDocument = nullptr;
 }
 
 void
-nsDOMStyleSheetList::StyleSheetAdded(CSSStyleSheet* aStyleSheet,
+nsDOMStyleSheetList::StyleSheetAdded(StyleSheetHandle aStyleSheet,
                                      bool aDocumentSheet)
 {
   if (aDocumentSheet && -1 != mLength) {
     mLength++;
   }
 }
 
 void
-nsDOMStyleSheetList::StyleSheetRemoved(CSSStyleSheet* aStyleSheet,
+nsDOMStyleSheetList::StyleSheetRemoved(StyleSheetHandle aStyleSheet,
                                        bool aDocumentSheet)
 {
   if (aDocumentSheet && -1 != mLength) {
     mLength--;
   }
 }
 
 // nsOnloadBlocker implementation
@@ -1317,19 +1325,24 @@ nsDOMStyleSheetSetList::EnsureFresh()
   if (!mDocument) {
     return; // Spec says "no exceptions", and we have no style sets if we have
             // no document, for sure
   }
 
   int32_t count = mDocument->GetNumberOfStyleSheets();
   nsAutoString title;
   for (int32_t index = 0; index < count; index++) {
-    CSSStyleSheet* sheet = mDocument->GetStyleSheetAt(index);
+    StyleSheetHandle sheet = mDocument->GetStyleSheetAt(index);
     NS_ASSERTION(sheet, "Null sheet in sheet list!");
-    sheet->GetTitle(title);
+    // XXXheycam ServoStyleSheets don't expose their title yet.
+    if (sheet->IsServo()) {
+      NS_ERROR("stylo: ServoStyleSets don't expose their title yet");
+      continue;
+    }
+    sheet->AsGecko()->GetTitle(title);
     if (!title.IsEmpty() && !mNames.Contains(title) && !Add(title)) {
       return;
     }
   }
 }
 
 // ==================================================================
 nsIDocument::SelectorCache::SelectorCache()
@@ -1599,17 +1612,17 @@ nsDocument::~nsDocument()
   for (uint32_t indx = mChildren.ChildCount(); indx-- != 0; ) {
     mChildren.ChildAt(indx)->UnbindFromTree();
     mChildren.RemoveChildAt(indx);
   }
   mFirstChild = nullptr;
   mCachedRootElement = nullptr;
 
   // Let the stylesheets know we're going away
-  for (CSSStyleSheet* sheet : mStyleSheets) {
+  for (StyleSheetHandle sheet : mStyleSheets) {
     sheet->SetOwningDocument(nullptr);
   }
   if (mAttrStyleSheet) {
     mAttrStyleSheet->SetOwningDocument(nullptr);
   }
   // We don't own the mOnDemandBuiltInUASheets, so we don't need to reset them.
 
   if (mListenerManager) {
@@ -2277,36 +2290,36 @@ nsDocument::ResetToURI(nsIURI *aURI, nsI
     nsGlobalWindow::Cast(win)->RefreshCompartmentPrincipal();
   }
 }
 
 void
 nsDocument::RemoveDocStyleSheetsFromStyleSets()
 {
   // The stylesheets should forget us
-  for (CSSStyleSheet* sheet : Reversed(mStyleSheets)) {
+  for (StyleSheetHandle sheet : Reversed(mStyleSheets)) {
     sheet->SetOwningDocument(nullptr);
 
     if (sheet->IsApplicable()) {
       nsCOMPtr<nsIPresShell> shell = GetShell();
       if (shell) {
         shell->StyleSet()->RemoveDocStyleSheet(sheet);
       }
     }
     // XXX Tell observers?
   }
 }
 
 void
 nsDocument::RemoveStyleSheetsFromStyleSets(
-    nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
+    nsTArray<StyleSheetHandle::RefPtr>& aSheets,
     SheetType aType)
 {
   // The stylesheets should forget us
-  for (CSSStyleSheet* sheet : Reversed(aSheets)) {
+  for (StyleSheetHandle sheet : Reversed(aSheets)) {
     sheet->SetOwningDocument(nullptr);
 
     if (sheet->IsApplicable()) {
       nsCOMPtr<nsIPresShell> shell = GetShell();
       if (shell) {
         shell->StyleSet()->RemoveStyleSheet(aType, sheet);
       }
     }
@@ -2363,47 +2376,47 @@ nsDocument::ResetStylesheetsToURI(nsIURI
   nsCOMPtr<nsIPresShell> shell = GetShell();
   if (shell) {
     FillStyleSet(shell->StyleSet());
   }
 }
 
 static void
 AppendSheetsToStyleSet(StyleSetHandle aStyleSet,
-                       const nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
+                       const nsTArray<StyleSheetHandle::RefPtr>& aSheets,
                        SheetType aType)
 {
-  for (CSSStyleSheet* sheet : Reversed(aSheets)) {
+  for (StyleSheetHandle sheet : Reversed(aSheets)) {
     aStyleSet->AppendStyleSheet(aType, sheet);
   }
 }
 
 
 void
 nsDocument::FillStyleSet(StyleSetHandle aStyleSet)
 {
   NS_PRECONDITION(aStyleSet, "Must have a style set");
   NS_PRECONDITION(aStyleSet->SheetCount(SheetType::Doc) == 0,
                   "Style set already has document sheets?");
 
-  for (CSSStyleSheet* sheet : Reversed(mStyleSheets)) {
+  for (StyleSheetHandle sheet : Reversed(mStyleSheets)) {
     if (sheet->IsApplicable()) {
       aStyleSet->AddDocStyleSheet(sheet, this);
     }
   }
 
   nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
   if (sheetService) {
-    for (CSSStyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
+    for (StyleSheetHandle sheet : *sheetService->AuthorStyleSheets()) {
       aStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
     }
   }
 
   // Iterate backwards to maintain order
-  for (CSSStyleSheet* sheet : Reversed(mOnDemandBuiltInUASheets)) {
+  for (StyleSheetHandle sheet : Reversed(mOnDemandBuiltInUASheets)) {
     if (sheet->IsApplicable()) {
       aStyleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
   }
 
   AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eAgentSheet],
                          SheetType::Agent);
   AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eUserSheet],
@@ -4046,28 +4059,28 @@ nsDocument::RemoveChildAt(uint32_t aInde
     DestroyElementMaps();
   }
 
   doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
   mCachedRootElement = nullptr;
 }
 
 void
-nsDocument::EnsureOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
+nsDocument::EnsureOnDemandBuiltInUASheet(StyleSheetHandle aSheet)
 {
   if (mOnDemandBuiltInUASheets.Contains(aSheet)) {
     return;
   }
   BeginUpdate(UPDATE_STYLE);
   AddOnDemandBuiltInUASheet(aSheet);
   EndUpdate(UPDATE_STYLE);
 }
 
 void
-nsDocument::AddOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
+nsDocument::AddOnDemandBuiltInUASheet(StyleSheetHandle aSheet)
 {
   MOZ_ASSERT(!mOnDemandBuiltInUASheets.Contains(aSheet));
 
   // Prepend here so that we store the sheets in mOnDemandBuiltInUASheets in
   // the same order that they should end up in the style set.
   mOnDemandBuiltInUASheets.InsertElementAt(0, aSheet);
 
   if (aSheet->IsApplicable()) {
@@ -4086,109 +4099,113 @@ nsDocument::AddOnDemandBuiltInUASheet(CS
 }
 
 int32_t
 nsDocument::GetNumberOfStyleSheets() const
 {
   return mStyleSheets.Length();
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsDocument::GetStyleSheetAt(int32_t aIndex) const
 {
-  return mStyleSheets.SafeElementAt(aIndex, nullptr);
+  return mStyleSheets.SafeElementAt(aIndex, StyleSheetHandle());
 }
 
 int32_t
-nsDocument::GetIndexOfStyleSheet(CSSStyleSheet* aSheet) const
+nsDocument::GetIndexOfStyleSheet(StyleSheetHandle aSheet) const
 {
   return mStyleSheets.IndexOf(aSheet);
 }
 
 void
-nsDocument::AddStyleSheetToStyleSets(CSSStyleSheet* aSheet)
+nsDocument::AddStyleSheetToStyleSets(StyleSheetHandle aSheet)
 {
   nsCOMPtr<nsIPresShell> shell = GetShell();
   if (shell) {
     shell->StyleSet()->AddDocStyleSheet(aSheet, this);
   }
 }
 
 #define DO_STYLESHEET_NOTIFICATION(className, type, memberName, argName)      \
   do {                                                                        \
     className##Init init;                                                     \
     init.mBubbles = true;                                                     \
     init.mCancelable = true;                                                  \
-    init.mStylesheet = aSheet;                                                \
+    /* XXXheycam ServoStyleSheet doesn't implement DOM interfaces yet */      \
+    if (aSheet->IsServo()) {                                                  \
+      NS_ERROR("stylo: can't dispatch events for ServoStyleSheets yet");      \
+    }                                                                         \
+    init.mStylesheet = aSheet->IsGecko() ? aSheet->AsGecko() : nullptr;       \
     init.memberName = argName;                                                \
                                                                               \
     RefPtr<className> event =                                               \
       className::Constructor(this, NS_LITERAL_STRING(type), init);            \
     event->SetTrusted(true);                                                  \
     event->SetTarget(this);                                                   \
     RefPtr<AsyncEventDispatcher> asyncDispatcher =                          \
       new AsyncEventDispatcher(this, event);                                  \
     asyncDispatcher->mOnlyChromeDispatch = true;                              \
     asyncDispatcher->PostDOMEvent();                                          \
   } while (0);
 
 void
-nsDocument::NotifyStyleSheetAdded(CSSStyleSheet* aSheet, bool aDocumentSheet)
+nsDocument::NotifyStyleSheetAdded(StyleSheetHandle aSheet, bool aDocumentSheet)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (aSheet, aDocumentSheet));
 
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
                                "StyleSheetAdded",
                                mDocumentSheet,
                                aDocumentSheet);
   }
 }
 
 void
-nsDocument::NotifyStyleSheetRemoved(CSSStyleSheet* aSheet, bool aDocumentSheet)
+nsDocument::NotifyStyleSheetRemoved(StyleSheetHandle aSheet, bool aDocumentSheet)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetRemoved, (aSheet, aDocumentSheet));
 
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
                                "StyleSheetRemoved",
                                mDocumentSheet,
                                aDocumentSheet);
   }
 }
 
 void
-nsDocument::AddStyleSheet(CSSStyleSheet* aSheet)
+nsDocument::AddStyleSheet(StyleSheetHandle aSheet)
 {
   NS_PRECONDITION(aSheet, "null arg");
   mStyleSheets.AppendElement(aSheet);
   aSheet->SetOwningDocument(this);
 
   if (aSheet->IsApplicable()) {
     AddStyleSheetToStyleSets(aSheet);
   }
 
   NotifyStyleSheetAdded(aSheet, true);
 }
 
 void
-nsDocument::RemoveStyleSheetFromStyleSets(CSSStyleSheet* aSheet)
+nsDocument::RemoveStyleSheetFromStyleSets(StyleSheetHandle aSheet)
 {
   nsCOMPtr<nsIPresShell> shell = GetShell();
   if (shell) {
     shell->StyleSet()->RemoveDocStyleSheet(aSheet);
   }
 }
 
 void
-nsDocument::RemoveStyleSheet(CSSStyleSheet* aSheet)
+nsDocument::RemoveStyleSheet(StyleSheetHandle aSheet)
 {
   NS_PRECONDITION(aSheet, "null arg");
-  RefPtr<CSSStyleSheet> sheet = aSheet; // hold ref so it won't die too soon
+  StyleSheetHandle::RefPtr sheet = aSheet; // hold ref so it won't die too soon
 
   if (!mStyleSheets.RemoveElement(aSheet)) {
     NS_ASSERTION(mInUnlinkOrDeletion, "stylesheet not found");
     return;
   }
 
   if (!mIsGoingAway) {
     if (aSheet->IsApplicable()) {
@@ -4197,71 +4214,71 @@ nsDocument::RemoveStyleSheet(CSSStyleShe
 
     NotifyStyleSheetRemoved(aSheet, true);
   }
 
   aSheet->SetOwningDocument(nullptr);
 }
 
 void
-nsDocument::UpdateStyleSheets(nsTArray<RefPtr<CSSStyleSheet>>& aOldSheets,
-                              nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets)
+nsDocument::UpdateStyleSheets(nsTArray<StyleSheetHandle::RefPtr>& aOldSheets,
+                              nsTArray<StyleSheetHandle::RefPtr>& aNewSheets)
 {
   BeginUpdate(UPDATE_STYLE);
 
   // XXX Need to set the sheet on the ownernode, if any
   NS_PRECONDITION(aOldSheets.Length() == aNewSheets.Length(),
                   "The lists must be the same length!");
   int32_t count = aOldSheets.Length();
 
-  RefPtr<CSSStyleSheet> oldSheet;
+  StyleSheetHandle::RefPtr oldSheet;
   int32_t i;
   for (i = 0; i < count; ++i) {
     oldSheet = aOldSheets[i];
 
     // First remove the old sheet.
     NS_ASSERTION(oldSheet, "None of the old sheets should be null");
     int32_t oldIndex = mStyleSheets.IndexOf(oldSheet);
     RemoveStyleSheet(oldSheet);  // This does the right notifications
 
     // Now put the new one in its place.  If it's null, just ignore it.
-    CSSStyleSheet* newSheet = aNewSheets[i];
+    StyleSheetHandle newSheet = aNewSheets[i];
     if (newSheet) {
       mStyleSheets.InsertElementAt(oldIndex, newSheet);
       newSheet->SetOwningDocument(this);
       if (newSheet->IsApplicable()) {
         AddStyleSheetToStyleSets(newSheet);
       }
 
       NotifyStyleSheetAdded(newSheet, true);
     }
   }
 
   EndUpdate(UPDATE_STYLE);
 }
 
 void
-nsDocument::InsertStyleSheetAt(CSSStyleSheet* aSheet, int32_t aIndex)
+nsDocument::InsertStyleSheetAt(StyleSheetHandle aSheet, int32_t aIndex)
 {
   NS_PRECONDITION(aSheet, "null ptr");
 
   mStyleSheets.InsertElementAt(aIndex, aSheet);
 
   aSheet->SetOwningDocument(this);
 
   if (aSheet->IsApplicable()) {
     AddStyleSheetToStyleSets(aSheet);
   }
 
   NotifyStyleSheetAdded(aSheet, true);
 }
 
 
 void
-nsDocument::SetStyleSheetApplicableState(CSSStyleSheet* aSheet,
+nsDocument::SetStyleSheetApplicableState(StyleSheetHandle aSheet,
                                          bool aApplicable)
 {
   NS_PRECONDITION(aSheet, "null arg");
 
   // If we're actually in the document style sheet list
   if (mStyleSheets.IndexOf(aSheet) != mStyleSheets.NoIndex) {
     if (aApplicable) {
       AddStyleSheetToStyleSets(aSheet);
@@ -4317,17 +4334,17 @@ ConvertAdditionalSheetType(nsIDocument::
     default:
       MOZ_ASSERT(false, "wrong type");
       // we must return something although this should never happen
       return SheetType::Count;
   }
 }
 
 static int32_t
-FindSheet(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets, nsIURI* aSheetURI)
+FindSheet(const nsTArray<StyleSheetHandle::RefPtr>& aSheets, nsIURI* aSheetURI)
 {
   for (int32_t i = aSheets.Length() - 1; i >= 0; i-- ) {
     bool bEqual;
     nsIURI* uri = aSheets[i]->GetSheetURI();
 
     if (uri && NS_SUCCEEDED(uri->Equals(aSheetURI, &bEqual)) && bEqual)
       return i;
   }
@@ -4361,29 +4378,28 @@ nsDocument::LoadAdditionalStyleSheet(add
     case nsIDocument::eAuthorSheet:
       parsingMode = css::eAuthorSheetFeatures;
       break;
 
     default:
       MOZ_CRASH("impossible value for aType");
   }
 
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
-                                      getter_AddRefs(sheet));
+  StyleSheetHandle::RefPtr sheet;
+  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   sheet->SetOwningDocument(this);
   MOZ_ASSERT(sheet->IsApplicable());
 
   return AddAdditionalStyleSheet(aType, sheet);
 }
 
 nsresult
-nsDocument::AddAdditionalStyleSheet(additionalSheetType aType, CSSStyleSheet* aSheet)
+nsDocument::AddAdditionalStyleSheet(additionalSheetType aType, StyleSheetHandle aSheet)
 {
   if (mAdditionalSheets[aType].Contains(aSheet))
     return NS_ERROR_INVALID_ARG;
 
   if (!aSheet->IsApplicable())
     return NS_ERROR_INVALID_ARG;
 
   mAdditionalSheets[aType].AppendElement(aSheet);
@@ -4402,21 +4418,21 @@ nsDocument::AddAdditionalStyleSheet(addi
   return NS_OK;
 }
 
 void
 nsDocument::RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheetURI)
 {
   MOZ_ASSERT(aSheetURI);
 
-  nsTArray<RefPtr<CSSStyleSheet>>& sheets = mAdditionalSheets[aType];
+  nsTArray<StyleSheetHandle::RefPtr>& sheets = mAdditionalSheets[aType];
 
   int32_t i = FindSheet(mAdditionalSheets[aType], aSheetURI);
   if (i >= 0) {
-    RefPtr<CSSStyleSheet> sheetRef = sheets[i];
+    StyleSheetHandle::RefPtr sheetRef = sheets[i];
     sheets.RemoveElementAt(i);
 
     BeginUpdate(UPDATE_STYLE);
     if (!mIsGoingAway) {
       MOZ_ASSERT(sheetRef->IsApplicable());
       nsCOMPtr<nsIPresShell> shell = GetShell();
       if (shell) {
         SheetType type = ConvertAdditionalSheetType(aType);
@@ -4428,20 +4444,20 @@ nsDocument::RemoveAdditionalStyleSheet(a
     // these additional sheets.
     NotifyStyleSheetRemoved(sheetRef, false);
     EndUpdate(UPDATE_STYLE);
 
     sheetRef->SetOwningDocument(nullptr);
   }
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsDocument::FirstAdditionalAuthorSheet()
 {
-  return mAdditionalSheets[eAuthorSheet].SafeElementAt(0, nullptr);
+  return mAdditionalSheets[eAuthorSheet].SafeElementAt(0, StyleSheetHandle());
 }
 
 nsIGlobalObject*
 nsDocument::GetScopeObject() const
 {
   nsCOMPtr<nsIGlobalObject> scope(do_QueryReferent(mScopeObject));
   return scope;
 }
@@ -5187,46 +5203,46 @@ nsDocument::DocumentStatesChanged(EventS
   // Invalidate our cached state.
   mGotDocumentState &= ~aStateMask;
   mDocumentState &= ~aStateMask;
 
   NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentStatesChanged, (this, aStateMask));
 }
 
 void
-nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
+nsDocument::StyleRuleChanged(StyleSheetHandle aSheet,
                              css::Rule* aStyleRule)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged, (aSheet));
 
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
                                "StyleRuleChanged",
                                mRule,
                                aStyleRule ? aStyleRule->GetDOMRule() : nullptr);
   }
 }
 
 void
-nsDocument::StyleRuleAdded(CSSStyleSheet* aSheet,
+nsDocument::StyleRuleAdded(StyleSheetHandle aSheet,
                            css::Rule* aStyleRule)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleAdded, (aSheet));
 
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
                                "StyleRuleAdded",
                                mRule,
                                aStyleRule ? aStyleRule->GetDOMRule()
                                           : nullptr);
   }
 }
 
 void
-nsDocument::StyleRuleRemoved(CSSStyleSheet* aSheet,
+nsDocument::StyleRuleRemoved(StyleSheetHandle aSheet,
                              css::Rule* aStyleRule)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved, (aSheet));
 
   if (StyleSheetChangeEventsEnabled()) {
     DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
                                "StyleRuleRemoved",
                                mRule,
@@ -6457,27 +6473,33 @@ void
 nsIDocument::GetSelectedStyleSheetSet(nsAString& aSheetSet)
 {
   aSheetSet.Truncate();
 
   // Look through our sheets, find the selected set title
   int32_t count = GetNumberOfStyleSheets();
   nsAutoString title;
   for (int32_t index = 0; index < count; index++) {
-    CSSStyleSheet* sheet = GetStyleSheetAt(index);
+    StyleSheetHandle sheet = GetStyleSheetAt(index);
     NS_ASSERTION(sheet, "Null sheet in sheet list!");
 
+    // XXXheycam Make this work with ServoStyleSheets.
+    if (sheet->IsServo()) {
+      NS_ERROR("stylo: can't handle alternate ServoStyleSheets yet");
+      continue;
+    }
+
     bool disabled;
-    sheet->GetDisabled(&disabled);
+    sheet->AsGecko()->GetDisabled(&disabled);
     if (disabled) {
       // Disabled sheets don't affect the currently selected set
       continue;
     }
 
-    sheet->GetTitle(title);
+    sheet->AsGecko()->GetTitle(title);
 
     if (aSheetSet.IsEmpty()) {
       aSheetSet = title;
     } else if (!title.IsEmpty() && !aSheetSet.Equals(title)) {
       // Sheets from multiple sets enabled; return null string, per spec.
       SetDOMStringToNull(aSheetSet);
       return;
     }
@@ -6571,21 +6593,28 @@ nsDocument::EnableStyleSheetsForSet(cons
 void
 nsDocument::EnableStyleSheetsForSetInternal(const nsAString& aSheetSet,
                                             bool aUpdateCSSLoader)
 {
   BeginUpdate(UPDATE_STYLE);
   int32_t count = GetNumberOfStyleSheets();
   nsAutoString title;
   for (int32_t index = 0; index < count; index++) {
-    CSSStyleSheet* sheet = GetStyleSheetAt(index);
+    StyleSheetHandle sheet = GetStyleSheetAt(index);
     NS_ASSERTION(sheet, "Null sheet in sheet list!");
-    sheet->GetTitle(title);
+
+    // XXXheycam Make this work with ServoStyleSheets.
+    if (sheet->IsServo()) {
+      NS_ERROR("stylo: can't handle alternate ServoStyleSheets yet");
+      continue;
+    }
+
+    sheet->AsGecko()->GetTitle(title);
     if (!title.IsEmpty()) {
-      sheet->SetEnabled(title.Equals(aSheetSet));
+      sheet->AsGecko()->SetEnabled(title.Equals(aSheetSet));
     }
   }
   if (aUpdateCSSLoader) {
     CSSLoader()->SetPreferredSheet(aSheetSet);
   }
   EndUpdate(UPDATE_STYLE);
 }
 
@@ -9849,17 +9878,17 @@ namespace {
 /**
  * Stub for LoadSheet(), since all we want is to get the sheet into
  * the CSSLoader's style cache
  */
 class StubCSSLoaderObserver final : public nsICSSLoaderObserver {
   ~StubCSSLoaderObserver() {}
 public:
   NS_IMETHOD
-  StyleSheetLoaded(CSSStyleSheet*, bool, nsresult) override
+  StyleSheetLoaded(StyleSheetHandle, bool, nsresult) override
   {
     return NS_OK;
   }
   NS_DECL_ISUPPORTS
 };
 NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
 
 } // namespace
@@ -9878,22 +9907,22 @@ nsDocument::PreloadStyle(nsIURI* uri, co
                          NS_LossyConvertUTF16toASCII(charset),
                          obs,
                          Element::StringToCORSMode(aCrossOriginAttr),
                          aReferrerPolicy, aIntegrity);
 }
 
 nsresult
 nsDocument::LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
-                                CSSStyleSheet** sheet)
+                                mozilla::StyleSheetHandle::RefPtr* aSheet)
 {
   css::SheetParsingMode mode =
     isAgentSheet ? css::eAgentSheetFeatures
                  : css::eAuthorSheetFeatures;
-  return CSSLoader()->LoadSheetSync(uri, mode, isAgentSheet, sheet);
+  return CSSLoader()->LoadSheetSync(uri, mode, isAgentSheet, aSheet);
 }
 
 class nsDelayedEventDispatcher : public nsRunnable
 {
 public:
   explicit nsDelayedEventDispatcher(nsTArray<nsCOMPtr<nsIDocument>>& aDocuments)
   {
     mDocuments.SwapElements(aDocuments);
@@ -10209,38 +10238,48 @@ nsIDocument::CreateStaticClone(nsIDocShe
       } else {
         clonedDoc->mOriginalDocument = this;
       }
 
       clonedDoc->mOriginalDocument->mStaticCloneCount++;
 
       int32_t sheetsCount = GetNumberOfStyleSheets();
       for (int32_t i = 0; i < sheetsCount; ++i) {
-        RefPtr<CSSStyleSheet> sheet = GetStyleSheetAt(i);
+        StyleSheetHandle::RefPtr sheet = GetStyleSheetAt(i);
         if (sheet) {
           if (sheet->IsApplicable()) {
-            RefPtr<CSSStyleSheet> clonedSheet =
-              sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
-            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
-            if (clonedSheet) {
-              clonedDoc->AddStyleSheet(clonedSheet);
+            // XXXheycam Need to make ServoStyleSheet cloning work.
+            if (sheet->IsGecko()) {
+              RefPtr<CSSStyleSheet> clonedSheet =
+                sheet->AsGecko()->Clone(nullptr, nullptr, clonedDoc, nullptr);
+              NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+              if (clonedSheet) {
+                clonedDoc->AddStyleSheet(clonedSheet);
+              }
+            } else {
+              NS_ERROR("stylo: ServoStyleSheet doesn't support cloning");
             }
           }
         }
       }
 
       // Iterate backwards to maintain order
-      for (CSSStyleSheet* sheet : Reversed(thisAsDoc->mOnDemandBuiltInUASheets)) {
+      for (StyleSheetHandle sheet : Reversed(thisAsDoc->mOnDemandBuiltInUASheets)) {
         if (sheet) {
           if (sheet->IsApplicable()) {
-            RefPtr<CSSStyleSheet> clonedSheet =
-              sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
-            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
-            if (clonedSheet) {
-              clonedDoc->AddOnDemandBuiltInUASheet(clonedSheet);
+            // XXXheycam Need to make ServoStyleSheet cloning work.
+            if (sheet->IsGecko()) {
+              RefPtr<CSSStyleSheet> clonedSheet =
+                sheet->AsGecko()->Clone(nullptr, nullptr, clonedDoc, nullptr);
+              NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+              if (clonedSheet) {
+                clonedDoc->AddOnDemandBuiltInUASheet(clonedSheet);
+              }
+            } else {
+              NS_ERROR("stylo: ServoStyleSheet doesn't support cloning");
             }
           }
         }
       }
     }
   }
   mCreatingStaticClone = false;
   return clonedDoc.forget();
@@ -12361,17 +12400,17 @@ nsDocument::OnAppThemeChanged()
 {
   // Bail out if there is no theme support set up properly.
   auto themeOrigin = Preferences::GetString("b2g.theme.origin");
   if (!themeOrigin || !Preferences::GetBool("dom.mozApps.themable")) {
     return;
   }
 
   for (int32_t i = 0; i < GetNumberOfStyleSheets(); i++) {
-    RefPtr<CSSStyleSheet> sheet = GetStyleSheetAt(i);
+    StyleSheetHandle::RefPtr sheet = GetStyleSheetAt(i);
     if (!sheet) {
       continue;
     }
 
     nsINode* owningNode = sheet->GetOwnerNode();
     if (!owningNode) {
       continue;
     }
@@ -12728,22 +12767,22 @@ nsIDocument::DocAddSizeOfExcludingThis(n
 void
 nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
   aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
   DocAddSizeOfExcludingThis(aWindowSizes);
 }
 
 static size_t
-SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
+SizeOfOwnedSheetArrayExcludingThis(const nsTArray<StyleSheetHandle::RefPtr>& aSheets,
                                    MallocSizeOf aMallocSizeOf)
 {
   size_t n = 0;
   n += aSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  for (CSSStyleSheet* sheet : aSheets) {
+  for (StyleSheetHandle sheet : aSheets) {
     if (!sheet->GetOwningDocument()) {
       // Avoid over-reporting shared sheets.
       continue;
     }
     n += sheet->SizeOfIncludingThis(aMallocSizeOf);
   }
   return n;
 }
@@ -13414,8 +13453,20 @@ nsIDocument::ReportHasScrollLinkedEffect
     return;
   }
   mHasScrollLinkedEffect = true;
   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                   NS_LITERAL_CSTRING("Async Pan/Zoom"),
                                   this, nsContentUtils::eLAYOUT_PROPERTIES,
                                   "ScrollLinkedEffectFound2");
 }
+
+mozilla::StyleBackendType
+nsIDocument::GetStyleBackendType() const
+{
+  if (!mPresShell) {
+#ifdef MOZ_STYLO
+    NS_WARNING("GetStyleBackendType() called on document without a pres shell");
+#endif
+    return StyleBackendType::Gecko;
+  }
+  return mPresShell->StyleSet()->BackendType();
+}
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -792,46 +792,46 @@ public:
       nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
 
   virtual nsresult SetSubDocumentFor(Element* aContent,
                                      nsIDocument* aSubDoc) override;
   virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const override;
   virtual Element* FindContentForSubDocument(nsIDocument *aDocument) const override;
   virtual Element* GetRootElementInternal() const override;
 
-  virtual void EnsureOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet) override;
+  virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheetHandle aSheet) override;
 
   /**
    * Get the (document) style sheets owned by this document.
    * These are ordered, highest priority last
    */
   virtual int32_t GetNumberOfStyleSheets() const override;
-  virtual mozilla::CSSStyleSheet* GetStyleSheetAt(int32_t aIndex) const override;
-  virtual int32_t GetIndexOfStyleSheet(mozilla::CSSStyleSheet* aSheet) const override;
-  virtual void AddStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
-  virtual void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
+  virtual mozilla::StyleSheetHandle GetStyleSheetAt(int32_t aIndex) const override;
+  virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const override;
+  virtual void AddStyleSheet(mozilla::StyleSheetHandle aSheet) override;
+  virtual void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet) override;
 
   virtual void UpdateStyleSheets(
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aOldSheets,
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aNewSheets) override;
-  virtual void AddStyleSheetToStyleSets(mozilla::CSSStyleSheet* aSheet);
-  virtual void RemoveStyleSheetFromStyleSets(mozilla::CSSStyleSheet* aSheet);
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aOldSheets,
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aNewSheets) override;
+  virtual void AddStyleSheetToStyleSets(mozilla::StyleSheetHandle aSheet);
+  virtual void RemoveStyleSheetFromStyleSets(mozilla::StyleSheetHandle aSheet);
 
-  virtual void InsertStyleSheetAt(mozilla::CSSStyleSheet* aSheet,
+  virtual void InsertStyleSheetAt(mozilla::StyleSheetHandle aSheet,
                                   int32_t aIndex) override;
-  virtual void SetStyleSheetApplicableState(mozilla::CSSStyleSheet* aSheet,
+  virtual void SetStyleSheetApplicableState(mozilla::StyleSheetHandle aSheet,
                                             bool aApplicable) override;
 
   virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType,
                                             nsIURI* aSheetURI) override;
   virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType,
-                                           mozilla::CSSStyleSheet* aSheet) override;
+                                           mozilla::StyleSheetHandle aSheet) override;
   virtual void RemoveAdditionalStyleSheet(additionalSheetType aType,
                                           nsIURI* sheetURI) override;
-  virtual mozilla::CSSStyleSheet* FirstAdditionalAuthorSheet() override;
+  virtual mozilla::StyleSheetHandle FirstAdditionalAuthorSheet() override;
 
   virtual nsIChannel* GetChannel() const override {
     return mChannel;
   }
 
   virtual nsIChannel* GetFailedChannel() const override {
     return mFailedChannel;
   }
@@ -881,21 +881,21 @@ public:
   virtual void SetReadyStateInternal(ReadyState rs) override;
 
   virtual void ContentStateChanged(nsIContent* aContent,
                                    mozilla::EventStates aStateMask)
                                      override;
   virtual void DocumentStatesChanged(
                  mozilla::EventStates aStateMask) override;
 
-  virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleChanged(mozilla::StyleSheetHandle aStyleSheet,
                                 mozilla::css::Rule* aStyleRule) override;
-  virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleAdded(mozilla::StyleSheetHandle aStyleSheet,
                               mozilla::css::Rule* aStyleRule) override;
-  virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleRemoved(mozilla::StyleSheetHandle aStyleSheet,
                                 mozilla::css::Rule* aStyleRule) override;
 
   virtual void FlushPendingNotifications(mozFlushType aType) override;
   virtual void FlushExternalResources(mozFlushType aType) override;
   virtual void SetXMLDeclaration(const char16_t *aVersion,
                                  const char16_t *aEncoding,
                                  const int32_t aStandalone) override;
   virtual void GetXMLDeclaration(nsAString& aVersion,
@@ -957,17 +957,17 @@ public:
    * Called when an app-theme-changed observer notification is
    * received by this document.
    */
   void OnAppThemeChanged();
 
   void ReportUseCounters();
 
 private:
-  void AddOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet);
+  void AddOnDemandBuiltInUASheet(mozilla::StyleSheetHandle aSheet);
   nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
   void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
 
 public:
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
 
   // nsIDOMDocument
@@ -1139,17 +1139,17 @@ public:
                                mozilla::CORSMode aCORSMode) override;
 
   virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
                             const nsAString& aCrossOriginAttr,
                             ReferrerPolicy aReferrerPolicy,
                             const nsAString& aIntegrity) override;
 
   virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
-                                       mozilla::CSSStyleSheet** sheet) override;
+                                       mozilla::StyleSheetHandle::RefPtr* aSheet) override;
 
   virtual nsISupports* GetCurrentContentSink() override;
 
   virtual mozilla::EventStates GetDocumentState() override;
 
   // Only BlockOnload should call this!
   void AsyncBlockOnload();
 
@@ -1489,17 +1489,17 @@ public:
 
 protected:
   already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext,
                                                nsViewManager* aViewManager,
                                                mozilla::StyleSetHandle aStyleSet);
 
   void RemoveDocStyleSheetsFromStyleSets();
   void RemoveStyleSheetsFromStyleSets(
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets,
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets,
       mozilla::SheetType aType);
   void ResetStylesheetsToURI(nsIURI* aURI);
   void FillStyleSet(mozilla::StyleSetHandle aStyleSet);
 
   // Return whether all the presshells for this document are safe to flush
   bool IsSafeToFlush() const;
 
   void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
@@ -1543,19 +1543,19 @@ protected:
   // parsed into.
   nsCOMPtr<nsIParser> mParser;
 
   // Weak reference to our sink for in case we no longer have a parser.  This
   // will allow us to flush out any pending stuff from the sink even if
   // EndLoad() has already happened.
   nsWeakPtr mWeakSink;
 
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mStyleSheets;
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mOnDemandBuiltInUASheets;
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mStyleSheets;
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mOnDemandBuiltInUASheets;
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mAdditionalSheets[AdditionalSheetTypeCount];
 
   // Array of observers
   nsTObserverArray<nsIDocumentObserver*> mObservers;
 
   // Tracker for animations that are waiting to start.
   // nullptr until GetOrCreatePendingAnimationTracker is called.
   RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
 
@@ -1704,18 +1704,18 @@ public:
   mozilla::EventStates mDocumentState;
   mozilla::EventStates mGotDocumentState;
 
   RefPtr<nsDOMNavigationTiming> mTiming;
 private:
   friend class nsUnblockOnloadEvent;
   // Recomputes the visibility state but doesn't set the new value.
   mozilla::dom::VisibilityState GetVisibilityState() const;
-  void NotifyStyleSheetAdded(mozilla::CSSStyleSheet* aSheet, bool aDocumentSheet);
-  void NotifyStyleSheetRemoved(mozilla::CSSStyleSheet* aSheet, bool aDocumentSheet);
+  void NotifyStyleSheetAdded(mozilla::StyleSheetHandle aSheet, bool aDocumentSheet);
+  void NotifyStyleSheetRemoved(mozilla::StyleSheetHandle aSheet, bool aDocumentSheet);
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   nsresult CheckFrameOptions();
   bool IsLoopDocument(nsIChannel* aChannel);
   nsresult InitCSP(nsIChannel* aChannel);
 
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -29,16 +29,18 @@
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsContentListDeclarations.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 #include "prclist.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/CORSMode.h"
+#include "mozilla/StyleBackendType.h"
+#include "mozilla/StyleSheetHandle.h"
 #include <bitset>                        // for member
 
 class gfxUserFontSet;
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsIDocShell;
 class nsDocShell;
@@ -913,103 +915,105 @@ public:
    * This function prepends the given style sheet to the document's style set
    * in order to make sure that it does not override user-agent style sheets
    * supplied by add-ons or by the app (Firefox OS or Firefox Mobile, for
    * example), since their sheets should override built-in sheets.
    *
    * TODO We can get rid of the whole concept of delayed loading if we fix
    * bug 77999.
    */
-  virtual void EnsureOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet) = 0;
+  virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheetHandle aSheet) = 0;
 
   /**
    * Get the number of (document) stylesheets
    *
    * @return the number of stylesheets
    * @throws no exceptions
    */
   virtual int32_t GetNumberOfStyleSheets() const = 0;
 
   /**
    * Get a particular stylesheet
    * @param aIndex the index the stylesheet lives at.  This is zero-based
    * @return the stylesheet at aIndex.  Null if aIndex is out of range.
    * @throws no exceptions
    */
-  virtual mozilla::CSSStyleSheet* GetStyleSheetAt(int32_t aIndex) const = 0;
+  virtual mozilla::StyleSheetHandle GetStyleSheetAt(int32_t aIndex) const = 0;
 
   /**
    * Insert a sheet at a particular spot in the stylesheet list (zero-based)
    * @param aSheet the sheet to insert
    * @param aIndex the index to insert at.  This index will be
    *   adjusted for the "special" sheets.
    * @throws no exceptions
    */
-  virtual void InsertStyleSheetAt(mozilla::CSSStyleSheet* aSheet,
+  virtual void InsertStyleSheetAt(mozilla::StyleSheetHandle aSheet,
                                   int32_t aIndex) = 0;
 
   /**
    * Get the index of a particular stylesheet.  This will _always_
    * consider the "special" sheets as part of the sheet list.
    * @param aSheet the sheet to get the index of
    * @return aIndex the index of the sheet in the full list
    */
-  virtual int32_t GetIndexOfStyleSheet(mozilla::CSSStyleSheet* aSheet) const = 0;
+  virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const = 0;
 
   /**
    * Replace the stylesheets in aOldSheets with the stylesheets in
    * aNewSheets. The two lists must have equal length, and the sheet
    * at positon J in the first list will be replaced by the sheet at
    * position J in the second list.  Some sheets in the second list
    * may be null; if so the corresponding sheets in the first list
    * will simply be removed.
    */
   virtual void UpdateStyleSheets(
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aOldSheets,
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aNewSheets) = 0;
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aOldSheets,
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aNewSheets) = 0;
 
   /**
    * Add a stylesheet to the document
    */
-  virtual void AddStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
+  virtual void AddStyleSheet(mozilla::StyleSheetHandle aSheet) = 0;
 
   /**
    * Remove a stylesheet from the document
    */
-  virtual void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
+  virtual void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet) = 0;
 
   /**
    * Notify the document that the applicable state of the sheet changed
    * and that observers should be notified and style sets updated
    */
-  virtual void SetStyleSheetApplicableState(mozilla::CSSStyleSheet* aSheet,
+  virtual void SetStyleSheetApplicableState(mozilla::StyleSheetHandle aSheet,
                                             bool aApplicable) = 0;
 
   enum additionalSheetType {
     eAgentSheet,
     eUserSheet,
     eAuthorSheet,
     AdditionalSheetTypeCount
   };
 
   virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType,
                                             nsIURI* aSheetURI) = 0;
   virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType,
-                                           mozilla::CSSStyleSheet* aSheet) = 0;
+                                           mozilla::StyleSheetHandle aSheet) = 0;
   virtual void RemoveAdditionalStyleSheet(additionalSheetType aType,
                                           nsIURI* sheetURI) = 0;
-  virtual mozilla::CSSStyleSheet* FirstAdditionalAuthorSheet() = 0;
+  virtual mozilla::StyleSheetHandle FirstAdditionalAuthorSheet() = 0;
 
   /**
    * Get this document's CSSLoader.  This is guaranteed to not return null.
    */
   mozilla::css::Loader* CSSLoader() const {
     return mCSSLoader;
   }
 
+  mozilla::StyleBackendType GetStyleBackendType() const;
+
   /**
    * Get this document's StyleImageLoader.  This is guaranteed to not return null.
    */
   mozilla::css::ImageLoader* StyleImageLoader() const {
     return mStyleImageLoader;
   }
 
   /**
@@ -1287,21 +1291,21 @@ public:
 
   // Notify that a document state has changed.
   // This should only be called by callers whose state is also reflected in the
   // implementation of nsDocument::GetDocumentState.
   virtual void DocumentStatesChanged(mozilla::EventStates aStateMask) = 0;
 
   // Observation hooks for style data to propagate notifications
   // to document observers
-  virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleChanged(mozilla::StyleSheetHandle aStyleSheet,
                                 mozilla::css::Rule* aStyleRule) = 0;
-  virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleAdded(mozilla::StyleSheetHandle aStyleSheet,
                               mozilla::css::Rule* aStyleRule) = 0;
-  virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleRuleRemoved(mozilla::StyleSheetHandle aStyleSheet,
                                 mozilla::css::Rule* aStyleRule) = 0;
 
   /**
    * Flush notifications for this document and its parent documents
    * (since those may affect the layout of this one).
    */
   virtual void FlushPendingNotifications(mozFlushType aType) = 0;
 
@@ -2086,17 +2090,17 @@ public:
    * Called by the chrome registry to load style sheets.  Can be put
    * back there if and when when that module is merged with libgklayout.
    *
    * This always does a synchronous load.  If aIsAgentSheet is true,
    * it also uses the system principal and enables unsafe rules.
    * DO NOT USE FOR UNTRUSTED CONTENT.
    */
   virtual nsresult LoadChromeSheetSync(nsIURI* aURI, bool aIsAgentSheet,
-                                       mozilla::CSSStyleSheet** aSheet) = 0;
+                                       mozilla::StyleSheetHandle::RefPtr* aSheet) = 0;
 
   /**
    * Returns true if the locale used for the document specifies a direction of
    * right to left. For chrome documents, this comes from the chrome registry.
    * This is used to determine the current state for the :-moz-locale-dir pseudoclass
    * so once can know whether a document is expected to be rendered left-to-right
    * or right-to-left.
    */
--- a/dom/base/nsIDocumentObserver.h
+++ b/dom/base/nsIDocumentObserver.h
@@ -2,24 +2,24 @@
 /* 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 nsIDocumentObserver_h___
 #define nsIDocumentObserver_h___
 
 #include "mozilla/EventStates.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "nsISupports.h"
 #include "nsIMutationObserver.h"
 
 class nsIContent;
 class nsIDocument;
 
 namespace mozilla {
-class CSSStyleSheet;
 namespace css {
 class Rule;
 } // namespace css
 } // namespace mozilla
 
 #define NS_IDOCUMENT_OBSERVER_IID \
 { 0x71041fa3, 0x6dd7, 0x4cde, \
   { 0xbb, 0x76, 0xae, 0xcc, 0x69, 0xe1, 0x75, 0x78 } }
@@ -95,75 +95,75 @@ public:
    * called automatically when a StyleSheet gets added to the
    * document, even if the stylesheet is not applicable. The
    * notification is passed on to all of the document observers.
    *
    * @param aStyleSheet the StyleSheet that has been added
    * @param aDocumentSheet True if sheet is in document's style sheet list,
    *                       false if sheet is not (i.e., UA or user sheet)
    */
-  virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleSheetAdded(mozilla::StyleSheetHandle aStyleSheet,
                                bool aDocumentSheet) = 0;
 
   /**
    * A StyleSheet has just been removed from the document.  This
    * method is called automatically when a StyleSheet gets removed
    * from the document, even if the stylesheet is not applicable. The
    * notification is passed on to all of the document observers.
    *
    * @param aStyleSheet the StyleSheet that has been removed
    * @param aDocumentSheet True if sheet is in document's style sheet list,
    *                       false if sheet is not (i.e., UA or user sheet)
    */
-  virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet,
+  virtual void StyleSheetRemoved(mozilla::StyleSheetHandle aStyleSheet,
                                  bool aDocumentSheet) = 0;
   
   /**
    * A StyleSheet has just changed its applicable state.
    * This method is called automatically when the applicable state
    * of a StyleSheet gets changed. The style sheet passes this
    * notification to the document. The notification is passed on 
    * to all of the document observers.
    *
    * @param aStyleSheet the StyleSheet that has changed state
    */
-  virtual void StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
+  virtual void StyleSheetApplicableStateChanged(mozilla::StyleSheetHandle aStyleSheet) = 0;
 
   /**
    * A StyleRule has just been modified within a style sheet.
    * This method is called automatically when the rule gets
    * modified. The style sheet passes this notification to 
    * the document. The notification is passed on to all of 
    * the document observers.
    *
    * @param aStyleSheet the StyleSheet that contians the rule
    */
-  virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
+  virtual void StyleRuleChanged(mozilla::StyleSheetHandle aStyleSheet) = 0;
 
   /**
    * A StyleRule has just been added to a style sheet.
    * This method is called automatically when the rule gets
    * added to the sheet. The style sheet passes this
    * notification to the document. The notification is passed on 
    * to all of the document observers.
    *
    * @param aStyleSheet the StyleSheet that has been modified
    */
-  virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) = 0;
+  virtual void StyleRuleAdded(mozilla::StyleSheetHandle aStyleSheet) = 0;
 
   /**
    * A StyleRule has just been removed from a style sheet.
    * This method is called automatically when the rule gets
    * removed from the sheet. The style sheet passes this
    * notification to the document. The notification is passed on 
    * to all of the document observers.
    *
    * @param aStyleSheet the StyleSheet that has been modified
    */
-  virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) = 0;
+  virtual void StyleRuleRemoved(mozilla::StyleSheetHandle aStyleSheet) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE                              \
     virtual void BeginUpdate(nsIDocument* aDocument,                         \
                              nsUpdateType aUpdateType) override;
 
@@ -181,35 +181,35 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumen
                                      nsIContent* aContent,                   \
                                      mozilla::EventStates aStateMask) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED                    \
     virtual void DocumentStatesChanged(nsIDocument* aDocument,               \
                                        mozilla::EventStates aStateMask) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED                          \
-    virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet,        \
+    virtual void StyleSheetAdded(mozilla::StyleSheetHandle aStyleSheet,      \
                                  bool aDocumentSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED                        \
-    virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet,      \
+    virtual void StyleSheetRemoved(mozilla::StyleSheetHandle aStyleSheet,    \
                                    bool aDocumentSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED         \
     virtual void StyleSheetApplicableStateChanged(                           \
-        mozilla::CSSStyleSheet* aStyleSheet) override;
+        mozilla::StyleSheetHandle aStyleSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED                         \
-    virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) override;
+    virtual void StyleRuleChanged(mozilla::StyleSheetHandle aStyleSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED                           \
-    virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) override;
+    virtual void StyleRuleAdded(mozilla::StyleSheetHandle aStyleSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED                         \
-    virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) override;
+    virtual void StyleRuleRemoved(mozilla::StyleSheetHandle aStyleSheet) override;
 
 #define NS_DECL_NSIDOCUMENTOBSERVER                                          \
     NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE                                  \
     NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE                                    \
     NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD                                    \
     NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD                                      \
     NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED                          \
     NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED                        \
@@ -257,35 +257,35 @@ void                                    
 {                                                                         \
 }
 
 #define NS_IMPL_NSIDOCUMENTOBSERVER_CONTENT(_class)                       \
 NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class)
 
 #define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class)                    \
 void                                                                      \
-_class::StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet,              \
+_class::StyleSheetAdded(mozilla::StyleSheetHandle aStyleSheet,            \
                         bool aDocumentSheet)                              \
 {                                                                         \
 }                                                                         \
 void                                                                      \
-_class::StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet,            \
+_class::StyleSheetRemoved(mozilla::StyleSheetHandle aStyleSheet,          \
                           bool aDocumentSheet)                            \
 {                                                                         \
 }                                                                         \
 void                                                                      \
-_class::StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) \
+_class::StyleSheetApplicableStateChanged(mozilla::StyleSheetHandle aStyleSheet) \
 {                                                                         \
 }                                                                         \
 void                                                                      \
-_class::StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet)             \
+_class::StyleRuleChanged(mozilla::StyleSheetHandle aStyleSheet)           \
 {                                                                         \
 }                                                                         \
 void                                                                      \
-_class::StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet)               \
+_class::StyleRuleAdded(mozilla::StyleSheetHandle aStyleSheet)             \
 {                                                                         \
 }                                                                         \
 void                                                                      \
-_class::StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet)             \
+_class::StyleRuleRemoved(mozilla::StyleSheetHandle aStyleSheet)           \
 {                                                                         \
 }
 
 #endif /* nsIDocumentObserver_h___ */
--- a/dom/base/nsIStyleSheetLinkingElement.h
+++ b/dom/base/nsIStyleSheetLinkingElement.h
@@ -3,47 +3,44 @@
 /* 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 nsIStyleSheetLinkingElement_h__
 #define nsIStyleSheetLinkingElement_h__
 
 
 #include "nsISupports.h"
+#include "mozilla/StyleSheetHandle.h"
 
 class nsICSSLoaderObserver;
 class nsIURI;
 
 #define NS_ISTYLESHEETLINKINGELEMENT_IID          \
 { 0xa8b79f3b, 0x9d18, 0x4f9c, \
   { 0xb1, 0xaa, 0x8c, 0x9b, 0x1b, 0xaa, 0xac, 0xad } }
 
-namespace mozilla {
-class CSSStyleSheet;
-} // namespace mozilla
-
 class nsIStyleSheetLinkingElement : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID)
 
   /**
    * Used to make the association between a style sheet and
    * the element that linked it to the document.
    *
    * @param aStyleSheet the style sheet associated with this
    *                    element.
    */
-  NS_IMETHOD SetStyleSheet(mozilla::CSSStyleSheet* aStyleSheet) = 0;
+  NS_IMETHOD SetStyleSheet(mozilla::StyleSheetHandle aStyleSheet) = 0;
 
   /**
    * Used to obtain the style sheet linked in by this element.
    *
    * @return the style sheet associated with this element.
    */
-  NS_IMETHOD_(mozilla::CSSStyleSheet*) GetStyleSheet() = 0;
+  NS_IMETHOD_(mozilla::StyleSheetHandle) GetStyleSheet() = 0;
 
   /**
    * Initialize the stylesheet linking element. If aDontLoadStyle is
    * true the element will ignore the first modification to the
    * element that would cause a stylesheet to be loaded. Subsequent
    * modifications to the element will not be ignored.
    */
   NS_IMETHOD InitStyleLinkElement(bool aDontLoadStyle) = 0;
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -7,17 +7,18 @@
 /*
  * A base class which implements nsIStyleSheetLinkingElement and can
  * be subclassed by various content nodes that want to load
  * stylesheets (<style>, <link>, processing instructions, etc).
  */
 
 #include "nsStyleLinkElement.h"
 
-#include "mozilla/CSSStyleSheet.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FragmentOrElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/Preferences.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMComment.h"
@@ -62,34 +63,34 @@ nsStyleLinkElement::Unlink()
 void
 nsStyleLinkElement::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   nsStyleLinkElement* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheet);
 }
 
 NS_IMETHODIMP 
-nsStyleLinkElement::SetStyleSheet(CSSStyleSheet* aStyleSheet)
+nsStyleLinkElement::SetStyleSheet(StyleSheetHandle aStyleSheet)
 {
   if (mStyleSheet) {
     mStyleSheet->SetOwningNode(nullptr);
   }
 
   mStyleSheet = aStyleSheet;
   if (mStyleSheet) {
     nsCOMPtr<nsINode> node = do_QueryObject(this);
     if (node) {
       mStyleSheet->SetOwningNode(node);
     }
   }
     
   return NS_OK;
 }
 
-NS_IMETHODIMP_(CSSStyleSheet*)
+NS_IMETHODIMP_(StyleSheetHandle)
 nsStyleLinkElement::GetStyleSheet()
 {
   return mStyleSheet;
 }
 
 NS_IMETHODIMP 
 nsStyleLinkElement::InitStyleLinkElement(bool aDontLoadStyle)
 {
@@ -311,18 +312,25 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
   // Check for a ShadowRoot because link elements are inert in a
   // ShadowRoot.
   ShadowRoot* containingShadow = thisContent->GetContainingShadow();
   if (thisContent->IsHTMLElement(nsGkAtoms::link) &&
       (aOldShadowRoot || containingShadow)) {
     return NS_OK;
   }
 
-  Element* oldScopeElement =
-    mStyleSheet ? mStyleSheet->GetScopeElement() : nullptr;
+  // XXXheycam ServoStyleSheets do not support <style scoped>.
+  Element* oldScopeElement = nullptr;
+  if (mStyleSheet) {
+    if (mStyleSheet->IsServo()) {
+      NS_ERROR("stylo: ServoStyleSheets don't support <style scoped>");
+    } else {
+      oldScopeElement = mStyleSheet->AsGecko()->GetScopeElement();
+    }
+  }
 
   if (mStyleSheet && (aOldDocument || aOldShadowRoot)) {
     MOZ_ASSERT(!(aOldDocument && aOldShadowRoot),
                "ShadowRoot content is never in document, thus "
                "there should not be a old document and old "
                "ShadowRoot simultaneously.");
 
     // We're removing the link element from the document or shadow tree,
@@ -460,42 +468,50 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
 
 void
 nsStyleLinkElement::UpdateStyleSheetScopedness(bool aIsNowScoped)
 {
   if (!mStyleSheet) {
     return;
   }
 
+  if (mStyleSheet->IsServo()) {
+    // XXXheycam ServoStyleSheets don't support <style scoped>.
+    NS_ERROR("stylo: ServoStyleSheets don't support <style scoped>");
+    return;
+  }
+
+  CSSStyleSheet* sheet = mStyleSheet->AsGecko();
+
   nsCOMPtr<nsIContent> thisContent;
   CallQueryInterface(this, getter_AddRefs(thisContent));
 
-  Element* oldScopeElement = mStyleSheet->GetScopeElement();
+  Element* oldScopeElement = sheet->GetScopeElement();
   Element* newScopeElement = aIsNowScoped ?
                                thisContent->GetParentElement() :
                                nullptr;
 
   if (oldScopeElement == newScopeElement) {
     return;
   }
 
   nsIDocument* document = thisContent->GetOwnerDocument();
 
   if (thisContent->IsInShadowTree()) {
     ShadowRoot* containingShadow = thisContent->GetContainingShadow();
     containingShadow->RemoveSheet(mStyleSheet);
 
-    mStyleSheet->SetScopeElement(newScopeElement);
+    sheet->SetScopeElement(newScopeElement);
 
     containingShadow->InsertSheet(mStyleSheet, thisContent);
   } else {
     document->BeginUpdate(UPDATE_STYLE);
     document->RemoveStyleSheet(mStyleSheet);
 
-    mStyleSheet->SetScopeElement(newScopeElement);
+    sheet->SetScopeElement(newScopeElement);
 
     document->AddStyleSheet(mStyleSheet);
     document->EndUpdate(UPDATE_STYLE);
   }
 
   if (oldScopeElement) {
     UpdateIsElementInStyleScopeFlagOnSubtree(oldScopeElement);
   }
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -19,34 +19,43 @@
 #include "nsCOMPtr.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsTArray.h"
 
 class nsIDocument;
 class nsIURI;
 
 namespace mozilla {
+class CSSStyleSheet;
 namespace dom {
 class ShadowRoot;
 } // namespace dom
 } // namespace mozilla
 
 class nsStyleLinkElement : public nsIStyleSheetLinkingElement
 {
 public:
   nsStyleLinkElement();
   virtual ~nsStyleLinkElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override = 0;
 
-  mozilla::CSSStyleSheet* GetSheet() const { return mStyleSheet; }
+  mozilla::CSSStyleSheet* GetSheet() const
+  {
+    // XXXheycam Return nullptr for ServoStyleSheets until we have a way of
+    // exposing them to script.
+    NS_ASSERTION(!mStyleSheet || mStyleSheet->IsGecko(),
+                 "stylo: ServoStyleSheets can't be exposed to script yet");
+    return mStyleSheet && mStyleSheet->IsGecko() ? mStyleSheet->AsGecko() :
+                                                   nullptr;
+  }
 
   // nsIStyleSheetLinkingElement  
-  NS_IMETHOD SetStyleSheet(mozilla::CSSStyleSheet* aStyleSheet) override;
-  NS_IMETHOD_(mozilla::CSSStyleSheet*) GetStyleSheet() override;
+  NS_IMETHOD SetStyleSheet(mozilla::StyleSheetHandle aStyleSheet) override;
+  NS_IMETHOD_(mozilla::StyleSheetHandle) GetStyleSheet() override;
   NS_IMETHOD InitStyleLinkElement(bool aDontLoadStyle) override;
   NS_IMETHOD UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate,
                               bool aForceReload) override;
   NS_IMETHOD SetEnableUpdates(bool aEnableUpdates) override;
   NS_IMETHOD GetCharset(nsAString& aCharset) override;
 
@@ -123,17 +132,17 @@ private:
    */
   nsresult DoUpdateStyleSheet(nsIDocument* aOldDocument,
                               mozilla::dom::ShadowRoot* aOldShadowRoot,
                               nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate,
                               bool aForceUpdate);
 
-  RefPtr<mozilla::CSSStyleSheet> mStyleSheet;
+  mozilla::StyleSheetHandle::RefPtr mStyleSheet;
 protected:
   bool mDontLoadStyle;
   bool mUpdatesEnabled;
   uint32_t mLineNumber;
 };
 
 #endif /* nsStyleLinkElement_h___ */
 
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -109,16 +109,18 @@
 #include "mozilla/dom/HTMLDocumentBinding.h"
 #include "nsCharsetSource.h"
 #include "nsIStringBundle.h"
 #include "nsDOMClassInfo.h"
 #include "nsFocusManager.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsLayoutStylesheetCache.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define NS_MAX_DOCUMENT_WRITE_DEPTH 20
 
 #include "prtime.h"
 
@@ -2636,22 +2638,24 @@ nsHTMLDocument::TearingDownEditor(nsIEdi
   if (IsEditingOn()) {
     EditingState oldState = mEditingState;
     mEditingState = eTearingDown;
 
     nsCOMPtr<nsIPresShell> presShell = GetShell();
     if (!presShell)
       return;
 
-    nsTArray<RefPtr<CSSStyleSheet>> agentSheets;
+    nsTArray<StyleSheetHandle::RefPtr> agentSheets;
     presShell->GetAgentStyleSheets(agentSheets);
 
-    agentSheets.RemoveElement(nsLayoutStylesheetCache::ContentEditableSheet());
+    auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
+
+    agentSheets.RemoveElement(cache->ContentEditableSheet());
     if (oldState == eDesignMode)
-      agentSheets.RemoveElement(nsLayoutStylesheetCache::DesignModeSheet());
+      agentSheets.RemoveElement(cache->DesignModeSheet());
 
     presShell->SetAgentStyleSheets(agentSheets);
 
     presShell->ReconstructStyleData();
   }
 }
 
 nsresult
@@ -2775,44 +2779,44 @@ nsHTMLDocument::EditingStateChanged()
     nsAutoEditingState push(this, eSettingUp);
 
     nsCOMPtr<nsIPresShell> presShell = GetShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
     // Before making this window editable, we need to modify UA style sheet
     // because new style may change whether focused element will be focusable
     // or not.
-    nsTArray<RefPtr<CSSStyleSheet>> agentSheets;
+    nsTArray<StyleSheetHandle::RefPtr> agentSheets;
     rv = presShell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    CSSStyleSheet* contentEditableSheet =
-      nsLayoutStylesheetCache::ContentEditableSheet();
+    auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
+
+    StyleSheetHandle contentEditableSheet = cache->ContentEditableSheet();
 
     if (!agentSheets.Contains(contentEditableSheet)) {
       agentSheets.AppendElement(contentEditableSheet);
     }
 
     // Should we update the editable state of all the nodes in the document? We
     // need to do this when the designMode value changes, as that overrides
     // specific states on the elements.
     if (designMode) {
       // designMode is being turned on (overrides contentEditable).
-      CSSStyleSheet* designModeSheet =
-        nsLayoutStylesheetCache::DesignModeSheet();
+      StyleSheetHandle designModeSheet = cache->DesignModeSheet();
       if (!agentSheets.Contains(designModeSheet)) {
         agentSheets.AppendElement(designModeSheet);
       }
 
       updateState = true;
       spellRecheckAll = oldState == eContentEditable;
     }
     else if (oldState == eDesignMode) {
       // designMode is being turned off (contentEditable is still on).
-      agentSheets.RemoveElement(nsLayoutStylesheetCache::DesignModeSheet());
+      agentSheets.RemoveElement(cache->DesignModeSheet());
       updateState = true;
     }
 
     rv = presShell->SetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
     presShell->ReconstructStyleData();
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2579,17 +2579,20 @@ OnFinishNuwaPreparation()
   MakeNuwaProcess();
 }
 #endif
 
 static void
 PreloadSlowThings()
 {
   // This fetches and creates all the built-in stylesheets.
-  nsLayoutStylesheetCache::UserContentSheet();
+  //
+  // XXXheycam In the future we might want to preload the Servo-flavoured
+  // UA sheets too, but for now that will be a waste of time.
+  nsLayoutStylesheetCache::For(StyleBackendType::Gecko)->UserContentSheet();
 
   TabChild::PreloadSlowThings();
 
 }
 
 bool
 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID,
                           const nsCString& name, const nsCString& UAName,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -180,16 +180,18 @@
 #include "prio.h"
 #include "private/pprio.h"
 #include "ContentProcessManager.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/psm/PSMContentListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginTags.h"
 #include "nsIBlocklistService.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #include "nsIBidiKeyboard.h"
 
 #ifdef MOZ_WEBRTC
 #include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
 #if defined(ANDROID) || defined(LINUX)
@@ -2692,29 +2694,29 @@ ContentParent::InitInternal(ProcessPrior
     Unused << SendAppInit();
   }
 
   nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
   if (sheetService) {
     // This looks like a lot of work, but in a normal browser session we just
     // send two loads.
 
-    for (CSSStyleSheet* sheet : *sheetService->AgentStyleSheets()) {
+    for (StyleSheetHandle sheet : *sheetService->AgentStyleSheets()) {
       URIParams uri;
       SerializeURI(sheet->GetSheetURI(), uri);
       Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AGENT_SHEET);
     }
 
-    for (CSSStyleSheet* sheet : *sheetService->UserStyleSheets()) {
+    for (StyleSheetHandle sheet : *sheetService->UserStyleSheets()) {
       URIParams uri;
       SerializeURI(sheet->GetSheetURI(), uri);
       Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::USER_SHEET);
     }
 
-    for (CSSStyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
+    for (StyleSheetHandle sheet : *sheetService->AuthorStyleSheets()) {
       URIParams uri;
       SerializeURI(sheet->GetSheetURI(), uri);
       Unused << SendLoadAndRegisterSheet(uri, nsIStyleSheetService::AUTHOR_SHEET);
     }
   }
 
 #ifdef MOZ_CONTENT_SANDBOX
   bool shouldSandbox = true;
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -106,19 +106,19 @@ nsMathMLElement::BindToTree(nsIDocument*
   }
 
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     if (!doc->GetMathMLEnabled()) {
       // Enable MathML and setup the style sheet during binding, not element
       // construction, because we could move a MathML element from the document
       // that created it to another document.
+      auto cache = nsLayoutStylesheetCache::For(doc->GetStyleBackendType());
       doc->SetMathMLEnabled();
-      doc->
-        EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::MathMLSheet());
+      doc->EnsureOnDemandBuiltInUASheet(cache->MathMLSheet());
 
       // Rebuild style data for the presshell, because style system
       // optimizations may have taken place assuming MathML was disabled.
       // (See nsRuleNode::CheckSpecifiedProperties.)
       nsCOMPtr<nsIPresShell> shell = doc->GetShell();
       if (shell) {
         shell->GetPresContext()->
           PostRebuildAllStyleDataEvent(nsChangeHint(0), eRestyle_Subtree);
--- a/dom/svg/SVGDocument.cpp
+++ b/dom/svg/SVGDocument.cpp
@@ -15,16 +15,18 @@
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsLiteralString.h"
 #include "nsIDOMSVGElement.h"
 #include "mozilla/dom/Element.h"
 #include "nsSVGElement.h"
 #include "mozilla/dom/SVGDocumentBinding.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla::css;
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
@@ -150,45 +152,47 @@ SVGDocument::EnsureNonSVGUserAgentStyleS
           catMan->GetCategoryEntry("agent-style-sheets", name.get(),
                                    getter_Copies(spec));
 
           mozilla::css::Loader* cssLoader = CSSLoader();
           if (cssLoader->GetEnabled()) {
             nsCOMPtr<nsIURI> uri;
             NS_NewURI(getter_AddRefs(uri), spec);
             if (uri) {
-              RefPtr<CSSStyleSheet> cssSheet;
+              StyleSheetHandle::RefPtr sheet;
               cssLoader->LoadSheetSync(uri,
                                        mozilla::css::eAgentSheetFeatures,
-                                       true, getter_AddRefs(cssSheet));
-              if (cssSheet) {
-                EnsureOnDemandBuiltInUASheet(cssSheet);
+                                       true, &sheet);
+              if (sheet) {
+                EnsureOnDemandBuiltInUASheet(sheet);
               }
             }
           }
         }
       }
     }
   }
 
-  CSSStyleSheet* sheet = nsLayoutStylesheetCache::NumberControlSheet();
+  auto cache = nsLayoutStylesheetCache::For(GetStyleBackendType());
+
+  StyleSheetHandle sheet = cache->NumberControlSheet();
   if (sheet) {
     // number-control.css can be behind a pref
     EnsureOnDemandBuiltInUASheet(sheet);
   }
-  EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::FormsSheet());
-  EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::CounterStylesSheet());
-  EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::HTMLSheet());
+  EnsureOnDemandBuiltInUASheet(cache->FormsSheet());
+  EnsureOnDemandBuiltInUASheet(cache->CounterStylesSheet());
+  EnsureOnDemandBuiltInUASheet(cache->HTMLSheet());
   if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) {
-    EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::NoFramesSheet());
+    EnsureOnDemandBuiltInUASheet(cache->NoFramesSheet());
   }
   if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) {
-    EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::NoScriptSheet());
+    EnsureOnDemandBuiltInUASheet(cache->NoScriptSheet());
   }
-  EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::UASheet());
+  EnsureOnDemandBuiltInUASheet(cache->UASheet());
 
   EndUpdate(UPDATE_STYLE);
 }
 
 JSObject*
 SVGDocument::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return SVGDocumentBinding::Wrap(aCx, this, aGivenProto);
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -747,17 +747,18 @@ SVGSVGElement::BindToTree(nsIDocument* a
                                               aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     // Setup the style sheet during binding, not element construction,
     // because we could move the root SVG element from the document
     // that created it to another document.
-    doc->EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::SVGSheet());
+    auto cache = nsLayoutStylesheetCache::For(doc->GetStyleBackendType());
+    doc->EnsureOnDemandBuiltInUASheet(cache->SVGSheet());
   }
 
   if (mTimedDocumentRoot && smilController) {
     rv = mTimedDocumentRoot->SetParent(smilController);
     if (mStartAnimationOnBindToTree) {
       mTimedDocumentRoot->Begin();
       mStartAnimationOnBindToTree = false;
     }
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -768,17 +768,17 @@ nsBindingManager::MediumFeaturesChanged(
     bool thisChanged = ruleProcessor->MediumFeaturesChanged(aPresContext);
     *aRulesChanged = *aRulesChanged || thisChanged;
   }
 
   return NS_OK;
 }
 
 void
-nsBindingManager::AppendAllSheets(nsTArray<CSSStyleSheet*>& aArray)
+nsBindingManager::AppendAllSheets(nsTArray<StyleSheetHandle>& aArray)
 {
   if (!mBoundContentSet) {
     return;
   }
 
   for (auto iter = mBoundContentSet->Iter(); !iter.Done(); iter.Next()) {
     nsIContent* boundContent = iter.Get()->GetKey();
     for (nsXBLBinding* binding = boundContent->GetXBLBinding(); binding;
--- a/dom/xbl/nsBindingManager.h
+++ b/dom/xbl/nsBindingManager.h
@@ -12,34 +12,31 @@
 #include "nsHashKeys.h"
 #include "nsInterfaceHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsXBLBinding.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
+#include "mozilla/StyleSheetHandle.h"
 
 struct ElementDependentRuleProcessorData;
 class nsIXPConnectWrappedJS;
 class nsIAtom;
 class nsIDOMNodeList;
 class nsIDocument;
 class nsIURI;
 class nsXBLDocumentInfo;
 class nsIStreamListener;
 class nsXBLBinding;
 typedef nsTArray<RefPtr<nsXBLBinding> > nsBindingList;
 class nsIPrincipal;
 class nsITimer;
 
-namespace mozilla {
-class CSSStyleSheet;
-} // namespace mozilla
-
 class nsBindingManager final : public nsStubMutationObserver
 {
   ~nsBindingManager();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@@ -124,17 +121,17 @@ public:
   /**
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether this rule
    * processor's rules have changed (e.g., because of media queries).
    */
   nsresult MediumFeaturesChanged(nsPresContext* aPresContext,
                                  bool* aRulesChanged);
 
-  void AppendAllSheets(nsTArray<mozilla::CSSStyleSheet*>& aArray);
+  void AppendAllSheets(nsTArray<mozilla::StyleSheetHandle>& aArray);
 
   void Traverse(nsIContent *aContent,
                             nsCycleCollectionTraversalCallback &cb);
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsBindingManager)
 
   // Notify the binding manager when an outermost update begins and
   // ends.  The end method can execute script.
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -39,16 +39,18 @@
 #include "nsIScriptError.h"
 
 #include "nsCSSRuleProcessor.h"
 #include "nsXBLResourceLoader.h"
 #include "mozilla/AddonPathService.h"
 #include "mozilla/dom/CDATASection.h"
 #include "mozilla/dom/Comment.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -1625,40 +1627,40 @@ void
 nsXBLPrototypeBinding::EnsureResources()
 {
   if (!mResources) {
     mResources = new nsXBLPrototypeResources(this);
   }
 }
 
 void
-nsXBLPrototypeBinding::AppendStyleSheet(CSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::AppendStyleSheet(StyleSheetHandle aSheet)
 {
   EnsureResources();
   mResources->AppendStyleSheet(aSheet);
 }
 
 void
-nsXBLPrototypeBinding::RemoveStyleSheet(CSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::RemoveStyleSheet(StyleSheetHandle aSheet)
 {
   if (!mResources) {
     MOZ_ASSERT(false, "Trying to remove a sheet that does not exist.");
     return;
   }
 
   mResources->RemoveStyleSheet(aSheet);
 } 
 void
-nsXBLPrototypeBinding::InsertStyleSheetAt(size_t aIndex, CSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::InsertStyleSheetAt(size_t aIndex, StyleSheetHandle aSheet)
 {
   EnsureResources();
   mResources->InsertStyleSheetAt(aIndex, aSheet);
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsXBLPrototypeBinding::StyleSheetAt(size_t aIndex) const
 {
   MOZ_ASSERT(mResources);
   return mResources->StyleSheetAt(aIndex);
 }
 
 size_t
 nsXBLPrototypeBinding::SheetCount() const
@@ -1669,14 +1671,14 @@ nsXBLPrototypeBinding::SheetCount() cons
 bool
 nsXBLPrototypeBinding::HasStyleSheets() const
 {
   return mResources && mResources->HasStyleSheets();
 }
 
 void
 nsXBLPrototypeBinding::AppendStyleSheetsTo(
-                                      nsTArray<CSSStyleSheet*>& aResult) const
+                                      nsTArray<StyleSheetHandle>& aResult) const
 {
   if (mResources) {
     mResources->AppendStyleSheetsTo(aResult);
   }
 }
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -14,28 +14,25 @@
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
 #include "nsXBLDocumentInfo.h"
 #include "nsXBLProtoImpl.h"
 #include "nsXBLProtoImplMethod.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLPrototypeResources.h"
 #include "mozilla/WeakPtr.h"
+#include "mozilla/StyleSheetHandle.h"
 
 class nsIAtom;
 class nsIContent;
 class nsIDocument;
 class nsXBLAttributeEntry;
 class nsXBLBinding;
 class nsXBLProtoImplField;
 
-namespace mozilla {
-class CSSStyleSheet;
-} // namespace mozilla
-
 // *********************************************************************/
 // The XBLPrototypeBinding class
 
 // Instances of this class are owned by the nsXBLDocumentInfo object returned
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
 class nsXBLPrototypeBinding final :
   public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
@@ -117,23 +114,23 @@ public:
   void SetBasePrototype(nsXBLPrototypeBinding* aBinding);
   nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; }
 
   nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; }
   bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); }
 
   void SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent);
 
-  void AppendStyleSheet(mozilla::CSSStyleSheet* aSheet);
-  void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet);
-  void InsertStyleSheetAt(size_t aIndex, mozilla::CSSStyleSheet* aSheet);
-  mozilla::CSSStyleSheet* StyleSheetAt(size_t aIndex) const;
+  void AppendStyleSheet(mozilla::StyleSheetHandle aSheet);
+  void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet);
+  void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheetHandle aSheet);
+  mozilla::StyleSheetHandle StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;
   bool HasStyleSheets() const;
-  void AppendStyleSheetsTo(nsTArray<mozilla::CSSStyleSheet*>& aResult) const;
+  void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheetHandle>& aResult) const;
 
   nsIStyleRuleProcessor* GetRuleProcessor();
 
   nsresult FlushSkinSheets();
 
   nsIAtom* GetBaseTag(int32_t* aNamespaceID);
   void SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag);
 
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -14,16 +14,18 @@
 #include "nsIDocumentObserver.h"
 #include "mozilla/css/Loader.h"
 #include "nsIURI.h"
 #include "nsLayoutCID.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsStyleSet.h"
 #include "mozilla/dom/URL.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using mozilla::dom::IsChromeURI;
 
 nsXBLPrototypeResources::nsXBLPrototypeResources(nsXBLPrototypeBinding* aBinding)
 {
   MOZ_COUNT_CTOR(nsXBLPrototypeResources);
 
@@ -75,30 +77,30 @@ nsXBLPrototypeResources::FlushSkinSheets
   if (!doc) {
     return NS_OK;
   }
 
   // We have scoped stylesheets.  Reload any chrome stylesheets we
   // encounter.  (If they aren't skin sheets, it doesn't matter, since
   // they'll still be in the chrome cache.
 
-  nsTArray<RefPtr<CSSStyleSheet>> oldSheets;
+  nsTArray<StyleSheetHandle::RefPtr> oldSheets;
 
   oldSheets.SwapElements(mStyleSheetList);
 
   mozilla::css::Loader* cssLoader = doc->CSSLoader();
 
   for (size_t i = 0, count = oldSheets.Length(); i < count; ++i) {
-    CSSStyleSheet* oldSheet = oldSheets[i];
+    StyleSheetHandle oldSheet = oldSheets[i];
 
     nsIURI* uri = oldSheet->GetSheetURI();
 
-    RefPtr<CSSStyleSheet> newSheet;
+    StyleSheetHandle::RefPtr newSheet;
     if (IsChromeURI(uri)) {
-      if (NS_FAILED(cssLoader->LoadSheetSync(uri, getter_AddRefs(newSheet))))
+      if (NS_FAILED(cssLoader->LoadSheetSync(uri, &newSheet)))
         continue;
     }
     else {
       newSheet = oldSheet;
     }
 
     mStyleSheetList.AppendElement(newSheet);
   }
@@ -137,41 +139,49 @@ void
 nsXBLPrototypeResources::ClearLoader()
 {
   mLoader = nullptr;
 }
 
 void
 nsXBLPrototypeResources::GatherRuleProcessor()
 {
-  mRuleProcessor = new nsCSSRuleProcessor(mStyleSheetList,
+  nsTArray<RefPtr<CSSStyleSheet>> sheets(mStyleSheetList.Length());
+  for (StyleSheetHandle sheet : mStyleSheetList) {
+    MOZ_ASSERT(sheet->IsGecko(),
+               "GatherRuleProcessor must only be called for "
+               "nsXBLPrototypeResources objects with Gecko-flavored style "
+               "backends");
+    sheets.AppendElement(sheet->AsGecko());
+  }
+  mRuleProcessor = new nsCSSRuleProcessor(sheets,
                                           SheetType::Doc,
                                           nullptr,
                                           mRuleProcessor);
 }
 
 void
-nsXBLPrototypeResources::AppendStyleSheet(CSSStyleSheet* aSheet)
+nsXBLPrototypeResources::AppendStyleSheet(StyleSheetHandle aSheet)
 {
   mStyleSheetList.AppendElement(aSheet);
 }
 
 void
-nsXBLPrototypeResources::RemoveStyleSheet(CSSStyleSheet* aSheet)
+nsXBLPrototypeResources::RemoveStyleSheet(StyleSheetHandle aSheet)
 {
   mStyleSheetList.RemoveElement(aSheet);
 }
 
 void
-nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, CSSStyleSheet* aSheet)
+nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, StyleSheetHandle aSheet)
 {
   mStyleSheetList.InsertElementAt(aIndex, aSheet);
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsXBLPrototypeResources::StyleSheetAt(size_t aIndex) const
 {
   return mStyleSheetList[aIndex];
 }
 
 size_t
 nsXBLPrototypeResources::SheetCount() const
 {
@@ -181,12 +191,12 @@ nsXBLPrototypeResources::SheetCount() co
 bool
 nsXBLPrototypeResources::HasStyleSheets() const
 {
   return !mStyleSheetList.IsEmpty();
 }
 
 void
 nsXBLPrototypeResources::AppendStyleSheetsTo(
-                                      nsTArray<CSSStyleSheet*>& aResult) const
+                                      nsTArray<StyleSheetHandle>& aResult) const
 {
   aResult.AppendElements(mStyleSheetList);
 }
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -2,16 +2,17 @@
 /* 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 nsXBLPrototypeResources_h__
 #define nsXBLPrototypeResources_h__
 
+#include "mozilla/StyleSheetHandle.h"
 #include "nsAutoPtr.h"
 #include "nsICSSLoaderObserver.h"
 
 class nsCSSRuleProcessor;
 class nsIAtom;
 class nsIContent;
 class nsXBLPrototypeBinding;
 class nsXBLResourceLoader;
@@ -36,37 +37,37 @@ public:
 
   nsresult Write(nsIObjectOutputStream* aStream);
 
   void Traverse(nsCycleCollectionTraversalCallback &cb);
   void Unlink();
 
   void ClearLoader();
 
-  void AppendStyleSheet(mozilla::CSSStyleSheet* aSheet);
-  void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet);
-  void InsertStyleSheetAt(size_t aIndex, mozilla::CSSStyleSheet* aSheet);
-  mozilla::CSSStyleSheet* StyleSheetAt(size_t aIndex) const;
+  void AppendStyleSheet(mozilla::StyleSheetHandle aSheet);
+  void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet);
+  void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheetHandle aSheet);
+  mozilla::StyleSheetHandle StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;
   bool HasStyleSheets() const;
-  void AppendStyleSheetsTo(nsTArray<mozilla::CSSStyleSheet*>& aResult) const;
+  void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheetHandle>& aResult) const;
 
   /**
    * Recreates mRuleProcessor to represent the current list of style sheets
    * stored in mStyleSheetList.  (Named GatherRuleProcessor to parallel
    * nsStyleSet::GatherRuleProcessors.)
    */
   void GatherRuleProcessor();
 
   nsCSSRuleProcessor* GetRuleProcessor() const { return mRuleProcessor; }
 
 private:
   // A loader object. Exists only long enough to load resources, and then it dies.
   RefPtr<nsXBLResourceLoader> mLoader;
 
   // A list of loaded stylesheets for this binding.
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mStyleSheetList;
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mStyleSheetList;
 
   // The list of stylesheets converted to a rule processor.
   RefPtr<nsCSSRuleProcessor> mRuleProcessor;
 };
 
 #endif
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -12,17 +12,18 @@
 #include "nsIPresShell.h"
 #include "nsXBLService.h"
 #include "nsIServiceManager.h"
 #include "nsXBLResourceLoader.h"
 #include "nsXBLPrototypeResources.h"
 #include "nsIDocumentObserver.h"
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
-#include "mozilla/CSSStyleSheet.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 #include "mozilla/css/Loader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsGkAtoms.h"
 #include "nsFrameManager.h"
 #include "nsStyleContext.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsCSSRuleProcessor.h"
@@ -134,18 +135,18 @@ nsXBLResourceLoader::LoadResources(bool*
       bool chrome;
       nsresult rv;
       if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
       {
         rv = nsContentUtils::GetSecurityManager()->
           CheckLoadURIWithPrincipal(docPrincipal, url,
                                     nsIScriptSecurityManager::ALLOW_CHROME);
         if (NS_SUCCEEDED(rv)) {
-          RefPtr<CSSStyleSheet> sheet;
-          rv = cssLoader->LoadSheetSync(url, getter_AddRefs(sheet));
+          StyleSheetHandle::RefPtr sheet;
+          rv = cssLoader->LoadSheetSync(url, &sheet);
           NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
           if (NS_SUCCEEDED(rv))
           {
             rv = StyleSheetLoaded(sheet, false, NS_OK);
             NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
           }
         }
       }
@@ -163,17 +164,17 @@ nsXBLResourceLoader::LoadResources(bool*
   
   // Destroy our resource list.
   delete mResourceList;
   mResourceList = nullptr;
 }
 
 // nsICSSLoaderObserver
 NS_IMETHODIMP
-nsXBLResourceLoader::StyleSheetLoaded(CSSStyleSheet* aSheet,
+nsXBLResourceLoader::StyleSheetLoaded(StyleSheetHandle aSheet,
                                       bool aWasAlternate,
                                       nsresult aStatus)
 {
   if (!mResources) {
     // Our resources got destroyed -- just bail out
     return NS_OK;
   }
    
--- a/dom/xbl/nsXBLResourceLoader.h
+++ b/dom/xbl/nsXBLResourceLoader.h
@@ -25,17 +25,17 @@ class nsIObjectOutputStream;
 
 class nsXBLResourceLoader : public nsICSSLoaderObserver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsXBLResourceLoader)
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) override;
 
   void LoadResources(bool* aResult);
   void AddResource(nsIAtom* aResourceType, const nsAString& aSrc);
   void AddResourceListener(nsIContent* aElement);
 
   nsXBLResourceLoader(nsXBLPrototypeBinding* aBinding,
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -406,17 +406,17 @@ nsXMLContentSink::OnTransformDone(nsresu
   ScrollToRef();
 
   originalDocument->EndLoad();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLContentSink::StyleSheetLoaded(CSSStyleSheet* aSheet,
+nsXMLContentSink::StyleSheetLoaded(StyleSheetHandle aSheet,
                                    bool aWasAlternate,
                                    nsresult aStatus)
 {
   if (!mPrettyPrinting) {
     return nsContentSink::StyleSheetLoaded(aSheet, aWasAlternate, aStatus);
   }
 
   if (!mDocument->CSSLoader()->HasPendingLoads()) {
--- a/dom/xml/nsXMLContentSink.h
+++ b/dom/xml/nsXMLContentSink.h
@@ -77,17 +77,17 @@ public:
   virtual bool IsScriptExecuting() override;
   virtual void ContinueInterruptedParsingAsync() override;
 
   // nsITransformObserver
   NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument) override;
   NS_IMETHOD OnTransformDone(nsresult aResult, nsIDocument *aResultDocument) override;
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) override;
   static bool ParsePIData(const nsString &aData, nsString &aHref,
                           nsString &aTitle, nsString &aMedia,
                           bool &aIsAlternate);
 
 protected:
   virtual ~nsXMLContentSink();
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -971,17 +971,17 @@ txTransformNotifier::ScriptEvaluated(nsr
     if (mScriptElements.RemoveObject(aElement)) {
         SignalTransformEnd();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-txTransformNotifier::StyleSheetLoaded(CSSStyleSheet* aSheet,
+txTransformNotifier::StyleSheetLoaded(StyleSheetHandle aSheet,
                                       bool aWasAlternate,
                                       nsresult aStatus)
 {
     if (mPendingStylesheetCount == 0) {
         // We weren't waiting on this stylesheet anyway.  This can happen if
         // SignalTransformEnd got called with an error aResult.  See
         // http://bugzilla.mozilla.org/show_bug.cgi?id=215465.
         return NS_OK;
--- a/dom/xslt/xslt/txMozillaXMLOutput.h
+++ b/dom/xslt/xslt/txMozillaXMLOutput.h
@@ -30,17 +30,17 @@ class txTransformNotifier final : public
 {
 public:
     txTransformNotifier();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTLOADEROBSERVER
     
     // nsICSSLoaderObserver
-    NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+    NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus) override;
 
     void Init(nsITransformObserver* aObserver);
     nsresult AddScriptElement(nsIScriptElement* aElement);
     void AddPendingStylesheet();
     void OnTransformEnd(nsresult aResult = NS_OK);
     void OnTransformStart();
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -88,16 +88,18 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
 #include "nsJSUtils.h"
 #include "mozilla/dom/URL.h"
 #include "nsIContentPolicy.h"
 #include "mozAutoDocUpdate.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 //
 // CIDs
 //
@@ -3093,17 +3095,17 @@ XULDocument::DoneWalking()
             }
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-XULDocument::StyleSheetLoaded(CSSStyleSheet* aSheet,
+XULDocument::StyleSheetLoaded(StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus)
 {
     if (!aWasAlternate) {
         // Don't care about when alternate sheets finish loading
 
         NS_ASSERTION(mPendingSheets > 0,
             "Unexpected StyleSheetLoaded notification");
@@ -3722,21 +3724,21 @@ XULDocument::AddPrototypeSheets()
 {
     nsresult rv;
 
     const nsCOMArray<nsIURI>& sheets = mCurrentPrototype->GetStyleSheetReferences();
 
     for (int32_t i = 0; i < sheets.Count(); i++) {
         nsCOMPtr<nsIURI> uri = sheets[i];
 
-        RefPtr<CSSStyleSheet> incompleteSheet;
+        StyleSheetHandle::RefPtr incompleteSheet;
         rv = CSSLoader()->LoadSheet(uri,
                                     mCurrentPrototype->DocumentPrincipal(),
                                     EmptyCString(), this,
-                                    getter_AddRefs(incompleteSheet));
+                                    &incompleteSheet);
 
         // XXXldb We need to prevent bogus sheets from being held in the
         // prototype's list, but until then, don't propagate the failure
         // from LoadSheet (and thus exit the loop).
         if (NS_SUCCEEDED(rv)) {
             ++mPendingSheets;
             if (!mOverlaySheets.AppendElement(incompleteSheet)) {
                 return NS_ERROR_OUT_OF_MEMORY;
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -7,16 +7,17 @@
 #define mozilla_dom_XULDocument_h
 
 #include "nsCOMPtr.h"
 #include "nsXULPrototypeDocument.h"
 #include "nsXULPrototypeCache.h"
 #include "nsTArray.h"
 
 #include "mozilla/dom/XMLDocument.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "nsForwardReference.h"
 #include "nsIContent.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMXULDocument.h"
 #include "nsCOMArray.h"
 #include "nsIURI.h"
 #include "nsIXULDocument.h"
 #include "nsScriptLoader.h"
@@ -156,17 +157,17 @@ public:
 
     // nsDocument interface overrides
     virtual Element* GetElementById(const nsAString & elementId) override;
 
     // nsIDOMXULDocument interface
     NS_DECL_NSIDOMXULDOCUMENT
 
     // nsICSSLoaderObserver
-    NS_IMETHOD StyleSheetLoaded(CSSStyleSheet* aSheet,
+    NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus) override;
 
     virtual void EndUpdate(nsUpdateType aUpdateType) override;
 
     virtual bool IsDocumentRightToLeft() override;
 
     virtual void ResetDocumentDirection() override;
@@ -337,17 +338,17 @@ protected:
      */
     bool                           mRestrictPersistence;
     nsTHashtable<nsStringHashKey>  mPersistenceIds;
 
     /**
      * An array of style sheets, that will be added (preserving order) to the
      * document after all of them are loaded (in DoneWalking).
      */
-    nsTArray<RefPtr<CSSStyleSheet>> mOverlaySheets;
+    nsTArray<StyleSheetHandle::RefPtr> mOverlaySheets;
 
     nsCOMPtr<nsIDOMXULCommandDispatcher>     mCommandDispatcher; // [OWNER] of the focus tracker
 
     // Maintains the template builders that have been attached to
     // content elements
     typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXULTemplateBuilder>
         BuilderTable;
     BuilderTable* mTemplateBuilderTable;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -854,17 +854,18 @@ nsXULElement::BindToTree(nsIDocument* aD
     // rules being in minimal-xul.css).  This is where we make sure that all
     // the other XUL UA style sheet rules (xul.css) have been loaded if the
     // minimal set is not sufficient.
     //
     // We do this during binding, not element construction, because elements
     // can be moved from the document that creates them to another document.
 
     if (!XULElementsRulesInMinimalXULSheet(NodeInfo()->NameAtom())) {
-      doc->EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::XULSheet());
+      auto cache = nsLayoutStylesheetCache::For(doc->GetStyleBackendType());
+      doc->EnsureOnDemandBuiltInUASheet(cache->XULSheet());
       // To keep memory usage down it is important that we try and avoid
       // pulling xul.css into non-XUL documents. That should be very rare, and
       // for HTML we currently should only pull it in if the document contains
       // an <audio> or <video> element. This assertion is here to make sure
       // that we don't fail to notice if a change to bindings causes us to
       // start pulling in xul.css much more frequently. If this assertion
       // fails then we need to figure out why, and how we can continue to avoid
       // pulling in xul.css.
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -4248,33 +4248,33 @@ nsEditor::CreateTxnForIMEText(const nsAS
                                             mIMETextLength,
                                             mComposition->GetRanges(),
                                             aStringToInsert, *this);
   return txn.forget();
 }
 
 
 NS_IMETHODIMP
-nsEditor::CreateTxnForAddStyleSheet(CSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn)
+nsEditor::CreateTxnForAddStyleSheet(StyleSheetHandle aSheet, AddStyleSheetTxn* *aTxn)
 {
   RefPtr<AddStyleSheetTxn> txn = new AddStyleSheetTxn();
 
   nsresult rv = txn->Init(this, aSheet);
   if (NS_SUCCEEDED(rv))
   {
     txn.forget(aTxn);
   }
 
   return rv;
 }
 
 
 
 NS_IMETHODIMP
-nsEditor::CreateTxnForRemoveStyleSheet(CSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn)
+nsEditor::CreateTxnForRemoveStyleSheet(StyleSheetHandle aSheet, RemoveStyleSheetTxn* *aTxn)
 {
   RefPtr<RemoveStyleSheetTxn> txn = new RemoveStyleSheetTxn();
 
   nsresult rv = txn->Init(this, aSheet);
   if (NS_SUCCEEDED(rv))
   {
     txn.forget(aTxn);
   }
--- a/editor/libeditor/nsEditor.h
+++ b/editor/libeditor/nsEditor.h
@@ -3,16 +3,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/. */
 
 #ifndef __editor_h__
 #define __editor_h__
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
 #include "mozilla/OwningNonNull.h"      // for OwningNonNull
+#include "mozilla/StyleSheetHandle.h"   // for StyleSheetHandle
 #include "mozilla/dom/Text.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
 #include "nsCycleCollectionParticipant.h"
 #include "nsGkAtoms.h"
 #include "nsIEditor.h"                  // for nsIEditor::EDirection, etc
 #include "nsIEditorIMESupport.h"        // for NS_DECL_NSIEDITORIMESUPPORT, etc
 #include "nsIObserver.h"                // for NS_DECL_NSIOBSERVER, etc
@@ -50,17 +51,16 @@ class nsISupports;
 class nsITransaction;
 class nsIWidget;
 class nsRange;
 class nsString;
 class nsTransactionManager;
 struct DOMPoint;
 
 namespace mozilla {
-class CSSStyleSheet;
 class ErrorResult;
 class TextComposition;
 
 namespace dom {
 class ChangeAttributeTxn;
 class CreateElementTxn;
 class DataTransfer;
 class DeleteTextTxn;
@@ -306,22 +306,22 @@ protected:
                          mozilla::dom::Text& aTextNode, int32_t aOffset);
 
   // Never returns null.
   already_AddRefed<mozilla::dom::IMETextTxn>
   CreateTxnForIMEText(const nsAString & aStringToInsert);
 
   /** create a transaction for adding a style sheet
     */
-  NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::StyleSheetHandle aSheet,
                                        AddStyleSheetTxn* *aTxn);
 
   /** create a transaction for removing a style sheet
     */
-  NS_IMETHOD CreateTxnForRemoveStyleSheet(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD CreateTxnForRemoveStyleSheet(mozilla::StyleSheetHandle aSheet,
                                           RemoveStyleSheetTxn* *aTxn);
 
   nsresult DeleteText(nsGenericDOMDataNode& aElement,
                       uint32_t aOffset, uint32_t aLength);
 
 //  NS_IMETHOD DeleteRange(nsIDOMRange *aRange);
 
   already_AddRefed<mozilla::dom::DeleteTextTxn>
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -32,17 +32,16 @@
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsISelectionController.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsILinkHandler.h"
 #include "nsIInlineSpellChecker.h"
 
-#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMStyleSheet.h"
 
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsISupportsArray.h"
 #include "nsContentUtils.h"
 #include "nsIDocumentEncoder.h"
@@ -70,16 +69,18 @@
 #include "nsIParserService.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "nsTextFragment.h"
 #include "nsContentList.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::widget;
 
 // Some utilities to handle overloading of "A" tag for link and named anchor.
 static bool
 IsLinkTag(const nsString& s)
@@ -2820,23 +2821,21 @@ nsHTMLEditor::ReplaceStyleSheet(const ns
 
   return ps->GetDocument()->CSSLoader()->
     LoadSheet(uaURI, false, nullptr, EmptyCString(), this);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::RemoveStyleSheet(const nsAString &aURL)
 {
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
-  NS_ENSURE_SUCCESS(rv, rv);
+  StyleSheetHandle::RefPtr sheet = GetStyleSheetForURL(aURL);
   NS_ENSURE_TRUE(sheet, NS_ERROR_UNEXPECTED);
 
   RefPtr<RemoveStyleSheetTxn> txn;
-  rv = CreateTxnForRemoveStyleSheet(sheet, getter_AddRefs(txn));
+  nsresult rv = CreateTxnForRemoveStyleSheet(sheet, getter_AddRefs(txn));
   if (!txn) rv = NS_ERROR_NULL_POINTER;
   if (NS_SUCCEEDED(rv))
   {
     rv = DoTransaction(txn);
     if (NS_SUCCEEDED(rv))
       mLastStyleSheetURL.Truncate();        // forget it
 
     // Remove it from our internal list
@@ -2860,21 +2859,21 @@ nsHTMLEditor::AddOverrideStyleSheet(cons
 
   nsCOMPtr<nsIURI> uaURI;
   nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We MUST ONLY load synchronous local files (no @import)
   // XXXbz Except this will actually try to load remote files
   // synchronously, of course..
-  RefPtr<CSSStyleSheet> sheet;
+  StyleSheetHandle::RefPtr sheet;
   // Editor override style sheets may want to style Gecko anonymous boxes
   rv = ps->GetDocument()->CSSLoader()->
     LoadSheetSync(uaURI, mozilla::css::eAgentSheetFeatures, true,
-                  getter_AddRefs(sheet));
+                  &sheet);
 
   // Synchronous loads should ALWAYS return completed
   NS_ENSURE_TRUE(sheet, NS_ERROR_NULL_POINTER);
 
   // Add the override style sheet
   // (This checks if already exists)
   ps->AddOverrideStyleSheet(sheet);
 
@@ -2905,18 +2904,17 @@ nsHTMLEditor::ReplaceOverrideStyleSheet(
 
   return AddOverrideStyleSheet(aURL);
 }
 
 // Do NOT use transaction system for override style sheets
 NS_IMETHODIMP
 nsHTMLEditor::RemoveOverrideStyleSheet(const nsAString &aURL)
 {
-  RefPtr<CSSStyleSheet> sheet;
-  GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
+  StyleSheetHandle::RefPtr sheet = GetStyleSheetForURL(aURL);
 
   // Make sure we remove the stylesheet from our internal list in all
   // cases.
   nsresult rv = RemoveStyleSheetFromList(aURL);
 
   NS_ENSURE_TRUE(sheet, NS_OK); /// Don't fail if sheet not found
 
   NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
@@ -2928,51 +2926,57 @@ nsHTMLEditor::RemoveOverrideStyleSheet(c
 
   // Remove it from our internal list
   return rv;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::EnableStyleSheet(const nsAString &aURL, bool aEnable)
 {
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
-  NS_ENSURE_SUCCESS(rv, rv);
+  StyleSheetHandle::RefPtr sheet = GetStyleSheetForURL(aURL);
   NS_ENSURE_TRUE(sheet, NS_OK); // Don't fail if sheet not found
 
   // Ensure the style sheet is owned by our document.
   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
   sheet->SetOwningDocument(doc);
 
-  return sheet->SetDisabled(!aEnable);
+  if (sheet->IsServo()) {
+    // XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
+    NS_ERROR("stylo: ServoStyleSheets can't be disabled yet");
+    return NS_ERROR_FAILURE;
+  }
+  return sheet->AsGecko()->SetDisabled(!aEnable);
 }
 
 bool
 nsHTMLEditor::EnableExistingStyleSheet(const nsAString &aURL)
 {
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
-  NS_ENSURE_SUCCESS(rv, false);
+  StyleSheetHandle::RefPtr sheet = GetStyleSheetForURL(aURL);
 
   // Enable sheet if already loaded.
   if (sheet)
   {
     // Ensure the style sheet is owned by our document.
     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
     sheet->SetOwningDocument(doc);
 
-    sheet->SetDisabled(false);
+    if (sheet->IsServo()) {
+      // XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
+      NS_ERROR("stylo: ServoStyleSheets can't be disabled yet");
+      return true;
+    }
+    sheet->AsGecko()->SetDisabled(false);
     return true;
   }
   return false;
 }
 
 nsresult
 nsHTMLEditor::AddNewStyleSheetToList(const nsAString &aURL,
-                                     CSSStyleSheet* aStyleSheet)
+                                     StyleSheetHandle aStyleSheet)
 {
   uint32_t countSS = mStyleSheets.Length();
   uint32_t countU = mStyleSheetURLs.Length();
 
   if (countSS != countU)
     return NS_ERROR_UNEXPECTED;
 
   if (!mStyleSheetURLs.AppendElement(aURL))
@@ -2992,51 +2996,43 @@ nsHTMLEditor::RemoveStyleSheetFromList(c
 
   // Attempt both removals; if one fails there's not much we can do.
   mStyleSheets.RemoveElementAt(foundIndex);
   mStyleSheetURLs.RemoveElementAt(foundIndex);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLEditor::GetStyleSheetForURL(const nsAString &aURL,
-                                  CSSStyleSheet** aStyleSheet)
+StyleSheetHandle
+nsHTMLEditor::GetStyleSheetForURL(const nsAString& aURL)
 {
-  NS_ENSURE_ARG_POINTER(aStyleSheet);
-  *aStyleSheet = 0;
-
   // is it already in the list?
   size_t foundIndex;
   foundIndex = mStyleSheetURLs.IndexOf(aURL);
-  if (foundIndex == mStyleSheetURLs.NoIndex)
-    return NS_OK; //No sheet -- don't fail!
-
-  *aStyleSheet = mStyleSheets[foundIndex];
-  NS_ENSURE_TRUE(*aStyleSheet, NS_ERROR_FAILURE);
-
-  NS_ADDREF(*aStyleSheet);
-
-  return NS_OK;
+  if (foundIndex == mStyleSheetURLs.NoIndex) {
+    return nullptr;
+  }
+
+  MOZ_ASSERT(mStyleSheets[foundIndex]);
+  return mStyleSheets[foundIndex];
 }
 
-NS_IMETHODIMP
-nsHTMLEditor::GetURLForStyleSheet(CSSStyleSheet* aStyleSheet,
-                                  nsAString &aURL)
+void
+nsHTMLEditor::GetURLForStyleSheet(StyleSheetHandle aStyleSheet,
+                                  nsAString& aURL)
 {
   // is it already in the list?
   int32_t foundIndex = mStyleSheets.IndexOf(aStyleSheet);
 
   // Don't fail if we don't find it in our list
   if (foundIndex == -1)
-    return NS_OK;
+    return;
 
   // Found it in the list!
   aURL = mStyleSheetURLs[foundIndex];
-  return NS_OK;
 }
 
 /*
  * nsIEditorMailSupport methods
  */
 
 NS_IMETHODIMP
 nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList)
@@ -3390,17 +3386,17 @@ nsHTMLEditor::DebugUnitTests(int32_t *ou
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
 
 NS_IMETHODIMP
-nsHTMLEditor::StyleSheetLoaded(CSSStyleSheet* aSheet, bool aWasAlternate,
+nsHTMLEditor::StyleSheetLoaded(StyleSheetHandle aSheet, bool aWasAlternate,
                                nsresult aStatus)
 {
   nsresult rv = NS_OK;
   nsAutoEditBatch batchIt(this);
 
   if (!mLastStyleSheetURL.IsEmpty())
     RemoveStyleSheet(mLastStyleSheetURL);
 
--- a/editor/libeditor/nsHTMLEditor.h
+++ b/editor/libeditor/nsHTMLEditor.h
@@ -34,16 +34,17 @@
 #include "nsPoint.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsAttrName.h"
 #include "nsStubMutationObserver.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/StyleSheetHandle.h"
 
 class nsDocumentFragment;
 class nsIDOMKeyEvent;
 class nsITransferable;
 class nsIClipboard;
 class TypeInState;
 class nsIContentFilter;
 class nsILinkHandler;
@@ -328,17 +329,17 @@ public:
 
   NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable) override;
 
   NS_IMETHOD SelectAll() override;
 
   NS_IMETHOD GetRootElement(nsIDOMElement **aRootElement) override;
 
   /* ------------ nsICSSLoaderObserver -------------- */
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate, nsresult aStatus) override;
 
   /* ------------ Utility Routines, not part of public API -------------- */
   NS_IMETHOD TypedText(const nsAString& aString, ETypingAction aAction) override;
   nsresult InsertNodeAtPoint( nsIDOMNode *aNode,
                               nsCOMPtr<nsIDOMNode> *ioParent,
                               int32_t *ioOffset,
                               bool aNoEmptyNodes);
@@ -373,24 +374,23 @@ public:
                            bool aListOrCellNotEmpty,
                            bool aSafeToAskFrames,
                            bool *aSeenBR);
 
   // Returns TRUE if sheet was loaded, false if it wasn't
   bool     EnableExistingStyleSheet(const nsAString& aURL);
 
   // Dealing with the internal style sheet lists:
-  NS_IMETHOD GetStyleSheetForURL(const nsAString &aURL,
-                                 mozilla::CSSStyleSheet** _retval) override;
-  NS_IMETHOD GetURLForStyleSheet(mozilla::CSSStyleSheet* aStyleSheet,
-                                 nsAString& aURL) override;
+  mozilla::StyleSheetHandle GetStyleSheetForURL(const nsAString& aURL);
+  void GetURLForStyleSheet(mozilla::StyleSheetHandle aStyleSheet,
+                           nsAString& aURL);
 
   // Add a url + known style sheet to the internal lists:
   nsresult AddNewStyleSheetToList(const nsAString &aURL,
-                                  mozilla::CSSStyleSheet* aStyleSheet);
+                                  mozilla::StyleSheetHandle aStyleSheet);
 
   nsresult RemoveStyleSheetFromList(const nsAString &aURL);
 
   bool IsCSSEnabled()
   {
     // TODO: removal of mCSSAware and use only the presence of mHTMLCSSUtils
     return mCSSAware && mHTMLCSSUtils && mHTMLCSSUtils->IsCSSPrefChecked();
   }
@@ -777,17 +777,17 @@ protected:
   // Used by GetFirstSelectedCell and GetNextSelectedCell
   int32_t  mSelectedCellIndex;
 
   nsString mLastStyleSheetURL;
   nsString mLastOverrideStyleSheetURL;
 
   // Maintain a list of associated style sheets and their urls.
   nsTArray<nsString> mStyleSheetURLs;
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mStyleSheets;
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mStyleSheets;
 
   // an array for holding default style settings
   nsTArray<PropItem*> mDefaultStyles;
 
 protected:
 
   /* ANONYMOUS UTILS */
   void     RemoveListenerAndDeleteRef(const nsAString& aEvent,
--- a/editor/libeditor/nsStyleSheetTxns.cpp
+++ b/editor/libeditor/nsStyleSheetTxns.cpp
@@ -4,41 +4,42 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsStyleSheetTxns.h"
 
 #include <stddef.h>                     // for nullptr
 
 #include "nsAString.h"
 #include "nsCOMPtr.h"                   // for nsCOMPtr, do_QueryInterface, etc
-#include "mozilla/CSSStyleSheet.h"      // for mozilla::CSSStyleSheet
+#include "mozilla/StyleSheetHandle.h"   // for mozilla::StyleSheetHandle
+#include "mozilla/StyleSheetHandleInlines.h"
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE
 #include "nsError.h"                    // for NS_OK, etc
 #include "nsIDOMDocument.h"             // for nsIDOMDocument
 #include "nsIDocument.h"                // for nsIDocument
 #include "nsIDocumentObserver.h"        // for UPDATE_STYLE
 #include "nsIEditor.h"                  // for nsIEditor
 
 using namespace mozilla;
 
 static void
-AddStyleSheet(nsIEditor* aEditor, CSSStyleSheet* aSheet)
+AddStyleSheet(nsIEditor* aEditor, StyleSheetHandle aSheet)
 {
   nsCOMPtr<nsIDOMDocument> domDoc;
   aEditor->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   if (doc) {
     doc->BeginUpdate(UPDATE_STYLE);
     doc->AddStyleSheet(aSheet);
     doc->EndUpdate(UPDATE_STYLE);
   }
 }
 
 static void
-RemoveStyleSheet(nsIEditor* aEditor, CSSStyleSheet* aSheet)
+RemoveStyleSheet(nsIEditor* aEditor, StyleSheetHandle aSheet)
 {
   nsCOMPtr<nsIDOMDocument> domDoc;
   aEditor->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   if (doc) {
     doc->BeginUpdate(UPDATE_STYLE);
     doc->RemoveStyleSheet(aSheet);
     doc->EndUpdate(UPDATE_STYLE);
@@ -53,17 +54,17 @@ AddStyleSheetTxn::AddStyleSheetTxn()
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AddStyleSheetTxn, EditTxn,
                                    mSheet)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddStyleSheetTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP
-AddStyleSheetTxn::Init(nsIEditor *aEditor, CSSStyleSheet *aSheet)
+AddStyleSheetTxn::Init(nsIEditor* aEditor, StyleSheetHandle aSheet)
 {
   NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
 
   mEditor = aEditor;
   mSheet = aSheet;
 
   return NS_OK;
 }
@@ -103,17 +104,17 @@ RemoveStyleSheetTxn::RemoveStyleSheetTxn
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(RemoveStyleSheetTxn, EditTxn,
                                    mSheet)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoveStyleSheetTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP
-RemoveStyleSheetTxn::Init(nsIEditor *aEditor, CSSStyleSheet *aSheet)
+RemoveStyleSheetTxn::Init(nsIEditor* aEditor, StyleSheetHandle aSheet)
 {
   NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
 
   mEditor = aEditor;
   mSheet = aSheet;
 
   return NS_OK;
 }
--- a/editor/libeditor/nsStyleSheetTxns.h
+++ b/editor/libeditor/nsStyleSheetTxns.h
@@ -3,67 +3,64 @@
  * 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 nsStylesheetTxns_h__
 #define nsStylesheetTxns_h__
 
 #include "EditTxn.h"                    // for EditTxn, NS_DECL_EDITTXN
 #include "nsAutoPtr.h"                  // for nsRefPtr
-#include "mozilla/CSSStyleSheet.h"      // for mozilla::CSSStyleSheet
+#include "mozilla/StyleSheetHandle.h"   // for mozilla::StyleSheetHandle
 #include "nsCycleCollectionParticipant.h"
 #include "nsID.h"                       // for REFNSIID
-#include "nsISupportsImpl.h"            // for CSSStyleSheet::Release
 #include "nscore.h"                     // for NS_IMETHOD
 
 class nsIEditor;
 
 class AddStyleSheetTxn : public EditTxn
 {
 public:
   /** Initialize the transaction.
     * @param aEditor the object providing core editing operations
     * @param aSheet   the stylesheet to add
     */
-  NS_IMETHOD Init(nsIEditor* aEditor,
-                  mozilla::CSSStyleSheet* aSheet);
+  NS_IMETHOD Init(nsIEditor* aEditor, mozilla::StyleSheetHandle aSheet);
 
   AddStyleSheetTxn();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AddStyleSheetTxn, EditTxn)
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   NS_DECL_EDITTXN
 
 protected:
 
   nsIEditor* mEditor;                      // the editor that created this transaction
-  RefPtr<mozilla::CSSStyleSheet> mSheet; // the style sheet to add
+  mozilla::StyleSheetHandle::RefPtr mSheet; // the style sheet to add
 
 };
 
 
 class RemoveStyleSheetTxn : public EditTxn
 {
 public:
   /** Initialize the transaction.
     * @param aEditor the object providing core editing operations
     * @param aSheet   the stylesheet to remove
     */
-  NS_IMETHOD Init(nsIEditor* aEditor,
-                  mozilla::CSSStyleSheet* aSheet);
+  NS_IMETHOD Init(nsIEditor* aEditor, mozilla::StyleSheetHandle aSheet);
 
   RemoveStyleSheetTxn();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RemoveStyleSheetTxn, EditTxn)
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
   NS_DECL_EDITTXN
 
 protected:
 
   nsIEditor* mEditor;                      // the editor that created this transaction
-  RefPtr<mozilla::CSSStyleSheet> mSheet; // the style sheet to remove
+  mozilla::StyleSheetHandle::RefPtr mSheet; // the style sheet to remove
 
 };
 
 
 #endif /* nsStylesheetTxns_h__ */
--- a/editor/nsIEditorStyleSheets.idl
+++ b/editor/nsIEditorStyleSheets.idl
@@ -1,23 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "nsISupports.idl"
 
-%{C++
-namespace mozilla {
-class CSSStyleSheet;
-} // namespace mozilla
-%}
-
-[ptr] native CSSStyleSheet(mozilla::CSSStyleSheet);
-
 [scriptable, uuid(4805e682-49b9-11d3-9ce4-ed60bd6cb5bc)]
 
 interface nsIEditorStyleSheets : nsISupports
 {
   /** Load and apply the style sheet, specified by aURL, to the
     * editor's document, replacing the last style sheet added (if any).
     * This is always asynchronous, and may cause network I/O.
     *
@@ -71,23 +63,9 @@ interface nsIEditorStyleSheets : nsISupp
 
   /** Enable or disable the given style sheet from the editor's document
     * This is always synchronous
     *
     * @param aURL  The style sheet to be enabled or disabled
     * @param aEnable true to enable, or false to disable the style sheet
     */
   void enableStyleSheet(in AString aURL, in boolean aEnable);
-
-  /** Get the CSSStyleSheet associated with the given URL.
-    *
-    * @param aURL         The style sheet's URL
-    * @return             the style sheet
-    */
-  [noscript] CSSStyleSheet getStyleSheetForURL(in AString aURL);
-
-  /** Get the URL associated with the given CSSStyleSheet.
-    *
-    * @param aStyleSheet  The style sheet
-    * @return             the style sheet's URL
-    */
-  [noscript] AString getURLForStyleSheet(in CSSStyleSheet aStyleSheet);
 };
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -35,16 +35,18 @@
 #include "nsLayoutStylesheetCache.h"
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/DocAccessible.h"
 #endif
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/WeakPtr.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #include "nsViewManager.h"
 #include "nsView.h"
 
 #include "nsIPageSequenceFrame.h"
 #include "nsNetUtil.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIContentViewerFile.h"
@@ -2165,36 +2167,37 @@ nsDocumentViewer::CreateStyleSet(nsIDocu
     // XXXjwatt Nothing else is loaded on-demand, but I don't think that
     // should matter for SVG-as-an-image. If it does, I want to know why!
 
     // Caller will handle calling EndUpdate, per contract.
     *aStyleSet = styleSet;
     return NS_OK;
   }
 
+  auto cache = nsLayoutStylesheetCache::For(styleSet->BackendType());
+
   // Handle the user sheets.
-  CSSStyleSheet* sheet = nullptr;
+  StyleSheetHandle sheet = nullptr;
   if (nsContentUtils::IsInChromeDocshell(aDocument)) {
-    sheet = nsLayoutStylesheetCache::UserChromeSheet();
-  }
-  else {
-    sheet = nsLayoutStylesheetCache::UserContentSheet();
+    sheet = cache->UserChromeSheet();
+  } else {
+    sheet = cache->UserContentSheet();
   }
 
   if (sheet)
     styleSet->AppendStyleSheet(SheetType::User, sheet);
 
   // Append chrome sheets (scrollbars + forms).
   bool shouldOverride = false;
   // We don't want a docshell here for external resource docs, so just
   // look at mContainer.
   nsCOMPtr<nsIDocShell> ds(mContainer);
   nsCOMPtr<nsIDOMEventTarget> chromeHandler;
   nsCOMPtr<nsIURI> uri;
-  RefPtr<CSSStyleSheet> csssheet;
+  StyleSheetHandle::RefPtr chromeSheet;
 
   if (ds) {
     ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
   }
   if (chromeHandler) {
     nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
     nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
     if (elt && content) {
@@ -2208,113 +2211,113 @@ nsDocumentViewer::CreateStyleSet(nsIDocu
         char *str = ToNewCString(sheets);
         char *newStr = str;
         char *token;
         while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) {
           NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nullptr,
                     baseURI);
           if (!uri) continue;
 
-          cssLoader->LoadSheetSync(uri, getter_AddRefs(csssheet));
-          if (!csssheet) continue;
-
-          styleSet->PrependStyleSheet(SheetType::Agent, csssheet);
+          cssLoader->LoadSheetSync(uri, &chromeSheet);
+          if (!chromeSheet) continue;
+
+          styleSet->PrependStyleSheet(SheetType::Agent, chromeSheet);
           shouldOverride = true;
         }
         free(str);
       }
     }
   }
 
   if (!shouldOverride) {
-    sheet = nsLayoutStylesheetCache::ScrollbarsSheet();
+    sheet = cache->ScrollbarsSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
   }
 
   if (!aDocument->IsSVGDocument()) {
     // !!! IMPORTANT - KEEP THIS BLOCK IN SYNC WITH
     // !!! SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded.
 
     // SVGForeignObjectElement::BindToTree calls SVGDocument::
     // EnsureNonSVGUserAgentStyleSheetsLoaded to loads these UA sheet
     // on-demand. (Excluding the quirks sheet, which should never be loaded for
     // an SVG document, and excluding xul.css which will be loaded on demand by
     // nsXULElement::BindToTree.)
 
-    sheet = nsLayoutStylesheetCache::NumberControlSheet();
+    sheet = cache->NumberControlSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
 
-    sheet = nsLayoutStylesheetCache::FormsSheet();
+    sheet = cache->FormsSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
 
     if (aDocument->LoadsFullXULStyleSheetUpFront()) {
       // nsXULElement::BindToTree loads xul.css on-demand if we don't load it
       // up-front here.
-      sheet = nsLayoutStylesheetCache::XULSheet();
+      sheet = cache->XULSheet();
       if (sheet) {
         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
       }
     }
 
-    sheet = nsLayoutStylesheetCache::MinimalXULSheet();
+    sheet = cache->MinimalXULSheet();
     if (sheet) {
       // Load the minimal XUL rules for scrollbars and a few other XUL things
       // that non-XUL (typically HTML) documents commonly use.
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
 
-    sheet = nsLayoutStylesheetCache::CounterStylesSheet();
+    sheet = cache->CounterStylesSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
 
     if (nsLayoutUtils::ShouldUseNoScriptSheet(aDocument)) {
-      sheet = nsLayoutStylesheetCache::NoScriptSheet();
+      sheet = cache->NoScriptSheet();
       if (sheet) {
         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
       }
     }
 
     if (nsLayoutUtils::ShouldUseNoFramesSheet(aDocument)) {
-      sheet = nsLayoutStylesheetCache::NoFramesSheet();
+      sheet = cache->NoFramesSheet();
       if (sheet) {
         styleSet->PrependStyleSheet(SheetType::Agent, sheet);
       }
     }
 
     // We don't add quirk.css here; nsPresContext::CompatibilityModeChanged will
     // append it if needed.
 
-    sheet = nsLayoutStylesheetCache::HTMLSheet();
+    sheet = cache->HTMLSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
 
     styleSet->PrependStyleSheet(SheetType::Agent,
-                                nsLayoutStylesheetCache::UASheet());
+                                cache->UASheet());
   } else {
     // SVG documents may have scrollbars and need the scrollbar styling.
-    sheet = nsLayoutStylesheetCache::MinimalXULSheet();
+    sheet = cache->MinimalXULSheet();
     if (sheet) {
       styleSet->PrependStyleSheet(SheetType::Agent, sheet);
     }
   }
 
   nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
   if (sheetService) {
-    for (CSSStyleSheet* sheet : *sheetService->AgentStyleSheets()) {
+    for (StyleSheetHandle sheet : *sheetService->AgentStyleSheets()) {
       styleSet->AppendStyleSheet(SheetType::Agent, sheet);
     }
-    for (CSSStyleSheet* sheet : Reversed(*sheetService->UserStyleSheets())) {
+    for (StyleSheetHandle sheet : Reversed(*sheetService->UserStyleSheets())) {
       styleSet->PrependStyleSheet(SheetType::User, sheet);
     }
   }
 
   // Caller will handle calling EndUpdate, per contract.
   *aStyleSet = styleSet;
   return NS_OK;
 }
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -20,16 +20,17 @@
 #ifndef nsIPresShell_h___
 #define nsIPresShell_h___
 
 #include "mozilla/ArenaObjectID.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/StyleSetHandle.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "mozilla/WeakPtr.h"
 #include "gfxPoint.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "nsISupports.h"
 #include "nsIContent.h"
 #include "nsQueryFrame.h"
 #include "nsCoord.h"
@@ -940,33 +941,33 @@ public:
    * Indicates whether theme support is enabled.
    */
   bool IsThemeSupportEnabled() const { return !mIsThemeSupportDisabled; }
 
   /**
    * Get the set of agent style sheets for this presentation
    */
   virtual nsresult GetAgentStyleSheets(
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets) = 0;
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets) = 0;
 
   /**
    * Replace the set of agent style sheets
    */
   virtual nsresult SetAgentStyleSheets(
-      const nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets) = 0;
+      const nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets) = 0;
 
   /**
    * Add an override style sheet for this presentation
    */
-  virtual nsresult AddOverrideStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
+  virtual nsresult AddOverrideStyleSheet(mozilla::StyleSheetHandle aSheet) = 0;
 
   /**
    * Remove an override style sheet
    */
-  virtual nsresult RemoveOverrideStyleSheet(mozilla::CSSStyleSheet* aSheet) = 0;
+  virtual nsresult RemoveOverrideStyleSheet(mozilla::StyleSheetHandle aSheet) = 0;
 
   /**
    * Reconstruct frames for all elements in the document
    */
   virtual nsresult ReconstructFrames() = 0;
 
   /**
    * Notify that a content node's state has changed
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -68,16 +68,18 @@
 #include "nsFrameLoader.h"
 #include "mozilla/dom/FontFaceSet.h"
 #include "nsContentUtils.h"
 #include "nsPIWindowRoot.h"
 #include "mozilla/Preferences.h"
 #include "gfxTextRun.h"
 #include "nsFontFaceUtils.h"
 #include "nsLayoutStylesheetCache.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #if defined(MOZ_WIDGET_GTK)
 #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
 #endif
 
 
 // Needed for Start/Stop of Image Animation
 #include "imgIContainer.h"
@@ -1352,17 +1354,18 @@ nsPresContext::CompatibilityModeChanged(
   }
 
   bool needsQuirkSheet = CompatibilityMode() == eCompatibility_NavQuirks;
   if (mQuirkSheetAdded == needsQuirkSheet) {
     return;
   }
 
   StyleSetHandle styleSet = mShell->StyleSet();
-  CSSStyleSheet* sheet = nsLayoutStylesheetCache::QuirkSheet();
+  auto cache = nsLayoutStylesheetCache::For(styleSet->BackendType());
+  StyleSheetHandle sheet = cache->QuirkSheet();
 
   if (needsQuirkSheet) {
     // quirk.css needs to come after html.css; we just keep it at the end.
     DebugOnly<nsresult> rv =
       styleSet->AppendStyleSheet(SheetType::Agent, sheet);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to insert quirk.css");
   } else {
     DebugOnly<nsresult> rv =
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -181,16 +181,18 @@
 #include "nsIFrameInlines.h"
 #include "mozilla/gfx/2D.h"
 #include "nsSubDocumentFrame.h"
 #include "nsQueryObject.h"
 #include "nsLayoutStylesheetCache.h"
 #include "mozilla/layers/ScrollInputMethods.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #ifdef ANDROID
 #include "nsIDocShellTreeOwner.h"
 #endif
 
 #ifdef MOZ_TASK_TRACER
 #include "GeckoTaskTracer.h"
 using namespace mozilla::tasktracer;
@@ -1359,20 +1361,21 @@ PresShell::UpdatePreferenceStyles()
   // We need to pass in mPresContext so that if the nsLayoutStylesheetCache
   // needs to recreate the pref style sheet, it has somewhere to get the
   // pref styling information from.  All pres contexts for
   // IsChromeOriginImage() == false will have the same pref styling information,
   // and similarly for IsChromeOriginImage() == true, so it doesn't really
   // matter which pres context we pass in when it does need to be recreated.
   // (See nsPresContext::GetDocumentColorPreferences for how whether we
   // are a chrome origin image affects some pref styling information.)
-  RefPtr<CSSStyleSheet> newPrefSheet =
+  auto cache = nsLayoutStylesheetCache::For(mStyleSet->BackendType());
+  StyleSheetHandle::RefPtr newPrefSheet =
     mPresContext->IsChromeOriginImage() ?
-      nsLayoutStylesheetCache::ChromePreferenceSheet(mPresContext) :
-      nsLayoutStylesheetCache::ContentPreferenceSheet(mPresContext);
+      cache->ChromePreferenceSheet(mPresContext) :
+      cache->ContentPreferenceSheet(mPresContext);
 
   if (mPrefStyleSheet == newPrefSheet) {
     return;
   }
 
   mStyleSet->BeginUpdate();
 
   RemovePreferenceStyles();
@@ -1401,73 +1404,78 @@ PresShell::AddUserSheet(nsISupports* aSh
   // for the ordering.  Just remove and readd all the nsStyleSheetService
   // sheets.
   nsCOMPtr<nsIStyleSheetService> dummy =
     do_GetService(NS_STYLESHEETSERVICE_CONTRACTID);
 
   mStyleSet->BeginUpdate();
 
   nsStyleSheetService* sheetService = nsStyleSheetService::gInstance;
-  nsTArray<RefPtr<CSSStyleSheet>>& userSheets = *sheetService->UserStyleSheets();
+  nsTArray<StyleSheetHandle::RefPtr>& userSheets = *sheetService->UserStyleSheets();
   // Iterate forwards when removing so the searches for RemoveStyleSheet are as
   // short as possible.
-  for (CSSStyleSheet* sheet : userSheets) {
+  for (StyleSheetHandle sheet : userSheets) {
     mStyleSet->RemoveStyleSheet(SheetType::User, sheet);
   }
 
   // Now iterate backwards, so that the order of userSheets will be the same as
   // the order of sheets from it in the style set.
-  for (CSSStyleSheet* sheet : Reversed(userSheets)) {
+  for (StyleSheetHandle sheet : Reversed(userSheets)) {
     mStyleSet->PrependStyleSheet(SheetType::User, sheet);
   }
 
   mStyleSet->EndUpdate();
 
   ReconstructStyleData();
 }
 
 void
 PresShell::AddAgentSheet(nsISupports* aSheet)
 {
   // Make sure this does what nsDocumentViewer::CreateStyleSet does
   // wrt ordering.
+  // XXXheycam This needs to work with ServoStyleSheets too.
   RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
   if (!sheet) {
+    NS_ERROR("stylo: AddAgentSheet needs to support ServoStyleSheets");
     return;
   }
 
   mStyleSet->AppendStyleSheet(SheetType::Agent, sheet);
   ReconstructStyleData();
 }
 
 void
 PresShell::AddAuthorSheet(nsISupports* aSheet)
 {
+  // XXXheycam This needs to work with ServoStyleSheets too.
   RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
   if (!sheet) {
+    NS_ERROR("stylo: AddAuthorSheet needs to support ServoStyleSheets");
     return;
   }
 
   // Document specific "additional" Author sheets should be stronger than the ones
   // added with the StyleSheetService.
-  CSSStyleSheet* firstAuthorSheet = mDocument->FirstAdditionalAuthorSheet();
+  StyleSheetHandle firstAuthorSheet = mDocument->FirstAdditionalAuthorSheet();
   if (firstAuthorSheet) {
     mStyleSet->InsertStyleSheetBefore(SheetType::Doc, sheet, firstAuthorSheet);
   } else {
     mStyleSet->AppendStyleSheet(SheetType::Doc, sheet);
   }
 
   ReconstructStyleData();
 }
 
 void
 PresShell::RemoveSheet(SheetType aType, nsISupports* aSheet)
 {
   RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
   if (!sheet) {
+    NS_ERROR("stylo: RemoveSheet needs to support ServoStyleSheets");
     return;
   }
 
   mStyleSet->RemoveStyleSheet(aType, sheet);
   ReconstructStyleData();
 }
 
 NS_IMETHODIMP
@@ -4419,82 +4427,84 @@ nsIPresShell::ReconstructStyleDataIntern
 
 void
 nsIPresShell::ReconstructStyleDataExternal()
 {
   ReconstructStyleDataInternal();
 }
 
 void
-PresShell::RecordStyleSheetChange(CSSStyleSheet* aStyleSheet)
+PresShell::RecordStyleSheetChange(StyleSheetHandle aStyleSheet)
 {
   // too bad we can't check that the update is UPDATE_STYLE
   NS_ASSERTION(mUpdateCount != 0, "must be in an update");
 
   if (mStylesHaveChanged)
     return;
 
-  RefPtr<CSSStyleSheet> cssStyleSheet = do_QueryObject(aStyleSheet);
-  if (cssStyleSheet) {
-    Element* scopeElement = cssStyleSheet->GetScopeElement();
+  if (aStyleSheet->IsGecko()) {
+    // XXXheycam ServoStyleSheets don't support <style scoped> yet.
+    Element* scopeElement = aStyleSheet->AsGecko()->GetScopeElement();
     if (scopeElement) {
       mChangedScopeStyleRoots.AppendElement(scopeElement);
       return;
     }
+  } else {
+    NS_ERROR("stylo: ServoStyleSheets don't support <style scoped>");
   }
 
   mStylesHaveChanged = true;
 }
 
 void
-PresShell::StyleSheetAdded(CSSStyleSheet* aStyleSheet,
+PresShell::StyleSheetAdded(StyleSheetHandle aStyleSheet,
                            bool aDocumentSheet)
 {
   // We only care when enabled sheets are added
   NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
 
   if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
     RecordStyleSheetChange(aStyleSheet);
   }
 }
 
 void
-PresShell::StyleSheetRemoved(CSSStyleSheet* aStyleSheet,
+PresShell::StyleSheetRemoved(StyleSheetHandle aStyleSheet,
                              bool aDocumentSheet)
 {
   // We only care when enabled sheets are removed
   NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
 
   if (aStyleSheet->IsApplicable() && aStyleSheet->HasRules()) {
     RecordStyleSheetChange(aStyleSheet);
   }
 }
 
 void
-PresShell::StyleSheetApplicableStateChanged(CSSStyleSheet* aStyleSheet)
+PresShell::StyleSheetApplicableStateChanged(StyleSheetHandle aStyleSheet)
 {
   if (aStyleSheet->HasRules()) {
     RecordStyleSheetChange(aStyleSheet);
   }
 }
 
 void
-PresShell::StyleRuleChanged(CSSStyleSheet* aStyleSheet)
+PresShell::StyleRuleChanged(StyleSheetHandle aStyleSheet)
 {
   RecordStyleSheetChange(aStyleSheet);
 }
 
 void
-PresShell::StyleRuleAdded(CSSStyleSheet* aStyleSheet)
+PresShell::StyleRuleAdded(StyleSheetHandle aStyleSheet)
 {
   RecordStyleSheetChange(aStyleSheet);
 }
 
 void
-PresShell::StyleRuleRemoved(CSSStyleSheet* aStyleSheet)
+PresShell::StyleRuleRemoved(StyleSheetHandle aStyleSheet)
 {
   RecordStyleSheetChange(aStyleSheet);
 }
 
 nsIFrame*
 PresShell::GetRealPrimaryFrameFor(nsIContent* aContent) const
 {
   if (aContent->GetComposedDoc() != GetDocument()) {
@@ -8496,47 +8506,47 @@ PresShell::IsVisible()
   nsIFrame* frame = view->GetFrame();
   if (!frame)
     return true;
 
   return frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY);
 }
 
 nsresult
-PresShell::GetAgentStyleSheets(nsTArray<RefPtr<CSSStyleSheet>>& aSheets)
+PresShell::GetAgentStyleSheets(nsTArray<StyleSheetHandle::RefPtr>& aSheets)
 {
   aSheets.Clear();
   int32_t sheetCount = mStyleSet->SheetCount(SheetType::Agent);
 
   if (!aSheets.SetCapacity(sheetCount, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (int32_t i = 0; i < sheetCount; ++i) {
-    CSSStyleSheet* sheet = mStyleSet->StyleSheetAt(SheetType::Agent, i);
+    StyleSheetHandle sheet = mStyleSet->StyleSheetAt(SheetType::Agent, i);
     aSheets.AppendElement(sheet);
   }
 
   return NS_OK;
 }
 
 nsresult
-PresShell::SetAgentStyleSheets(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets)
+PresShell::SetAgentStyleSheets(const nsTArray<StyleSheetHandle::RefPtr>& aSheets)
 {
   return mStyleSet->ReplaceSheets(SheetType::Agent, aSheets);
 }
 
 nsresult
-PresShell::AddOverrideStyleSheet(CSSStyleSheet* aSheet)
+PresShell::AddOverrideStyleSheet(StyleSheetHandle aSheet)
 {
   return mStyleSet->PrependStyleSheet(SheetType::Override, aSheet);
 }
 
 nsresult
-PresShell::RemoveOverrideStyleSheet(CSSStyleSheet* aSheet)
+PresShell::RemoveOverrideStyleSheet(StyleSheetHandle aSheet)
 {
   return mStyleSet->RemoveStyleSheet(SheetType::Override, aSheet);
 }
 
 static void
 FreezeElement(nsISupports *aSupports, void * /* unused */)
 {
   nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aSupports));
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -46,17 +46,16 @@ struct nsCallbackEventRequest;
 #ifdef MOZ_REFLOW_PERF
 class ReflowCountMgr;
 #endif
 
 class nsPresShellEventCB;
 class nsAutoCauseReflowNotifier;
 
 namespace mozilla {
-class CSSStyleSheet;
 class EventDispatchingCallback;
 } // namespace mozilla
 
 // 250ms.  This is actually pref-controlled, but we use this value if we fail
 // to get the pref for any reason.
 #define PAINTLOCK_EVENT_DELAY 250
 
 class PresShell final : public nsIPresShell,
@@ -150,22 +149,22 @@ public:
   virtual void SetIgnoreFrameDestruction(bool aIgnore) override;
   virtual void NotifyDestroyingFrame(nsIFrame* aFrame) override;
 
   virtual nsresult CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState) override;
 
   virtual void UnsuppressPainting() override;
 
   virtual nsresult GetAgentStyleSheets(
-      nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets) override;
+      nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets) override;
   virtual nsresult SetAgentStyleSheets(
-      const nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets) override;
+      const nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets) override;
 
-  virtual nsresult AddOverrideStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
-  virtual nsresult RemoveOverrideStyleSheet(mozilla::CSSStyleSheet* aSheet) override;
+  virtual nsresult AddOverrideStyleSheet(mozilla::StyleSheetHandle aSheet) override;
+  virtual nsresult RemoveOverrideStyleSheet(mozilla::StyleSheetHandle aSheet) override;
 
   virtual nsresult HandleEventWithTarget(
                                  mozilla::WidgetEvent* aEvent,
                                  nsIFrame* aFrame,
                                  nsIContent* aContent,
                                  nsEventStatus* aStatus) override;
   virtual nsIFrame* GetEventTargetFrame() override;
   virtual already_AddRefed<nsIContent> GetEventTargetContent(
@@ -498,17 +497,17 @@ protected:
   bool mIsHidden;
 #ifdef DEBUG
   nsStyleSet* CloneStyleSet(nsStyleSet* aSet);
   bool VerifyIncrementalReflow();
   bool mInVerifyReflow;
   void ShowEventTargetDebug();
 #endif
 
-  void RecordStyleSheetChange(mozilla::CSSStyleSheet* aStyleSheet);
+  void RecordStyleSheetChange(mozilla::StyleSheetHandle aStyleSheet);
 
   void RemovePreferenceStyles();
 
   // methods for painting a range to an offscreen buffer
 
   // given a display list, clip the items within the list to
   // the range
   nsRect ClipListToRange(nsDisplayListBuilder *aBuilder,
@@ -776,17 +775,17 @@ protected:
   // It is set only on a presshell for a root document, this value represents
   // the last observed location of the mouse relative to that root document. It
   // is set to (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if the mouse isn't
   // over our window or there is no last observed mouse location for some
   // reason.
   nsPoint                   mMouseLocation;
 
   // mStyleSet owns it but we maintain a ref, may be null
-  RefPtr<mozilla::CSSStyleSheet> mPrefStyleSheet;
+  mozilla::StyleSheetHandle::RefPtr mPrefStyleSheet;
 
   // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
   // we finish reflowing mCurrentReflowRoot.
   nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesToDirty;
 
   // Reflow roots that need to be reflowed.
   nsTArray<nsIFrame*>       mDirtyRoots;
 
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -4,16 +4,18 @@
  * 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/. */
 
 /* implementation of interface for managing user and user-agent style sheets */
 
 #include "nsStyleSheetService.h"
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 #include "mozilla/unused.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
@@ -73,17 +75,17 @@ nsStyleSheetService::RegisterFromEnumera
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), spec);
     if (uri)
       LoadAndRegisterSheetInternal(uri, aSheetType);
   }
 }
 
 int32_t
-nsStyleSheetService::FindSheetByURI(const nsTArray<RefPtr<CSSStyleSheet>>& aSheets,
+nsStyleSheetService::FindSheetByURI(const nsTArray<StyleSheetHandle::RefPtr>& aSheets,
                                     nsIURI* aSheetURI)
 {
   for (int32_t i = aSheets.Length() - 1; i >= 0; i-- ) {
     bool bEqual;
     nsIURI* uri = aSheets[i]->GetSheetURI();
     if (uri
         && NS_SUCCEEDED(uri->Equals(aSheetURI, &bEqual))
         && bEqual) {
@@ -147,19 +149,27 @@ nsStyleSheetService::LoadAndRegisterShee
         break;
       default:
         return NS_ERROR_INVALID_ARG;
     }
     nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
     if (serv) {
       // We're guaranteed that the new sheet is the last sheet in
       // mSheets[aSheetType]
-      CSSStyleSheet* sheet = mSheets[aSheetType].LastElement();
-      serv->NotifyObservers(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheet),
-                            message, nullptr);
+
+      // XXXheycam Once the nsStyleSheetService can hold ServoStyleSheets too,
+      // we'll need to include them in the notification.
+      StyleSheetHandle sheet = mSheets[aSheetType].LastElement();
+      if (sheet->IsGecko()) {
+        CSSStyleSheet* cssSheet = sheet->AsGecko();
+        serv->NotifyObservers(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, cssSheet),
+                              message, nullptr);
+      } else {
+        NS_ERROR("stylo: can't notify observers of ServoStyleSheets");
+      }
     }
 
     if (XRE_IsParentProcess()) {
       nsTArray<dom::ContentParent*> children;
       dom::ContentParent::GetAll(children);
 
       if (children.IsEmpty()) {
         return rv;
@@ -198,19 +208,18 @@ nsStyleSheetService::LoadAndRegisterShee
 
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
   RefPtr<css::Loader> loader = new css::Loader();
 
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
-                                      getter_AddRefs(sheet));
+  StyleSheetHandle::RefPtr sheet;
+  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mSheets[aSheetType].AppendElement(sheet);
 
   return rv;
 }
 
 NS_IMETHODIMP
@@ -248,37 +257,45 @@ nsStyleSheetService::PreloadSheet(nsIURI
       parsingMode = css::eAuthorSheetFeatures;
       break;
 
     default:
       NS_WARNING("invalid sheet type argument");
       return NS_ERROR_INVALID_ARG;
   }
 
+  // XXXheycam PreloadSheet can't support ServoStyleSheets until they implement
+  // nsIDOMStyleSheet.
+
   RefPtr<css::Loader> loader = new css::Loader();
 
-  RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
-                                      getter_AddRefs(sheet));
+  StyleSheetHandle::RefPtr sheet;
+  nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
-  sheet.forget(aSheet);
+
+  MOZ_ASSERT(sheet->IsGecko(),
+             "stylo: didn't expect Loader to create a ServoStyleSheet");
+
+  RefPtr<CSSStyleSheet> cssSheet = sheet->AsGecko();
+  cssSheet.forget(aSheet);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStyleSheetService::UnregisterSheet(nsIURI *aSheetURI, uint32_t aSheetType)
 {
   NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
                 aSheetType == USER_SHEET ||
                 aSheetType == AUTHOR_SHEET);
   NS_ENSURE_ARG_POINTER(aSheetURI);
 
   int32_t foundIndex = FindSheetByURI(mSheets[aSheetType], aSheetURI);
   NS_ENSURE_TRUE(foundIndex >= 0, NS_ERROR_INVALID_ARG);
-  RefPtr<CSSStyleSheet> sheet = mSheets[aSheetType][foundIndex];
+  StyleSheetHandle::RefPtr sheet = mSheets[aSheetType][foundIndex];
   mSheets[aSheetType].RemoveElementAt(foundIndex);
 
   const char* message;
   switch (aSheetType) {
     case AGENT_SHEET:
       message = "agent-sheet-removed";
       break;
     case USER_SHEET:
@@ -286,18 +303,25 @@ nsStyleSheetService::UnregisterSheet(nsI
       break;
     case AUTHOR_SHEET:
       message = "author-sheet-removed";
       break;
   }
 
   nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
   if (serv) {
-    serv->NotifyObservers(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheet),
-                          message, nullptr);
+    // XXXheycam Once the nsStyleSheetService can hold ServoStyleSheets too,
+    // we'll need to include them in the notification.
+    if (sheet->IsGecko()) {
+      CSSStyleSheet* cssSheet = sheet->AsGecko();
+      serv->NotifyObservers(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, cssSheet),
+                            message, nullptr);
+    } else {
+      NS_ERROR("stylo: can't notify observers of ServoStyleSheets");
+    }
   }
 
   if (XRE_IsParentProcess()) {
     nsTArray<dom::ContentParent*> children;
     dom::ContentParent::GetAll(children);
 
     if (children.IsEmpty()) {
       return NS_OK;
@@ -342,14 +366,14 @@ nsStyleSheetService::CollectReports(nsIH
 }
 
 size_t
 nsStyleSheetService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
   for (auto& sheetArray : mSheets) {
     n += sheetArray.ShallowSizeOfExcludingThis(aMallocSizeOf);
-    for (CSSStyleSheet* sheet : sheetArray) {
+    for (StyleSheetHandle sheet : sheetArray) {
       n += sheet->SizeOfIncludingThis(aMallocSizeOf);
     }
   }
   return n;
 }
--- a/layout/base/nsStyleSheetService.h
+++ b/layout/base/nsStyleSheetService.h
@@ -10,20 +10,18 @@
 #define nsStyleSheetService_h_
 
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsIMemoryReporter.h"
 #include "nsIStyleSheetService.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/StyleSheetHandle.h"
 
-namespace mozilla {
-class CSSStyleSheet;
-}
 class nsICategoryManager;
 class nsIMemoryReporter;
 class nsISimpleEnumerator;
 
 #define NS_STYLESHEETSERVICE_CID \
 { 0x3b55e72e, 0xab7e, 0x431b, \
   { 0x89, 0xc0, 0x3b, 0x06, 0xa8, 0xb1, 0x40, 0x16 } }
 
@@ -38,25 +36,25 @@ class nsStyleSheetService final
   nsStyleSheetService();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTYLESHEETSERVICE
   NS_DECL_NSIMEMORYREPORTER
 
   nsresult Init();
 
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>>* AgentStyleSheets()
+  nsTArray<mozilla::StyleSheetHandle::RefPtr>* AgentStyleSheets()
   {
     return &mSheets[AGENT_SHEET];
   }
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>>* UserStyleSheets()
+  nsTArray<mozilla::StyleSheetHandle::RefPtr>* UserStyleSheets()
   {
     return &mSheets[USER_SHEET];
   }
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>>* AuthorStyleSheets()
+  nsTArray<mozilla::StyleSheetHandle::RefPtr>* AuthorStyleSheets()
   {
     return &mSheets[AUTHOR_SHEET];
   }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   static nsStyleSheetService *GetInstance();
   static nsStyleSheetService *gInstance;
@@ -64,20 +62,20 @@ class nsStyleSheetService final
  private:
   ~nsStyleSheetService();
 
   void RegisterFromEnumerator(nsICategoryManager  *aManager,
                                           const char          *aCategory,
                                           nsISimpleEnumerator *aEnumerator,
                                           uint32_t             aSheetType);
 
-  int32_t FindSheetByURI(const nsTArray<RefPtr<mozilla::CSSStyleSheet>>& aSheets,
+  int32_t FindSheetByURI(const nsTArray<mozilla::StyleSheetHandle::RefPtr>& aSheets,
                          nsIURI* aSheetURI);
 
   // Like LoadAndRegisterSheet, but doesn't notify.  If successful, the
   // new sheet will be the last sheet in mSheets[aSheetType].
   nsresult LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
                                         uint32_t aSheetType);
 
-  nsTArray<RefPtr<mozilla::CSSStyleSheet>> mSheets[3];
+  nsTArray<mozilla::StyleSheetHandle::RefPtr> mSheets[3];
 };
 
 #endif
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -109,17 +109,19 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocu
         sheetSet.PutEntry(sheet);
         sheets.AppendElement(sheet);
       }
     }
   }
 
   // Get the document sheets.
   for (int32_t i = 0; i < document->GetNumberOfStyleSheets(); i++) {
-    sheets.AppendElement(document->GetStyleSheetAt(i));
+    // XXXheycam ServoStyleSets don't have the ability to expose their
+    // sheets in a script-accessible way yet.
+    sheets.AppendElement(document->GetStyleSheetAt(i)->AsGecko());
   }
 
   nsISupports** ret = static_cast<nsISupports**>(moz_xmalloc(sheets.Length() *
                                                  sizeof(nsISupports*)));
 
   for (size_t i = 0; i < sheets.Length(); i++) {
     NS_ADDREF(ret[i] = NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheets[i]));
   }
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -2198,32 +2198,37 @@ CSSStyleSheet::InsertRuleIntoGroup(const
   }
 
   *_retval = aIndex;
   return NS_OK;
 }
 
 // nsICSSLoaderObserver implementation
 NS_IMETHODIMP
-CSSStyleSheet::StyleSheetLoaded(CSSStyleSheet* aSheet,
+CSSStyleSheet::StyleSheetLoaded(StyleSheetHandle aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus)
 {
-  if (aSheet->GetParentSheet() == nullptr) {
+  MOZ_ASSERT(aSheet->IsGecko(),
+             "why we were called back with a ServoStyleSheet?");
+
+  CSSStyleSheet* sheet = aSheet->AsGecko();
+
+  if (sheet->GetParentSheet() == nullptr) {
     return NS_OK; // ignore if sheet has been detached already (see parseSheet)
   }
-  NS_ASSERTION(this == aSheet->GetParentSheet(),
+  NS_ASSERTION(this == sheet->GetParentSheet(),
                "We are being notified of a sheet load for a sheet that is not our child!");
 
   if (mDocument && NS_SUCCEEDED(aStatus)) {
     mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
 
     // XXXldb @import rules shouldn't even implement nsIStyleRule (but
     // they do)!
-    mDocument->StyleRuleAdded(this, aSheet->GetOwnerRule());
+    mDocument->StyleRuleAdded(this, sheet->GetOwnerRule());
   }
 
   return NS_OK;
 }
 
 nsresult
 CSSStyleSheet::ReparseSheet(const nsAString& aInput)
 {
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -243,17 +243,17 @@ public:
   nsresult InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, uint32_t* aReturn);
 
   /* Get the URI this sheet was originally loaded from, if any.  Can
      return null */
   nsIURI* GetOriginalURI() const { return mInner->mOriginalSheetURI; }
 
   // nsICSSLoaderObserver interface
-  NS_IMETHOD StyleSheetLoaded(CSSStyleSheet* aSheet, bool aWasAlternate,
+  NS_IMETHOD StyleSheetLoaded(StyleSheetHandle aSheet, bool aWasAlternate,
                               nsresult aStatus) override;
 
   void EnsureUniqueInner();
 
   // Append all of this sheet's child sheets to aArray.
   void AppendAllChildSheets(nsTArray<CSSStyleSheet*>& aArray);
 
   bool UseForPresentation(nsPresContext* aPresContext,
@@ -277,17 +277,17 @@ public:
 
   // Get this style sheet's CORS mode
   CORSMode GetCORSMode() const { return mInner->mCORSMode; }
 
   // Get this style sheet's Referrer Policy
   ReferrerPolicy GetReferrerPolicy() const { return mInner->mReferrerPolicy; }
 
   // Get this style sheet's integrity metadata
-  dom::SRIMetadata GetIntegrity() const { return mInner->mIntegrity; }
+  void GetIntegrity(dom::SRIMetadata& aResult) const { aResult = mInner->mIntegrity; }
 
   dom::Element* GetScopeElement() const { return mScopeElement; }
   void SetScopeElement(dom::Element* aScopeElement)
   {
     mScopeElement = aScopeElement;
   }
 
   // WebIDL StyleSheet API
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1689,17 +1689,17 @@ FontFaceSet::PrefEnabled()
     Preferences::AddBoolVarCache(&enabled, FONT_LOADING_API_ENABLED_PREF);
   }
   return enabled;
 }
 
 // nsICSSLoaderObserver
 
 NS_IMETHODIMP
-FontFaceSet::StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+FontFaceSet::StyleSheetLoaded(StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus)
 {
   CheckLoadingFinished();
   return NS_OK;
 }
 
 void
--- a/layout/style/FontFaceSet.h
+++ b/layout/style/FontFaceSet.h
@@ -139,17 +139,17 @@ public:
   void DidRefresh();
 
   /**
    * Returns whether the "layout.css.font-loading-api.enabled" pref is true.
    */
   static bool PrefEnabled();
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) override;
 
   FontFace* GetFontFaceAt(uint32_t aIndex);
 
   void FlushUserFontSet();
 
   static nsPresContext* GetPresContextFor(gfxUserFontSet* aUserFontSet)
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -46,16 +46,18 @@
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/ImportRule.h"
 #include "nsThreadUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIThreadInternal.h"
 #include "nsINetworkPredictor.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/URL.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 
 #include "nsIMediaList.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsError.h"
@@ -114,36 +116,36 @@ class SheetLoadData final : public nsIRu
 protected:
   virtual ~SheetLoadData(void);
 
 public:
   // Data for loading a sheet linked from a document
   SheetLoadData(Loader* aLoader,
                 const nsSubstring& aTitle,
                 nsIURI* aURI,
-                CSSStyleSheet* aSheet,
+                StyleSheetHandle aSheet,
                 nsIStyleSheetLinkingElement* aOwningElement,
                 bool aIsAlternate,
                 nsICSSLoaderObserver* aObserver,
                 nsIPrincipal* aLoaderPrincipal,
                 nsINode* aRequestingNode);
 
   // Data for loading a sheet linked from an @import rule
   SheetLoadData(Loader* aLoader,
                 nsIURI* aURI,
-                CSSStyleSheet* aSheet,
+                StyleSheetHandle aSheet,
                 SheetLoadData* aParentData,
                 nsICSSLoaderObserver* aObserver,
                 nsIPrincipal* aLoaderPrincipal,
                 nsINode* aRequestingNode);
 
   // Data for loading a non-document sheet
   SheetLoadData(Loader* aLoader,
                 nsIURI* aURI,
-                CSSStyleSheet* aSheet,
+                StyleSheetHandle aSheet,
                 bool aSyncLoad,
                 SheetParsingMode aParsingMode,
                 bool aUseSystemPrincipal,
                 const nsCString& aCharset,
                 nsICSSLoaderObserver* aObserver,
                 nsIPrincipal* aLoaderPrincipal,
                 nsINode* aRequestingNode);
 
@@ -169,17 +171,17 @@ public:
 
   // URI we're loading.  Null for inline sheets
   nsCOMPtr<nsIURI>           mURI;
 
   // Should be 1 for non-inline sheets.
   uint32_t                   mLineNumber;
 
   // The sheet we're loading data for
-  RefPtr<CSSStyleSheet>    mSheet;
+  StyleSheetHandle::RefPtr mSheet;
 
   // Linked list of datas for the same URI as us
   SheetLoadData*             mNext;  // strong ref
 
   // Load data for the sheet that @import-ed us if we were @import-ed
   // during the parse
   RefPtr<SheetLoadData>    mParentData;
 
@@ -300,17 +302,17 @@ static const char* const gStateStrings[]
  * SheetLoadData implementation *
  ********************************/
 NS_IMPL_ISUPPORTS(SheetLoadData, nsIUnicharStreamLoaderObserver, nsIRunnable,
                   nsIThreadObserver)
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              const nsSubstring& aTitle,
                              nsIURI* aURI,
-                             CSSStyleSheet* aSheet,
+                             StyleSheetHandle aSheet,
                              nsIStyleSheetLinkingElement* aOwningElement,
                              bool aIsAlternate,
                              nsICSSLoaderObserver* aObserver,
                              nsIPrincipal* aLoaderPrincipal,
                              nsINode* aRequestingNode)
   : mLoader(aLoader),
     mTitle(aTitle),
     mURI(aURI),
@@ -332,17 +334,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mLoaderPrincipal(aLoaderPrincipal),
     mRequestingNode(aRequestingNode)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
 }
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              nsIURI* aURI,
-                             CSSStyleSheet* aSheet,
+                             StyleSheetHandle aSheet,
                              SheetLoadData* aParentData,
                              nsICSSLoaderObserver* aObserver,
                              nsIPrincipal* aLoaderPrincipal,
                              nsINode* aRequestingNode)
   : mLoader(aLoader),
     mURI(aURI),
     mLineNumber(1),
     mSheet(aSheet),
@@ -373,17 +375,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
   }
 
   NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
                    "Shouldn't use system principal for async loads");
 }
 
 SheetLoadData::SheetLoadData(Loader* aLoader,
                              nsIURI* aURI,
-                             CSSStyleSheet* aSheet,
+                             StyleSheetHandle aSheet,
                              bool aSyncLoad,
                              SheetParsingMode aParsingMode,
                              bool aUseSystemPrincipal,
                              const nsCString& aCharset,
                              nsICSSLoaderObserver* aObserver,
                              nsIPrincipal* aLoaderPrincipal,
                              nsINode* aRequestingNode)
   : mLoader(aLoader),
@@ -945,17 +947,18 @@ SheetLoadData::OnStreamComplete(nsIUnich
     if (errorFlag == nsIScriptError::errorFlag) {
       LOG_WARN(("  Ignoring sheet with improper MIME type %s",
                 contentType.get()));
       mLoader->SheetComplete(this, NS_ERROR_NOT_AVAILABLE);
       return NS_OK;
     }
   }
 
-  SRIMetadata sriMetadata = mSheet->GetIntegrity();
+  SRIMetadata sriMetadata;
+  mSheet->GetIntegrity(sriMetadata);
   if (!sriMetadata.IsEmpty() &&
       NS_FAILED(SRICheck::VerifyIntegrity(sriMetadata, aLoader,
                                           mSheet->GetCORSMode(), aBuffer,
                                           mLoader->mDocument))) {
     LOG(("  Load was blocked by SRI"));
     MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
             ("css::Loader::OnStreamComplete, bad metadata"));
     mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
@@ -1063,84 +1066,91 @@ Loader::CreateSheet(nsIURI* aURI,
                     CORSMode aCORSMode,
                     ReferrerPolicy aReferrerPolicy,
                     const nsAString& aIntegrity,
                     bool aSyncLoad,
                     bool aHasAlternateRel,
                     const nsAString& aTitle,
                     StyleSheetState& aSheetState,
                     bool *aIsAlternate,
-                    CSSStyleSheet** aSheet)
+                    StyleSheetHandle::RefPtr* aSheet)
 {
   LOG(("css::Loader::CreateSheet"));
   NS_PRECONDITION(aSheet, "Null out param!");
 
   if (!mSheets) {
     mSheets = new Sheets();
   }
 
   *aSheet = nullptr;
   aSheetState = eSheetStateUnknown;
 
   // Check the alternate state before doing anything else, because it
   // can mess with our hashtables.
   *aIsAlternate = IsAlternate(aTitle, aHasAlternateRel);
 
+  // XXXheycam Cached sheets currently must be CSSStyleSheets.
   if (aURI) {
     aSheetState = eSheetComplete;
-    RefPtr<CSSStyleSheet> sheet;
+    StyleSheetHandle::RefPtr sheet;
 
     // First, the XUL cache
 #ifdef MOZ_XUL
     if (IsChromeURI(aURI)) {
       nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
       if (cache) {
         if (cache->IsEnabled()) {
           sheet = cache->GetStyleSheet(aURI);
-          LOG(("  From XUL cache: %p", sheet.get()));
+          LOG(("  From XUL cache: %p", sheet->AsVoidPtr()));
         }
       }
     }
 #endif
 
     bool fromCompleteSheets = false;
     if (!sheet) {
       // Then our per-document complete sheets.
       URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
 
-      mSheets->mCompleteSheets.Get(&key, getter_AddRefs(sheet));
-      LOG(("  From completed: %p", sheet.get()));
+      StyleSheetHandle completeSheet;
+      mSheets->mCompleteSheets.Get(&key, &completeSheet);
+      sheet = completeSheet;
+      LOG(("  From completed: %p", sheet->AsVoidPtr()));
 
       fromCompleteSheets = !!sheet;
     }
 
     if (sheet) {
+      if (sheet->IsServo()) {
+        MOZ_CRASH("stylo: can't clone ServoStyleSheets yet");
+      }
+
       // This sheet came from the XUL cache or our per-document hashtable; it
       // better be a complete sheet.
-      NS_ASSERTION(sheet->IsComplete(),
+      NS_ASSERTION(sheet->AsGecko()->IsComplete(),
                    "Sheet thinks it's not complete while we think it is");
 
       // Make sure it hasn't been modified; if it has, we can't use it
-      if (sheet->IsModified()) {
+      if (sheet->AsGecko()->IsModified()) {
         LOG(("  Not cloning completed sheet %p because it's been modified",
-             sheet.get()));
+             sheet->AsVoidPtr()));
         sheet = nullptr;
         fromCompleteSheets = false;
       }
     }
 
     // Then loading sheets
     if (!sheet && !aSyncLoad) {
       aSheetState = eSheetLoading;
       SheetLoadData* loadData = nullptr;
       URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
       mSheets->mLoadingDatas.Get(&key, &loadData);
       if (loadData) {
         sheet = loadData->mSheet;
-        LOG(("  From loading: %p", sheet.get()));
+        LOG(("  From loading: %p", sheet->AsVoidPtr()));
 
 #ifdef DEBUG
         bool debugEqual;
         NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
                      (aLoaderPrincipal && loadData->mLoaderPrincipal &&
                       NS_SUCCEEDED(aLoaderPrincipal->
                                    Equals(loadData->mLoaderPrincipal,
                                           &debugEqual)) && debugEqual),
@@ -1150,47 +1160,55 @@ Loader::CreateSheet(nsIURI* aURI,
 
       // Then alternate sheets
       if (!sheet) {
         aSheetState = eSheetPending;
         loadData = nullptr;
         mSheets->mPendingDatas.Get(&key, &loadData);
         if (loadData) {
           sheet = loadData->mSheet;
-          LOG(("  From pending: %p", sheet.get()));
+          LOG(("  From pending: %p", sheet->AsVoidPtr()));
 
 #ifdef DEBUG
           bool debugEqual;
           NS_ASSERTION((!aLoaderPrincipal && !loadData->mLoaderPrincipal) ||
                        (aLoaderPrincipal && loadData->mLoaderPrincipal &&
                         NS_SUCCEEDED(aLoaderPrincipal->
                                      Equals(loadData->mLoaderPrincipal,
                                             &debugEqual)) && debugEqual),
                        "Principals should be the same");
 #endif
         }
       }
     }
 
     if (sheet) {
       // The sheet we have now should be either incomplete or unmodified
-      NS_ASSERTION(!sheet->IsModified() || !sheet->IsComplete(),
+      if (sheet->IsServo()) {
+        MOZ_CRASH("stylo: can't clone ServoStyleSheets yet");
+      }
+      NS_ASSERTION(!sheet->AsGecko()->IsModified() ||
+                   !sheet->AsGecko()->IsComplete(),
                    "Unexpected modified complete sheet");
-      NS_ASSERTION(sheet->IsComplete() || aSheetState != eSheetComplete,
+      NS_ASSERTION(sheet->AsGecko()->IsComplete() ||
+                   aSheetState != eSheetComplete,
                    "Sheet thinks it's not complete while we think it is");
 
-      *aSheet = sheet->Clone(nullptr, nullptr, nullptr, nullptr).take();
+      RefPtr<CSSStyleSheet> clonedSheet =
+        sheet->AsGecko()->Clone(nullptr, nullptr, nullptr, nullptr);
+      *aSheet = Move(clonedSheet);
       if (*aSheet && fromCompleteSheets &&
-          !sheet->GetOwnerNode() && !sheet->GetParentSheet()) {
+          !sheet->AsGecko()->GetOwnerNode() &&
+          !sheet->AsGecko()->GetParentSheet()) {
         // The sheet we're cloning isn't actually referenced by
         // anyone.  Replace it in the cache, so that if our CSSOM is
         // later modified we don't end up with two copies of our inner
         // hanging around.
         URIPrincipalReferrerPolicyAndCORSModeHashKey key(aURI, aLoaderPrincipal, aCORSMode, aReferrerPolicy);
-        NS_ASSERTION((*aSheet)->IsComplete(),
+        NS_ASSERTION((*aSheet)->AsGecko()->IsComplete(),
                      "Should only be caching complete sheets");
         mSheets->mCompleteSheets.Put(&key, *aSheet);
       }
     }
   }
 
   if (!*aSheet) {
     aSheetState = eSheetNeedsParser;
@@ -1213,81 +1231,86 @@ Loader::CreateSheet(nsIURI* aURI,
     SRIMetadata sriMetadata;
     if (!aIntegrity.IsEmpty()) {
       MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
               ("css::Loader::CreateSheet, integrity=%s",
                NS_ConvertUTF16toUTF8(aIntegrity).get()));
       SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata);
     }
 
-    RefPtr<CSSStyleSheet> sheet = new CSSStyleSheet(aCORSMode,
-                                                      aReferrerPolicy,
-                                                      sriMetadata);
-    sheet->SetURIs(sheetURI, originalURI, baseURI);
-    sheet.forget(aSheet);
+    *aSheet = new CSSStyleSheet(aCORSMode, aReferrerPolicy, sriMetadata);
+    (*aSheet)->SetURIs(sheetURI, originalURI, baseURI);
   }
 
   NS_ASSERTION(*aSheet, "We should have a sheet by now!");
   NS_ASSERTION(aSheetState != eSheetStateUnknown, "Have to set a state!");
   LOG(("  State: %s", gStateStrings[aSheetState]));
 
   return NS_OK;
 }
 
 /**
  * PrepareSheet() handles setting the media and title on the sheet, as
  * well as setting the enabled state based on the title and whether
  * the sheet had "alternate" in its rel.
  */
 void
-Loader::PrepareSheet(CSSStyleSheet* aSheet,
+Loader::PrepareSheet(StyleSheetHandle aSheet,
                      const nsSubstring& aTitle,
                      const nsSubstring& aMediaString,
                      nsMediaList* aMediaList,
                      Element* aScopeElement,
                      bool isAlternate)
 {
   NS_PRECONDITION(aSheet, "Must have a sheet!");
 
+  // XXXheycam Need to set media, title, etc. on ServoStyleSheets.
+  if (aSheet->IsServo()) {
+    NS_ERROR("stylo: should set metadata on ServoStyleSheets");
+    return;
+  }
+
+  CSSStyleSheet* sheet = aSheet->AsGecko();
+
   RefPtr<nsMediaList> mediaList(aMediaList);
 
   if (!aMediaString.IsEmpty()) {
     NS_ASSERTION(!aMediaList,
                  "must not provide both aMediaString and aMediaList");
     mediaList = new nsMediaList();
 
     nsCSSParser mediumParser(this);
 
     // We have aMediaString only when linked from link elements, style
     // elements, or PIs, so pass true.
     mediumParser.ParseMediaList(aMediaString, nullptr, 0, mediaList, true);
   }
 
-  aSheet->SetMedia(mediaList);
+  sheet->SetMedia(mediaList);
 
-  aSheet->SetTitle(aTitle);
-  aSheet->SetEnabled(! isAlternate);
-  aSheet->SetScopeElement(aScopeElement);
+  sheet->SetTitle(aTitle);
+  sheet->SetEnabled(!isAlternate);
+  sheet->SetScopeElement(aScopeElement);
 }
 
 /**
  * InsertSheetInDoc handles ordering of sheets in the document.  Here
  * we have two types of sheets -- those with linking elements and
  * those without.  The latter are loaded by Link: headers.
  * The following constraints are observed:
  * 1) Any sheet with a linking element comes after all sheets without
  *    linking elements
  * 2) Sheets without linking elements are inserted in the order in
  *    which the inserting requests come in, since all of these are
  *    inserted during header data processing in the content sink
  * 3) Sheets with linking elements are ordered based on document order
  *    as determined by CompareDocumentPosition.
  */
 nsresult
-Loader::InsertSheetInDoc(CSSStyleSheet* aSheet,
+Loader::InsertSheetInDoc(StyleSheetHandle aSheet,
                          nsIContent* aLinkingContent,
                          nsIDocument* aDocument)
 {
   LOG(("css::Loader::InsertSheetInDoc"));
   NS_PRECONDITION(aSheet, "Nothing to insert");
   NS_PRECONDITION(aDocument, "Must have a document to insert into");
 
   // XXX Need to cancel pending sheet loads for this element, if any
@@ -1299,38 +1322,36 @@ Loader::InsertSheetInDoc(CSSStyleSheet* 
    * case we'll just want to append anyway.  We want to break out of
    * the loop when insertionPoint points to just before the index we
    * want to insert at.  In other words, when we leave the loop
    * insertionPoint is the index of the stylesheet that immediately
    * precedes the one we're inserting.
    */
   int32_t insertionPoint;
   for (insertionPoint = sheetCount - 1; insertionPoint >= 0; --insertionPoint) {
-    CSSStyleSheet* curSheet = aDocument->GetStyleSheetAt(insertionPoint);
+    StyleSheetHandle curSheet = aDocument->GetStyleSheetAt(insertionPoint);
     NS_ASSERTION(curSheet, "There must be a sheet here!");
-    nsCOMPtr<nsIDOMNode> sheetOwner;
-    curSheet->GetOwnerNode(getter_AddRefs(sheetOwner));
+    nsCOMPtr<nsINode> sheetOwner = curSheet->GetOwnerNode();
     if (sheetOwner && !aLinkingContent) {
       // Keep moving; all sheets with a sheetOwner come after all
       // sheets without a linkingNode
       continue;
     }
 
     if (!sheetOwner) {
       // Aha!  The current sheet has no sheet owner, so we want to
       // insert after it no matter whether we have a linkingNode
       break;
     }
 
-    nsCOMPtr<nsINode> sheetOwnerNode = do_QueryInterface(sheetOwner);
-    NS_ASSERTION(aLinkingContent != sheetOwnerNode,
+    NS_ASSERTION(aLinkingContent != sheetOwner,
                  "Why do we still have our old sheet?");
 
     // Have to compare
-    if (nsContentUtils::PositionIsBefore(sheetOwnerNode, aLinkingContent)) {
+    if (nsContentUtils::PositionIsBefore(sheetOwner, aLinkingContent)) {
       // The current sheet comes before us, and it better be the first
       // such, because now we break
       break;
     }
   }
 
   ++insertionPoint; // adjust the index to the spot we want to insert in
 
@@ -1358,31 +1379,37 @@ Loader::InsertSheetInDoc(CSSStyleSheet* 
  * practice, we get the call to load the child sheet before the CSSOM
  * has finished inserting the @import rule, so we have no idea where
  * to put it anyway.  So just append for now.  (In the future if we
  * want to insert the sheet at the correct position, we'll need to
  * restore CSSStyleSheet::InsertStyleSheetAt, which was removed in
  * bug 1220506.)
  */
 nsresult
-Loader::InsertChildSheet(CSSStyleSheet* aSheet,
-                         CSSStyleSheet* aParentSheet,
+Loader::InsertChildSheet(StyleSheetHandle aSheet,
+                         StyleSheetHandle aParentSheet,
                          ImportRule* aParentRule)
 {
   LOG(("css::Loader::InsertChildSheet"));
   NS_PRECONDITION(aSheet, "Nothing to insert");
   NS_PRECONDITION(aParentSheet, "Need a parent to insert into");
   NS_PRECONDITION(aParentSheet, "How did we get imported?");
 
+  // XXXheycam The InsertChildSheet API doesn't work with ServoStyleSheets,
+  // since they won't have Gecko ImportRules in them.
+  if (aSheet->IsServo()) {
+    return NS_ERROR_FAILURE;
+  }
+
   // child sheets should always start out enabled, even if they got
   // cloned off of top-level sheets which were disabled
-  aSheet->SetEnabled(true);
+  aSheet->AsGecko()->SetEnabled(true);
 
   aParentSheet->AppendStyleSheet(aSheet);
-  aParentRule->SetSheet(aSheet); // This sets the ownerRule on the sheet
+  aParentRule->SetSheet(aSheet->AsGecko()); // This sets the ownerRule on the sheet
 
   LOG(("  Inserting into parent sheet"));
   //  LOG(("  Inserting into parent sheet at position %d", insertionPoint));
 
   return NS_OK;
 }
 
 /**
@@ -1413,17 +1440,18 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
 
   if (!mDocument && !aLoadData->mIsNonDocumentSheet) {
     // No point starting the load; just release all the data and such.
     LOG_WARN(("  No document and not non-document sheet; pre-dropping load"));
     SheetComplete(aLoadData, NS_BINDING_ABORTED);
     return NS_BINDING_ABORTED;
   }
 
-  SRIMetadata sriMetadata = aLoadData->mSheet->GetIntegrity();
+  SRIMetadata sriMetadata;
+  aLoadData->mSheet->GetIntegrity(sriMetadata);
 
   if (aLoadData->mSyncLoad) {
     LOG(("  Synchronous load"));
     NS_ASSERTION(!aLoadData->mObserver, "Observer for a sync load?");
     NS_ASSERTION(aSheetState == eSheetNeedsParser,
                  "Sync loads can't reuse existing async loads");
 
     // Create a nsIUnicharStreamLoader instance to which we will feed
@@ -1704,17 +1732,20 @@ Loader::ParseSheet(const nsAString& aInp
                    bool& aCompleted)
 {
   LOG(("css::Loader::ParseSheet"));
   NS_PRECONDITION(aLoadData, "Must have load data");
   NS_PRECONDITION(aLoadData->mSheet, "Must have sheet to parse into");
 
   aCompleted = false;
 
-  nsCSSParser parser(this, aLoadData->mSheet);
+  // XXXheycam ServoStyleSheets don't support parsing their contents yet.
+  MOZ_ASSERT(aLoadData->mSheet->IsGecko(),
+             "stylo: can't parse ServoStyleSheets contents yet");
+  nsCSSParser parser(this, aLoadData->mSheet->AsGecko());
 
   // Push our load data on the stack so any kids can pick it up
   mParsingDatas.AppendElement(aLoadData);
   nsIURI* sheetURI = aLoadData->mSheet->GetSheetURI();
   nsIURI* baseURI = aLoadData->mSheet->GetBaseURI();
   nsresult rv = parser.ParseSheet(aInput, sheetURI, baseURI,
                                   aLoadData->mSheet->Principal(),
                                   aLoadData->mLineNumber,
@@ -1825,17 +1856,18 @@ Loader::DoSheetComplete(SheetLoadData* a
 
   // Go through and deal with the whole linked list.
   SheetLoadData* data = aLoadData;
   while (data) {
     if (!data->mSheetAlreadyComplete) {
       // If mSheetAlreadyComplete, then the sheet could well be modified between
       // when we posted the async call to SheetComplete and now, since the sheet
       // was page-accessible during that whole time.
-      MOZ_ASSERT(!data->mSheet->IsModified(),
+      MOZ_ASSERT(!(data->mSheet->IsGecko() &&
+                   data->mSheet->AsGecko()->IsModified()),
                  "should not get marked modified during parsing");
       data->mSheet->SetComplete();
       data->ScheduleLoadEventIfNeeded(aStatus);
     }
     if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
       // Don't notify here so we don't trigger script.  Remember the
       // info we need to notify, then do it later when it's safe.
       aDatasToNotify.AppendElement(data);
@@ -1866,49 +1898,53 @@ Loader::DoSheetComplete(SheetLoadData* a
   // If we ever start doing this for failure aStatus, we'll need to
   // adjust the PostLoadEvent code that thinks anything already
   // complete must have loaded succesfully.
   if (NS_SUCCEEDED(aStatus) && aLoadData->mURI) {
     // Pick our sheet to cache carefully.  Ideally, we want to cache
     // one of the sheets that will be kept alive by a document or
     // parent sheet anyway, so that if someone then accesses it via
     // CSSOM we won't have extra clones of the inner lying around.
-    data = aLoadData;
-    CSSStyleSheet* sheet = aLoadData->mSheet;
-    while (data) {
-      if (data->mSheet->GetParentSheet() || data->mSheet->GetOwnerNode()) {
-        sheet = data->mSheet;
-        break;
+    if (aLoadData->mSheet->IsGecko()) {
+      data = aLoadData;
+      CSSStyleSheet* sheet = aLoadData->mSheet->AsGecko();
+      while (data) {
+        if (data->mSheet->GetParentSheet() || data->mSheet->GetOwnerNode()) {
+          sheet = data->mSheet->AsGecko();
+          break;
+        }
+        data = data->mNext;
       }
-      data = data->mNext;
-    }
 #ifdef MOZ_XUL
-    if (IsChromeURI(aLoadData->mURI)) {
-      nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
-      if (cache && cache->IsEnabled()) {
-        if (!cache->GetStyleSheet(aLoadData->mURI)) {
-          LOG(("  Putting sheet in XUL prototype cache"));
-          NS_ASSERTION(sheet->IsComplete(),
-                       "Should only be caching complete sheets");
-          cache->PutStyleSheet(sheet);
+      if (IsChromeURI(aLoadData->mURI)) {
+        nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
+        if (cache && cache->IsEnabled()) {
+          if (!cache->GetStyleSheet(aLoadData->mURI)) {
+            LOG(("  Putting sheet in XUL prototype cache"));
+            NS_ASSERTION(sheet->IsComplete(),
+                         "Should only be caching complete sheets");
+            cache->PutStyleSheet(sheet);
+          }
         }
       }
-    }
-    else {
+      else {
 #endif
-      URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
-                                         aLoadData->mLoaderPrincipal,
-                                         aLoadData->mSheet->GetCORSMode(),
-                                         aLoadData->mSheet->GetReferrerPolicy());
-      NS_ASSERTION(sheet->IsComplete(),
-                   "Should only be caching complete sheets");
-      mSheets->mCompleteSheets.Put(&key, sheet);
+        URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
+                                           aLoadData->mLoaderPrincipal,
+                                           aLoadData->mSheet->GetCORSMode(),
+                                           aLoadData->mSheet->GetReferrerPolicy());
+        NS_ASSERTION(sheet->IsComplete(),
+                     "Should only be caching complete sheets");
+        mSheets->mCompleteSheets.Put(&key, sheet);
 #ifdef MOZ_XUL
+      }
+#endif
+    } else {
+      NS_ERROR("stylo: not caching ServoStyleSheet");
     }
-#endif
   }
 
   NS_RELEASE(aLoadData);  // this will release parents and siblings and all that
 }
 
 nsresult
 Loader::LoadInlineStyle(nsIContent* aElement,
                         const nsAString& aBuffer,
@@ -1934,22 +1970,22 @@ Loader::LoadInlineStyle(nsIContent* aEle
 
   nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
   NS_ASSERTION(owningElement, "Element is not a style linking element!");
 
   // Since we're not planning to load a URI, no need to hand a principal to the
   // load data or to CreateSheet().  Also, OK to use CORS_NONE for the CORS
   // mode and mDocument's ReferrerPolicy.
   StyleSheetState state;
-  RefPtr<CSSStyleSheet> sheet;
+  StyleSheetHandle::RefPtr sheet;
   nsresult rv = CreateSheet(nullptr, aElement, nullptr, CORS_NONE,
                             mDocument->GetReferrerPolicy(),
                             EmptyString(), // no inline integrity checks
                             false, false, aTitle, state, aIsAlternate,
-                            getter_AddRefs(sheet));
+                            &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(state == eSheetNeedsParser,
                "Inline sheets should not be cached");
 
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   PrepareSheet(sheet, aTitle, aMedia, nullptr, aScopeElement, *aIsAlternate);
 
@@ -2017,35 +2053,34 @@ Loader::LoadStyleLink(nsIContent* aEleme
   if (!context) {
     context = mDocument;
   }
 
   nsresult rv = CheckContentPolicy(principal, aURL, context, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   StyleSheetState state;
-  RefPtr<CSSStyleSheet> sheet;
+  StyleSheetHandle::RefPtr sheet;
   rv = CreateSheet(aURL, aElement, principal, aCORSMode,
                    aReferrerPolicy, aIntegrity, false,
                    aHasAlternateRel, aTitle, state, aIsAlternate,
-                   getter_AddRefs(sheet));
+                   &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   PrepareSheet(sheet, aTitle, aMedia, nullptr, nullptr, *aIsAlternate);
 
   rv = InsertSheetInDoc(sheet, aElement, mDocument);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
 
   if (state == eSheetComplete) {
-    LOG(("  Sheet already complete: 0x%p",
-         static_cast<void*>(sheet.get())));
+    LOG(("  Sheet already complete: 0x%p", sheet->AsVoidPtr()));
     if (aObserver || !mObservers.IsEmpty() || owningElement) {
       rv = PostLoadEvent(aURL, sheet, aObserver, *aIsAlternate,
                          owningElement);
       return rv;
     }
 
     return NS_OK;
   }
@@ -2105,49 +2140,43 @@ HaveAncestorDataWithURI(SheetLoadData *a
 
     aData = aData->mNext;
   }
 
   return false;
 }
 
 nsresult
-Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
+Loader::LoadChildSheet(StyleSheetHandle aParentSheet,
                        nsIURI* aURL,
                        nsMediaList* aMedia,
                        ImportRule* aParentRule,
                        LoaderReusableStyleSheets* aReusableSheets)
 {
   LOG(("css::Loader::LoadChildSheet"));
   NS_PRECONDITION(aURL, "Must have a URI to load");
   NS_PRECONDITION(aParentSheet, "Must have a parent sheet");
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   LOG_URI("  Child uri: '%s'", aURL);
 
-  nsCOMPtr<nsIDOMNode> owningNode;
+  nsCOMPtr<nsINode> owningNode;
 
   // check for an owning document: if none, don't bother walking up the parent
   // sheets
   if (aParentSheet->GetOwningDocument()) {
-    nsCOMPtr<nsIDOMStyleSheet> nextParentSheet(aParentSheet);
-    NS_ENSURE_TRUE(nextParentSheet, NS_ERROR_FAILURE); //Not a stylesheet!?
-
-    nsCOMPtr<nsIDOMStyleSheet> topSheet;
-    //traverse our way to the top-most sheet
-    do {
-      topSheet.swap(nextParentSheet);
-      topSheet->GetParentStyleSheet(getter_AddRefs(nextParentSheet));
-    } while (nextParentSheet);
-
-    topSheet->GetOwnerNode(getter_AddRefs(owningNode));
+    StyleSheetHandle topSheet = aParentSheet;
+    while (StyleSheetHandle parent = topSheet->GetParentSheet()) {
+      topSheet = parent;
+    }
+    owningNode = topSheet->GetOwnerNode();
   }
 
   nsISupports* context = owningNode;
   if (!context) {
     context = mDocument;
   }
 
   nsIPrincipal* principal = aParentSheet->Principal();
@@ -2170,35 +2199,40 @@ Loader::LoadChildSheet(CSSStyleSheet* aP
     }
 
     NS_ASSERTION(parentData->mSheet == aParentSheet,
                  "Unexpected call to LoadChildSheet");
   } else {
     LOG(("  No parent load; must be CSSOM"));
     // No parent load data, so the sheet will need to be notified when
     // we finish, if it can be, if we do the load asynchronously.
-    observer = aParentSheet;
+    // XXXheycam ServoStyleSheet doesn't implement nsICSSLoaderObserver yet.
+    MOZ_ASSERT(aParentSheet->IsGecko(),
+               "stylo: ServoStyleSheets don't support child sheet loading yet");
+    observer = aParentSheet->AsGecko();
   }
 
   // Now that we know it's safe to load this (passes security check and not a
   // loop) do so.
-  RefPtr<CSSStyleSheet> sheet;
+  StyleSheetHandle::RefPtr sheet;
+  RefPtr<CSSStyleSheet> reusableSheet;
   StyleSheetState state;
-  if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
-    aParentRule->SetSheet(sheet);
+  if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, reusableSheet)) {
+    sheet = reusableSheet;
+    aParentRule->SetSheet(reusableSheet);
     state = eSheetComplete;
   } else {
     bool isAlternate;
     const nsSubstring& empty = EmptyString();
     // For now, use CORS_NONE for child sheets
     rv = CreateSheet(aURL, nullptr, principal, CORS_NONE,
                      aParentSheet->GetReferrerPolicy(),
                      EmptyString(), // integrity is only checked on main sheet
                      parentData ? parentData->mSyncLoad : false,
-                     false, empty, state, &isAlternate, getter_AddRefs(sheet));
+                     false, empty, state, &isAlternate, &sheet);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PrepareSheet(sheet, empty, empty, aMedia, nullptr, isAlternate);
   }
 
   rv = InsertChildSheet(sheet, aParentSheet, aParentRule);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2227,31 +2261,31 @@ Loader::LoadChildSheet(CSSStyleSheet* aP
   }
   return rv;
 }
 
 nsresult
 Loader::LoadSheetSync(nsIURI* aURL,
                       SheetParsingMode aParsingMode,
                       bool aUseSystemPrincipal,
-                      CSSStyleSheet** aSheet)
+                      StyleSheetHandle::RefPtr* aSheet)
 {
   LOG(("css::Loader::LoadSheetSync"));
   return InternalLoadNonDocumentSheet(aURL,
                                       false, aParsingMode, aUseSystemPrincipal,
                                       nullptr, EmptyCString(),
                                       aSheet, nullptr);
 }
 
 nsresult
 Loader::LoadSheet(nsIURI* aURL,
                   nsIPrincipal* aOriginPrincipal,
                   const nsCString& aCharset,
                   nsICSSLoaderObserver* aObserver,
-                  CSSStyleSheet** aSheet)
+                  StyleSheetHandle::RefPtr* aSheet)
 {
   LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call"));
   NS_PRECONDITION(aSheet, "aSheet is null");
   return InternalLoadNonDocumentSheet(aURL,
                                       false, eAuthorSheetFeatures, false,
                                       aOriginPrincipal, aCharset,
                                       aSheet, aObserver);
 }
@@ -2276,17 +2310,17 @@ Loader::LoadSheet(nsIURI* aURL,
 
 nsresult
 Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
                                      bool aIsPreload,
                                      SheetParsingMode aParsingMode,
                                      bool aUseSystemPrincipal,
                                      nsIPrincipal* aOriginPrincipal,
                                      const nsCString& aCharset,
-                                     CSSStyleSheet** aSheet,
+                                     StyleSheetHandle::RefPtr* aSheet,
                                      nsICSSLoaderObserver* aObserver,
                                      CORSMode aCORSMode,
                                      ReferrerPolicy aReferrerPolicy,
                                      const nsAString& aIntegrity)
 {
   NS_PRECONDITION(aURL, "Must have a URI to load");
   NS_PRECONDITION(aSheet || aObserver, "Sheet and observer can't both be null");
   NS_PRECONDITION(!aUseSystemPrincipal || !aObserver,
@@ -2304,23 +2338,23 @@ Loader::InternalLoadNonDocumentSheet(nsI
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
   NS_ENSURE_SUCCESS(rv, rv);
 
   StyleSheetState state;
   bool isAlternate;
-  RefPtr<CSSStyleSheet> sheet;
+  StyleSheetHandle::RefPtr sheet;
   bool syncLoad = (aObserver == nullptr);
   const nsSubstring& empty = EmptyString();
 
   rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode,
                    aReferrerPolicy, aIntegrity, syncLoad, false,
-                   empty, state, &isAlternate, getter_AddRefs(sheet));
+                   empty, state, &isAlternate, &sheet);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PrepareSheet(sheet, empty, empty, nullptr, nullptr, isAlternate);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     if (aObserver || !mObservers.IsEmpty()) {
       rv = PostLoadEvent(aURL, sheet, aObserver, false, nullptr);
@@ -2347,17 +2381,17 @@ Loader::InternalLoadNonDocumentSheet(nsI
     data->mMustNotify = true;
   }
 
   return rv;
 }
 
 nsresult
 Loader::PostLoadEvent(nsIURI* aURI,
-                      CSSStyleSheet* aSheet,
+                      StyleSheetHandle aSheet,
                       nsICSSLoaderObserver* aObserver,
                       bool aWasAlternate,
                       nsIStyleSheetLinkingElement* aElement)
 {
   LOG(("css::Loader::PostLoadEvent"));
   NS_PRECONDITION(aSheet, "Must have sheet");
   NS_PRECONDITION(aObserver || !mObservers.IsEmpty() || aElement,
                   "Must have observer or element");
@@ -2530,17 +2564,20 @@ Loader::StartAlternateLoads()
 NS_IMPL_CYCLE_COLLECTION_CLASS(Loader)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Loader)
   if (tmp->mSheets) {
     for (auto iter = tmp->mSheets->mCompleteSheets.Iter();
          !iter.Done();
          iter.Next()) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "Sheet cache nsCSSLoader");
-      cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, iter.UserData()));
+      if (iter.UserData()->IsGecko()) {
+        CSSStyleSheet* sheet = iter.UserData()->AsGecko();
+        cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheet));
+      }
     }
   }
   nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver>>::ForwardIterator
     it(tmp->mObservers);
   while (it.HasMore()) {
     ImplCycleCollectionTraverse(cb, it.GetNext(),
                                 "mozilla::css::Loader.mObservers");
   }
@@ -2564,20 +2601,20 @@ Loader::SizeOfIncludingThis(mozilla::Mal
   if (mSheets) {
     n += mSheets->mCompleteSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (auto iter = mSheets->mCompleteSheets.ConstIter();
          !iter.Done();
          iter.Next()) {
       // If aSheet has a parent, then its parent will report it so we don't
       // have to worry about it here. Likewise, if aSheet has an owning node,
       // then the document that node is in will report it.
-      const RefPtr<CSSStyleSheet>& aSheet = iter.Data();
-      n += (aSheet->GetOwnerNode() || aSheet->GetParentSheet())
+      const StyleSheetHandle sheet = iter.UserData();
+      n += (sheet->GetOwnerNode() || sheet->GetParentSheet())
          ? 0
-         : aSheet->SizeOfIncludingThis(aMallocSizeOf);
+         : sheet->SizeOfIncludingThis(aMallocSizeOf);
     }
   }
   n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mLoadingDatas: transient, and should be small
   // - mPendingDatas: transient, and should be small
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -17,16 +17,17 @@
 #include "nsStringFwd.h"
 #include "nsTArray.h"
 #include "nsTObserverArray.h"
 #include "nsURIHashKey.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsICSSLoaderObserver;
 class nsIContent;
 class nsIDocument;
 class nsMediaList;
 class nsIStyleSheetLinkingElement;
 
@@ -281,17 +282,17 @@ public:
    * @param aParentSheet the parent of this child sheet
    * @param aURL the URL of the child sheet
    * @param aMedia the already-parsed media list for the child sheet
    * @param aRule the @import rule importing this child.  This is used to
    *              properly order the child sheet list of aParentSheet.
    * @param aSavedSheets any saved style sheets which could be reused
    *              for this load
    */
-  nsresult LoadChildSheet(CSSStyleSheet* aParentSheet,
+  nsresult LoadChildSheet(StyleSheetHandle aParentSheet,
                           nsIURI* aURL,
                           nsMediaList* aMedia,
                           ImportRule* aRule,
                           LoaderReusableStyleSheets* aSavedSheets);
 
   /**
    * Synchronously load and return the stylesheet at aURL.  Any child sheets
    * will also be loaded synchronously.  Note that synchronous loads over some
@@ -312,23 +313,23 @@ public:
    *
    * NOTE: A successful return from this method doesn't indicate anything about
    * whether the data could be parsed as CSS and doesn't indicate anything
    * about the status of child sheets of the returned sheet.
    */
   nsresult LoadSheetSync(nsIURI* aURL,
                          SheetParsingMode aParsingMode,
                          bool aUseSystemPrincipal,
-                         CSSStyleSheet** aSheet);
+                         StyleSheetHandle::RefPtr* aSheet);
 
   /**
    * As above, but defaults aParsingMode to eAuthorSheetFeatures and
    * aUseSystemPrincipal to false.
    */
-  nsresult LoadSheetSync(nsIURI* aURL, CSSStyleSheet** aSheet) {
+  nsresult LoadSheetSync(nsIURI* aURL, StyleSheetHandle::RefPtr* aSheet) {
     return LoadSheetSync(aURL, eAuthorSheetFeatures, false, aSheet);
   }
 
   /**
    * Asynchronously load the stylesheet at aURL.  If a successful result is
    * returned, aObserver is guaranteed to be notified asynchronously once the
    * sheet is loaded and marked complete.  This method can be used to load
    * sheets not associated with a document.  This method cannot be used to
@@ -347,17 +348,17 @@ public:
    *                  Must not be null.
    * @param [out] aSheet the sheet to load. Note that the sheet may well
    *              not be loaded by the time this method returns.
    */
   nsresult LoadSheet(nsIURI* aURL,
                      nsIPrincipal* aOriginPrincipal,
                      const nsCString& aCharset,
                      nsICSSLoaderObserver* aObserver,
-                     CSSStyleSheet** aSheet);
+                     StyleSheetHandle::RefPtr* aSheet);
 
   /**
    * Same as above, to be used when the caller doesn't care about the
    * not-yet-loaded sheet.
    */
   nsresult LoadSheet(nsIURI* aURL,
                      bool aIsPreload,
                      nsIPrincipal* aOriginPrincipal,
@@ -456,57 +457,57 @@ private:
                        CORSMode aCORSMode,
                        ReferrerPolicy aReferrerPolicy,
                        const nsAString& aIntegrity,
                        bool aSyncLoad,
                        bool aHasAlternateRel,
                        const nsAString& aTitle,
                        StyleSheetState& aSheetState,
                        bool *aIsAlternate,
-                       CSSStyleSheet** aSheet);
+                       StyleSheetHandle::RefPtr* aSheet);
 
   // Pass in either a media string or the nsMediaList from the
   // CSSParser.  Don't pass both.
   // This method will set the sheet's enabled state based on isAlternate
-  void PrepareSheet(CSSStyleSheet* aSheet,
+  void PrepareSheet(StyleSheetHandle aSheet,
                     const nsAString& aTitle,
                     const nsAString& aMediaString,
                     nsMediaList* aMediaList,
                     dom::Element* aScopeElement,
                     bool isAlternate);
 
-  nsresult InsertSheetInDoc(CSSStyleSheet* aSheet,
+  nsresult InsertSheetInDoc(StyleSheetHandle aSheet,
                             nsIContent* aLinkingContent,
                             nsIDocument* aDocument);
 
-  nsresult InsertChildSheet(CSSStyleSheet* aSheet,
-                            CSSStyleSheet* aParentSheet,
+  nsresult InsertChildSheet(StyleSheetHandle aSheet,
+                            StyleSheetHandle aParentSheet,
                             ImportRule* aParentRule);
 
   nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
                                         bool aIsPreload,
                                         SheetParsingMode aParsingMode,
                                         bool aUseSystemPrincipal,
                                         nsIPrincipal* aOriginPrincipal,
                                         const nsCString& aCharset,
-                                        CSSStyleSheet** aSheet,
+                                        StyleSheetHandle::RefPtr* aSheet,
                                         nsICSSLoaderObserver* aObserver,
                                         CORSMode aCORSMode = CORS_NONE,
                                         ReferrerPolicy aReferrerPolicy = mozilla::net::RP_Default,
                                         const nsAString& aIntegrity = EmptyString());
 
   // Post a load event for aObserver to be notified about aSheet.  The
   // notification will be sent with status NS_OK unless the load event is
   // canceled at some point (in which case it will be sent with
   // NS_BINDING_ABORTED).  aWasAlternate indicates the state when the load was
   // initiated, not the state at some later time.  aURI should be the URI the
   // sheet was loaded from (may be null for inline sheets).  aElement is the
   // owning element for this sheet.
   nsresult PostLoadEvent(nsIURI* aURI,
-                         CSSStyleSheet* aSheet,
+                         StyleSheetHandle aSheet,
                          nsICSSLoaderObserver* aObserver,
                          bool aWasAlternate,
                          nsIStyleSheetLinkingElement* aElement);
 
   // Start the loads of all the sheets in mPendingDatas
   void StartAlternateLoads();
 
   // Handle an event posted by PostLoadEvent
@@ -532,18 +533,19 @@ private:
 
   // The guts of SheetComplete.  This may be called recursively on parent datas
   // or datas that had glommed on to a single load.  The array is there so load
   // datas whose observers need to be notified can be added to it.
   void DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
                        LoadDataArray& aDatasToNotify);
 
   struct Sheets {
-    nsRefPtrHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, CSSStyleSheet>
-                      mCompleteSheets;
+    nsBaseHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey,
+                    StyleSheetHandle::RefPtr,
+                    StyleSheetHandle> mCompleteSheets;
     nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, SheetLoadData*>
                       mLoadingDatas; // weak refs
     nsDataHashtable<URIPrincipalReferrerPolicyAndCORSModeHashKey, SheetLoadData*>
                       mPendingDatas; // weak refs
   };
   nsAutoPtr<Sheets> mSheets;
 
   // We're not likely to have many levels of @import...  But likely to have
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -91,71 +91,71 @@ ServoStyleSet::ResolveAnonymousBoxStyle(
                                         uint32_t aFlags)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 // manage the set of style sheets in the style set
 nsresult
 ServoStyleSet::AppendStyleSheet(SheetType aType,
-                                CSSStyleSheet* aSheet)
+                                ServoStyleSheet* aSheet)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
 ServoStyleSet::PrependStyleSheet(SheetType aType,
-                                 CSSStyleSheet* aSheet)
+                                 ServoStyleSheet* aSheet)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
 ServoStyleSet::RemoveStyleSheet(SheetType aType,
-                                CSSStyleSheet* aSheet)
+                                ServoStyleSheet* aSheet)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
 ServoStyleSet::ReplaceSheets(SheetType aType,
-                             const nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets)
+                             const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
 ServoStyleSet::InsertStyleSheetBefore(SheetType aType,
-                                      CSSStyleSheet* aNewSheet,
-                                      CSSStyleSheet* aReferenceSheet)
+                                      ServoStyleSheet* aNewSheet,
+                                      ServoStyleSheet* aReferenceSheet)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 int32_t
 ServoStyleSet::SheetCount(SheetType aType) const
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
-CSSStyleSheet*
+ServoStyleSheet*
 ServoStyleSet::StyleSheetAt(SheetType aType,
                             int32_t aIndex) const
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
-ServoStyleSet::RemoveDocStyleSheet(CSSStyleSheet* aSheet)
+ServoStyleSet::RemoveDocStyleSheet(ServoStyleSheet* aSheet)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 nsresult
-ServoStyleSet::AddDocStyleSheet(CSSStyleSheet* aSheet,
+ServoStyleSet::AddDocStyleSheet(ServoStyleSheet* aSheet,
                                 nsIDocument* aDocument)
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ProbePseudoElementStyle(Element* aParentElement,
                                        CSSPseudoElementType aType,
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -15,16 +15,17 @@
 #include "nsIAtom.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 class CSSStyleSheet;
+class ServoStyleSheet;
 } // namespace mozilla
 class nsStyleContext;
 class nsPresContext;
 struct TreeMatchContext;
 
 namespace mozilla {
 
 /**
@@ -64,30 +65,30 @@ public:
                             dom::Element* aPseudoElement);
 
   // aFlags is an nsStyleSet flags bitfield
   already_AddRefed<nsStyleContext>
   ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
                            uint32_t aFlags = 0);
 
   // manage the set of style sheets in the style set
-  nsresult AppendStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
-  nsresult PrependStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
-  nsresult RemoveStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
+  nsresult AppendStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
+  nsresult PrependStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
+  nsresult RemoveStyleSheet(SheetType aType, ServoStyleSheet* aSheet);
   nsresult ReplaceSheets(SheetType aType,
-                         const nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets);
+                         const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets);
   nsresult InsertStyleSheetBefore(SheetType aType,
-                                  CSSStyleSheet* aNewSheet,
-                                  CSSStyleSheet* aReferenceSheet);
+                                  ServoStyleSheet* aNewSheet,
+                                  ServoStyleSheet* aReferenceSheet);
 
   int32_t SheetCount(SheetType aType) const;
-  CSSStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
+  ServoStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
 
-  nsresult RemoveDocStyleSheet(CSSStyleSheet* aSheet);
-  nsresult AddDocStyleSheet(CSSStyleSheet* aSheet, nsIDocument* aDocument);
+  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* aParentElement,
                           mozilla::CSSPseudoElementType aType,
                           nsStyleContext* aParentContext);
 
   already_AddRefed<nsStyleContext>
--- a/layout/style/StyleSetHandle.h
+++ b/layout/style/StyleSetHandle.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_StyleSetHandle_h
 #define mozilla_StyleSetHandle_h
 
 #include "mozilla/EventStates.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/SheetType.h"
 #include "mozilla/StyleBackendType.h"
+#include "mozilla/StyleSheetHandle.h"
 #include "nsChangeHint.h"
 #include "nsCSSPseudoElements.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 class CSSStyleSheet;
 class ServoStyleSet;
 namespace dom {
@@ -122,28 +123,28 @@ public:
     inline already_AddRefed<nsStyleContext>
     ResolvePseudoElementStyle(dom::Element* aParentElement,
                               mozilla::CSSPseudoElementType aType,
                               nsStyleContext* aParentContext,
                               dom::Element* aPseudoElement);
     inline already_AddRefed<nsStyleContext>
     ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
                              uint32_t aFlags = 0);
-    inline nsresult AppendStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
-    inline nsresult PrependStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
-    inline nsresult RemoveStyleSheet(SheetType aType, CSSStyleSheet* aSheet);
+    inline nsresult AppendStyleSheet(SheetType aType, StyleSheetHandle aSheet);
+    inline nsresult PrependStyleSheet(SheetType aType, StyleSheetHandle aSheet);
+    inline nsresult RemoveStyleSheet(SheetType aType, StyleSheetHandle aSheet);
     inline nsresult ReplaceSheets(SheetType aType,
-                           const nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets);
+                           const nsTArray<StyleSheetHandle::RefPtr>& aNewSheets);
     inline nsresult InsertStyleSheetBefore(SheetType aType,
-                                    CSSStyleSheet* aNewSheet,
-                                    CSSStyleSheet* aReferenceSheet);
+                                    StyleSheetHandle aNewSheet,
+                                    StyleSheetHandle aReferenceSheet);
     inline int32_t SheetCount(SheetType aType) const;
-    inline CSSStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
-    inline nsresult RemoveDocStyleSheet(CSSStyleSheet* aSheet);
-    inline nsresult AddDocStyleSheet(CSSStyleSheet* aSheet, nsIDocument* aDocument);
+    inline StyleSheetHandle StyleSheetAt(SheetType aType, int32_t aIndex) const;
+    inline nsresult RemoveDocStyleSheet(StyleSheetHandle aSheet);
+    inline nsresult AddDocStyleSheet(StyleSheetHandle aSheet, nsIDocument* aDocument);
     inline already_AddRefed<nsStyleContext>
     ProbePseudoElementStyle(dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType,
                             nsStyleContext* aParentContext);
     inline already_AddRefed<nsStyleContext>
     ProbePseudoElementStyle(dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType,
                             nsStyleContext* aParentContext,
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -2,21 +2,29 @@
 /* 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_StyleSetHandleInlines_h
 #define mozilla_StyleSetHandleInlines_h
 
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/ServoStyleSet.h"
+#include "mozilla/ServoStyleSheet.h"
 #include "nsStyleSet.h"
 
-#define FORWARD(method_, args_) \
-  return IsGecko() ? AsGecko()->method_ args_ : AsServo()->method_ args_;
+#define FORWARD_CONCRETE(method_, geckoargs_, servoargs_) \
+  if (IsGecko()) { \
+    return AsGecko()->method_ geckoargs_; \
+  } else { \
+    return AsServo()->method_ servoargs_; \
+  }
+
+#define FORWARD(method_, args_) FORWARD_CONCRETE(method_, args_, args_)
 
 namespace mozilla {
 
 void
 StyleSetHandle::Ptr::Delete()
 {
   if (mValue) {
     if (IsGecko()) {
@@ -107,71 +115,91 @@ StyleSetHandle::Ptr::ResolveAnonymousBox
                                               nsStyleContext* aParentContext,
                                               uint32_t aFlags)
 {
   FORWARD(ResolveAnonymousBoxStyle, (aPseudoTag, aParentContext, aFlags));
 }
 
 // manage the set of style sheets in the style set
 nsresult
-StyleSetHandle::Ptr::AppendStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
+StyleSetHandle::Ptr::AppendStyleSheet(SheetType aType, StyleSheetHandle aSheet)
 {
-  FORWARD(AppendStyleSheet, (aType, aSheet));
+  FORWARD_CONCRETE(AppendStyleSheet, (aType, aSheet->AsGecko()),
+                                     (aType, aSheet->AsServo()));
 }
 
 nsresult
-StyleSetHandle::Ptr::PrependStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
+StyleSetHandle::Ptr::PrependStyleSheet(SheetType aType, StyleSheetHandle aSheet)
 {
-  FORWARD(PrependStyleSheet, (aType, aSheet));
+  FORWARD_CONCRETE(PrependStyleSheet, (aType, aSheet->AsGecko()),
+                                      (aType, aSheet->AsServo()));
 }
 
 nsresult
-StyleSetHandle::Ptr::RemoveStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
+StyleSetHandle::Ptr::RemoveStyleSheet(SheetType aType, StyleSheetHandle aSheet)
 {
-  FORWARD(RemoveStyleSheet, (aType, aSheet));
+  FORWARD_CONCRETE(RemoveStyleSheet, (aType, aSheet->AsGecko()),
+                                     (aType, aSheet->AsServo()));
 }
 
 nsresult
 StyleSetHandle::Ptr::ReplaceSheets(SheetType aType,
-                       const nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets)
+                       const nsTArray<StyleSheetHandle::RefPtr>& aNewSheets)
 {
-  FORWARD(ReplaceSheets, (aType, aNewSheets));
+  if (IsGecko()) {
+    nsTArray<RefPtr<CSSStyleSheet>> newSheets(aNewSheets.Length());
+    for (auto& sheet : aNewSheets) {
+      newSheets.AppendElement(sheet->AsGecko());
+    }
+    return AsGecko()->ReplaceSheets(aType, newSheets);
+  } else {
+    nsTArray<RefPtr<ServoStyleSheet>> newSheets(aNewSheets.Length());
+    for (auto& sheet : aNewSheets) {
+      newSheets.AppendElement(sheet->AsServo());
+    }
+    return AsServo()->ReplaceSheets(aType, newSheets);
+  }
 }
 
 nsresult
 StyleSetHandle::Ptr::InsertStyleSheetBefore(SheetType aType,
-                                CSSStyleSheet* aNewSheet,
-                                CSSStyleSheet* aReferenceSheet)
+                                StyleSheetHandle aNewSheet,
+                                StyleSheetHandle aReferenceSheet)
 {
-  FORWARD(InsertStyleSheetBefore, (aType, aNewSheet, aReferenceSheet));
+  FORWARD_CONCRETE(
+    InsertStyleSheetBefore,
+    (aType, aNewSheet->AsGecko(), aReferenceSheet->AsGecko()),
+    (aType, aReferenceSheet->AsServo(), aReferenceSheet->AsServo()));
 }
 
 int32_t
 StyleSetHandle::Ptr::SheetCount(SheetType aType) const
 {
   FORWARD(SheetCount, (aType));
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 StyleSetHandle::Ptr::StyleSheetAt(SheetType aType, int32_t aIndex) const
 {
   FORWARD(StyleSheetAt, (aType, aIndex));
 }
 
 nsresult
-StyleSetHandle::Ptr::RemoveDocStyleSheet(CSSStyleSheet* aSheet)
+StyleSetHandle::Ptr::RemoveDocStyleSheet(StyleSheetHandle aSheet)
 {
-  FORWARD(RemoveDocStyleSheet, (aSheet));
+  FORWARD_CONCRETE(RemoveDocStyleSheet, (aSheet->AsGecko()),
+                                        (aSheet->AsServo()));
 }
 
 nsresult
-StyleSetHandle::Ptr::AddDocStyleSheet(CSSStyleSheet* aSheet,
+StyleSetHandle::Ptr::AddDocStyleSheet(StyleSheetHandle aSheet,
                                       nsIDocument* aDocument)
 {
-  FORWARD(AddDocStyleSheet, (aSheet, aDocument));
+  FORWARD_CONCRETE(AddDocStyleSheet, (aSheet->AsGecko(), aDocument),
+                                     (aSheet->AsServo(), aDocument));
 }
 
 // check whether there is ::before/::after style for an element
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
                                              CSSPseudoElementType aType,
                                              nsStyleContext* aParentContext)
 {
--- a/layout/style/nsICSSLoaderObserver.h
+++ b/layout/style/nsICSSLoaderObserver.h
@@ -4,24 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* internal interface for observing CSS style sheet loads */
 
 #ifndef nsICSSLoaderObserver_h___
 #define nsICSSLoaderObserver_h___
 
 #include "nsISupports.h"
+#include "mozilla/StyleSheetHandle.h"
 
-#define NS_ICSSLOADEROBSERVER_IID     \
-{ 0x7eb90c74, 0xea0c, 0x4df5,       \
-{0xa1, 0x5f, 0x95, 0xf0, 0x6a, 0x98, 0xb9, 0x40} }
-
-namespace mozilla {
-class CSSStyleSheet;
-} // namespace mozilla
+#define NS_ICSSLOADEROBSERVER_IID \
+{ 0xf51fbf2c, 0xfe4b, 0x4a15, \
+  { 0xaf, 0x7e, 0x5e, 0x20, 0x64, 0x5f, 0xaf, 0x58 } }
 
 class nsICSSLoaderObserver : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSSLOADEROBSERVER_IID)
 
   /**
    * StyleSheetLoaded is called after aSheet is marked complete and before any
    * load events associated with aSheet are fired.
@@ -32,16 +29,16 @@ public:
    *        aIsAlternate if one of those methods were used to load the sheet,
    *        and will always be false otherwise.
    * @param aStatus is a success code if the sheet loaded successfully and a
    *        failure code otherwise.  Note that successful load of aSheet
    *        doesn't indicate anything about whether the data actually parsed
    *        as CSS, and doesn't indicate anything about the status of any child
    *        sheets of aSheet.
    */
-  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+  NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheetHandle aSheet,
                               bool aWasAlternate,
                               nsresult aStatus) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSLoaderObserver, NS_ICSSLOADEROBSERVER_IID)
 
 #endif // nsICSSLoaderObserver_h___
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsLayoutStylesheetCache.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 #include "mozilla/css/Loader.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsPrintfCString.h"
 
@@ -60,227 +62,195 @@ nsLayoutStylesheetCache::Observe(nsISupp
     mNumberControlSheet = nullptr;
   }
   else {
     NS_NOTREACHED("Unexpected observer topic.");
   }
   return NS_OK;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::ScrollbarsSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mScrollbarsSheet) {
+  if (!mScrollbarsSheet) {
     // Scrollbars don't need access to unsafe rules
     LoadSheetURL("chrome://global/skin/scrollbars.css",
-                 gStyleCache->mScrollbarsSheet, eAuthorSheetFeatures);
+                 mScrollbarsSheet, eAuthorSheetFeatures);
   }
 
-  return gStyleCache->mScrollbarsSheet;
+  return mScrollbarsSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::FormsSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mFormsSheet) {
+  if (!mFormsSheet) {
     // forms.css needs access to unsafe rules
     LoadSheetURL("resource://gre-resources/forms.css",
-                 gStyleCache->mFormsSheet, eAgentSheetFeatures);
+                 mFormsSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mFormsSheet;
+  return mFormsSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::NumberControlSheet()
 {
-  EnsureGlobal();
-
   if (!sNumberControlEnabled) {
     return nullptr;
   }
 
-  if (!gStyleCache->mNumberControlSheet) {
+  if (!mNumberControlSheet) {
     LoadSheetURL("resource://gre-resources/number-control.css",
-                 gStyleCache->mNumberControlSheet, eAgentSheetFeatures);
+                 mNumberControlSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mNumberControlSheet;
+  return mNumberControlSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::UserContentSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mUserContentSheet;
+  return mUserContentSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::UserChromeSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mUserChromeSheet;
+  return mUserChromeSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::UASheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mUASheet) {
+  if (!mUASheet) {
     LoadSheetURL("resource://gre-resources/ua.css",
-                 gStyleCache->mUASheet, eAgentSheetFeatures);
+                 mUASheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mUASheet;
+  return mUASheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::HTMLSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mHTMLSheet;
+  return mHTMLSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::MinimalXULSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mMinimalXULSheet;
+  return mMinimalXULSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::XULSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mXULSheet;
+  return mXULSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::QuirkSheet()
 {
-  EnsureGlobal();
-  return gStyleCache->mQuirkSheet;
-}
-
-CSSStyleSheet*
-nsLayoutStylesheetCache::SVGSheet()
-{
-  EnsureGlobal();
-  return gStyleCache->mSVGSheet;
+  return mQuirkSheet;
 }
 
-CSSStyleSheet*
-nsLayoutStylesheetCache::MathMLSheet()
+StyleSheetHandle
+nsLayoutStylesheetCache::SVGSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mMathMLSheet) {
-    LoadSheetURL("resource://gre-resources/mathml.css",
-                 gStyleCache->mMathMLSheet, eAgentSheetFeatures);
-  }
-
-  return gStyleCache->mMathMLSheet;
+  return mSVGSheet;
 }
 
-CSSStyleSheet*
-nsLayoutStylesheetCache::CounterStylesSheet()
+StyleSheetHandle
+nsLayoutStylesheetCache::MathMLSheet()
 {
-  EnsureGlobal();
-
-  return gStyleCache->mCounterStylesSheet;
-}
-
-CSSStyleSheet*
-nsLayoutStylesheetCache::NoScriptSheet()
-{
-  EnsureGlobal();
-
-  if (!gStyleCache->mNoScriptSheet) {
-    LoadSheetURL("resource://gre-resources/noscript.css",
-                 gStyleCache->mNoScriptSheet, eAgentSheetFeatures);
+  if (!mMathMLSheet) {
+    LoadSheetURL("resource://gre-resources/mathml.css",
+                 mMathMLSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mNoScriptSheet;
+  return mMathMLSheet;
+}
+
+StyleSheetHandle
+nsLayoutStylesheetCache::CounterStylesSheet()
+{
+  return mCounterStylesSheet;
 }
 
-CSSStyleSheet*
+StyleSheetHandle
+nsLayoutStylesheetCache::NoScriptSheet()
+{
+  if (!mNoScriptSheet) {
+    LoadSheetURL("resource://gre-resources/noscript.css",
+                 mNoScriptSheet, eAgentSheetFeatures);
+  }
+
+  return mNoScriptSheet;
+}
+
+StyleSheetHandle
 nsLayoutStylesheetCache::NoFramesSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mNoFramesSheet) {
+  if (!mNoFramesSheet) {
     LoadSheetURL("resource://gre-resources/noframes.css",
-                 gStyleCache->mNoFramesSheet, eAgentSheetFeatures);
+                 mNoFramesSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mNoFramesSheet;
+  return mNoFramesSheet;
 }
 
-/* static */ CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::ChromePreferenceSheet(nsPresContext* aPresContext)
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mChromePreferenceSheet) {
-    gStyleCache->BuildPreferenceSheet(gStyleCache->mChromePreferenceSheet,
-                                      aPresContext);
+  if (!mChromePreferenceSheet) {
+    BuildPreferenceSheet(mChromePreferenceSheet, aPresContext);
   }
 
-  return gStyleCache->mChromePreferenceSheet;
+  return mChromePreferenceSheet;
 }
 
-/* static */ CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::ContentPreferenceSheet(nsPresContext* aPresContext)
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mContentPreferenceSheet) {
-    gStyleCache->BuildPreferenceSheet(gStyleCache->mContentPreferenceSheet,
-                                      aPresContext);
+  if (!mContentPreferenceSheet) {
+    BuildPreferenceSheet(mContentPreferenceSheet, aPresContext);
   }
 
-  return gStyleCache->mContentPreferenceSheet;
+  return mContentPreferenceSheet;
 }
 
-/* static */ CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::ContentEditableSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mContentEditableSheet) {
+  if (!mContentEditableSheet) {
     LoadSheetURL("resource://gre/res/contenteditable.css",
-                 gStyleCache->mContentEditableSheet, eAgentSheetFeatures);
+                 mContentEditableSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mContentEditableSheet;
+  return mContentEditableSheet;
 }
 
-/* static */ CSSStyleSheet*
+StyleSheetHandle
 nsLayoutStylesheetCache::DesignModeSheet()
 {
-  EnsureGlobal();
-
-  if (!gStyleCache->mDesignModeSheet) {
+  if (!mDesignModeSheet) {
     LoadSheetURL("resource://gre/res/designmode.css",
-                 gStyleCache->mDesignModeSheet, eAgentSheetFeatures);
+                 mDesignModeSheet, eAgentSheetFeatures);
   }
 
-  return gStyleCache->mDesignModeSheet;
+  return mDesignModeSheet;
 }
 
 void
 nsLayoutStylesheetCache::Shutdown()
 {
   NS_IF_RELEASE(gCSSLoader);
-  gStyleCache = nullptr;
+  gStyleCache_Gecko = nullptr;
+  gStyleCache_Servo = nullptr;
 }
 
 MOZ_DEFINE_MALLOC_SIZE_OF(LayoutStylesheetCacheMallocSizeOf)
 
 NS_IMETHODIMP
 nsLayoutStylesheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
                                         nsISupports* aData, bool aAnonymize)
 {
@@ -320,17 +290,18 @@ nsLayoutStylesheetCache::SizeOfIncluding
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - gCSSLoader
 
   return n;
 }
 
-nsLayoutStylesheetCache::nsLayoutStylesheetCache()
+nsLayoutStylesheetCache::nsLayoutStylesheetCache(StyleBackendType aType)
+  : mBackendType(aType)
 {
   nsCOMPtr<nsIObserverService> obsSvc =
     mozilla::services::GetObserverService();
   NS_ASSERTION(obsSvc, "No global observer service?");
 
   if (obsSvc) {
     obsSvc->AddObserver(this, "profile-before-change", false);
     obsSvc->AddObserver(this, "profile-do-change", false);
@@ -358,47 +329,56 @@ nsLayoutStylesheetCache::nsLayoutStylesh
   // The remaining sheets are created on-demand do to their use being rarer
   // (which helps save memory for Firefox OS apps) or because they need to
   // be re-loadable in DependentPrefChanged.
 }
 
 nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
 {
   mozilla::UnregisterWeakMemoryReporter(this);
-  MOZ_ASSERT(!gStyleCache);
 }
 
 void
 nsLayoutStylesheetCache::InitMemoryReporter()
 {
   mozilla::RegisterWeakMemoryReporter(this);
 }
 
-void
-nsLayoutStylesheetCache::EnsureGlobal()
+/* static */ nsLayoutStylesheetCache*
+nsLayoutStylesheetCache::For(StyleBackendType aType)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (gStyleCache) return;
-
-  gStyleCache = new nsLayoutStylesheetCache();
+  bool mustInit = !gStyleCache_Gecko && !gStyleCache_Servo;
+  auto& cache = aType == StyleBackendType::Gecko ? gStyleCache_Gecko :
+                                                   gStyleCache_Servo;
 
-  gStyleCache->InitMemoryReporter();
+  if (!cache) {
+    cache = new nsLayoutStylesheetCache(aType);
+    cache->InitMemoryReporter();
+  }
 
-  Preferences::AddBoolVarCache(&sNumberControlEnabled, NUMBER_CONTROL_PREF,
-                               true);
+  if (mustInit) {
+    // Initialization that only needs to be done once for both
+    // nsLayoutStylesheetCaches.
 
-  // For each pref that controls a CSS feature that a UA style sheet depends
-  // on (such as a pref that enables a property that a UA style sheet uses),
-  // register DependentPrefChanged as a callback to ensure that the relevant
-  // style sheets will be re-parsed.
-  // Preferences::RegisterCallback(&DependentPrefChanged,
-  //                               "layout.css.example-pref.enabled");
-  Preferences::RegisterCallback(&DependentPrefChanged,
-                                "layout.css.grid.enabled");
+    Preferences::AddBoolVarCache(&sNumberControlEnabled, NUMBER_CONTROL_PREF,
+                                 true);
+
+    // For each pref that controls a CSS feature that a UA style sheet depends
+    // on (such as a pref that enables a property that a UA style sheet uses),
+    // register DependentPrefChanged as a callback to ensure that the relevant
+    // style sheets will be re-parsed.
+    // Preferences::RegisterCallback(&DependentPrefChanged,
+    //                               "layout.css.example-pref.enabled");
+    Preferences::RegisterCallback(&DependentPrefChanged,
+                                  "layout.css.grid.enabled");
+  }
+
+  return cache;
 }
 
 void
 nsLayoutStylesheetCache::InitFromProfile()
 {
   nsCOMPtr<nsIXULRuntime> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
   if (appInfo) {
     bool inSafeMode = false;
@@ -423,30 +403,30 @@ nsLayoutStylesheetCache::InitFromProfile
   chromeFile->Append(NS_LITERAL_STRING("userChrome.css"));
 
   LoadSheetFile(contentFile, mUserContentSheet, eUserSheetFeatures);
   LoadSheetFile(chromeFile, mUserChromeSheet, eUserSheetFeatures);
 }
 
 /* static */ void
 nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
-                                      RefPtr<CSSStyleSheet>& aSheet,
+                                      StyleSheetHandle::RefPtr& aSheet,
                                       SheetParsingMode aParsingMode)
 {
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), aURL);
   LoadSheet(uri, aSheet, aParsingMode);
   if (!aSheet) {
     NS_ERROR(nsPrintfCString("Could not load %s", aURL).get());
   }
 }
 
 void
 nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile,
-                                       RefPtr<CSSStyleSheet>& aSheet,
+                                       StyleSheetHandle::RefPtr& aSheet,
                                        SheetParsingMode aParsingMode)
 {
   bool exists = false;
   aFile->Exists(&exists);
 
   if (!exists) return;
 
   nsCOMPtr<nsIURI> uri;
@@ -742,17 +722,17 @@ ErrorLoadingBuiltinSheet(nsIURI* aURI, c
     aURI->GetSpec(spec);
   }
   NS_RUNTIMEABORT(nsPrintfCString("%s loading built-in stylesheet '%s'",
                                   aMsg, spec.get()).get());
 }
 
 void
 nsLayoutStylesheetCache::LoadSheet(nsIURI* aURI,
-                                   RefPtr<CSSStyleSheet>& aSheet,
+                                   StyleSheetHandle::RefPtr& aSheet,
                                    SheetParsingMode aParsingMode)
 {
   if (!aURI) {
     ErrorLoadingBuiltinSheet(aURI, "null URI");
     return;
   }
 
   if (!gCSSLoader) {
@@ -763,62 +743,96 @@ nsLayoutStylesheetCache::LoadSheet(nsIUR
       return;
     }
   }
 
 
 #ifdef MOZ_CRASHREPORTER
   nsZipArchive::sFileCorruptedReason = nullptr;
 #endif
-  nsresult rv = gCSSLoader->LoadSheetSync(aURI, aParsingMode, true,
-                                          getter_AddRefs(aSheet));
+  nsresult rv = gCSSLoader->LoadSheetSync(aURI, aParsingMode, true, &aSheet);
   if (NS_FAILED(rv)) {
     ErrorLoadingBuiltinSheet(aURI,
       nsPrintfCString("LoadSheetSync failed with error %x", rv).get());
   }
 }
 
 /* static */ void
-nsLayoutStylesheetCache::InvalidateSheet(RefPtr<CSSStyleSheet>& aSheet)
+nsLayoutStylesheetCache::InvalidateSheet(StyleSheetHandle::RefPtr* aGeckoSheet,
+                                         StyleSheetHandle::RefPtr* aServoSheet)
 {
   MOZ_ASSERT(gCSSLoader, "pref changed before we loaded a sheet?");
 
-  if (aSheet) {
-    gCSSLoader->ObsoleteSheet(aSheet->GetSheetURI());
-    aSheet = nullptr;
+  // Make sure sheets have the expected types
+  MOZ_ASSERT(!aGeckoSheet || (*aGeckoSheet)->IsGecko());
+  MOZ_ASSERT(!aServoSheet || (*aServoSheet)->IsServo());
+  // Make sure the URIs match
+  MOZ_ASSERT(!aGeckoSheet || !aServoSheet ||
+             (*aGeckoSheet)->GetSheetURI() == (*aServoSheet)->GetSheetURI(),
+             "Sheets passed should have the same URI");
+
+  nsIURI* uri;
+  if (aGeckoSheet && *aGeckoSheet) {
+    uri = (*aGeckoSheet)->GetSheetURI();
+  } else if (aServoSheet && *aServoSheet) {
+    uri = (*aServoSheet)->GetSheetURI();
+  } else {
+    return;
+  }
+
+  gCSSLoader->ObsoleteSheet(uri);
+  if (aGeckoSheet) {
+    *aGeckoSheet = nullptr;
+  }
+  if (aServoSheet) {
+    *aServoSheet = nullptr;
   }
 }
 
 /* static */ void
 nsLayoutStylesheetCache::DependentPrefChanged(const char* aPref, void* aData)
 {
-  MOZ_ASSERT(gStyleCache, "pref changed after shutdown?");
+  MOZ_ASSERT(gStyleCache_Gecko || gStyleCache_Servo,
+             "pref changed after shutdown?");
 
   // Cause any UA style sheets whose parsing depends on the value of prefs
   // to be re-parsed by dropping the sheet from gCSSLoader's cache then
   // setting our cached sheet pointer to null.  This will only work for sheets
   // that are loaded lazily.
-  InvalidateSheet(gStyleCache->mUASheet); // for layout.css.grid.enabled
+
+#define INVALIDATE(sheet_) \
+  InvalidateSheet(gStyleCache_Gecko ? &gStyleCache_Gecko->sheet_ : nullptr, \
+                  gStyleCache_Servo ? &gStyleCache_Servo->sheet_ : nullptr);
+
+  INVALIDATE(mUASheet);  // for layout.css.grid.enabled
+
+#undef INVALIDATE
 }
 
 /* static */ void
 nsLayoutStylesheetCache::InvalidatePreferenceSheets()
 {
-  if (!gStyleCache) {
-    return;
+  if (gStyleCache_Gecko) {
+    gStyleCache_Gecko->mContentPreferenceSheet = nullptr;
+    gStyleCache_Gecko->mChromePreferenceSheet = nullptr;
   }
-
-  gStyleCache->mContentPreferenceSheet = nullptr;
-  gStyleCache->mChromePreferenceSheet = nullptr;
+  if (gStyleCache_Servo) {
+    gStyleCache_Servo->mContentPreferenceSheet = nullptr;
+    gStyleCache_Servo->mChromePreferenceSheet = nullptr;
+  }
 }
 
 void
-nsLayoutStylesheetCache::BuildPreferenceSheet(RefPtr<CSSStyleSheet>& aSheet,
+nsLayoutStylesheetCache::BuildPreferenceSheet(StyleSheetHandle::RefPtr& aSheet,
                                               nsPresContext* aPresContext)
 {
+  if (mBackendType == StyleBackendType::Servo) {
+    MOZ_CRASH("not implemented");
+  }
+
   aSheet = new CSSStyleSheet(CORS_NONE, mozilla::net::RP_Default);
   aSheet->SetParsingMode(eAgentSheetFeatures);
 
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nullptr);
   MOZ_ASSERT(uri, "URI creation shouldn't fail");
 
   aSheet->SetURIs(uri, uri, uri);
@@ -904,18 +918,21 @@ nsLayoutStylesheetCache::BuildPreference
         NS_GET_R_G_B(focusText),
         NS_GET_R_G_B(focusBG));
   }
 
   NS_ASSERTION(sheetText.Length() <= kPreallocSize,
                "kPreallocSize should be big enough to build preference style "
                "sheet without reallocation");
 
-  aSheet->ReparseSheet(sheetText);
+  aSheet->AsGecko()->ReparseSheet(sheetText);
 
 #undef NS_GET_R_G_B
 }
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
-nsLayoutStylesheetCache::gStyleCache;
+nsLayoutStylesheetCache::gStyleCache_Gecko;
+
+mozilla::StaticRefPtr<nsLayoutStylesheetCache>
+nsLayoutStylesheetCache::gStyleCache_Servo;
 
 mozilla::css::Loader*
 nsLayoutStylesheetCache::gCSSLoader = nullptr;
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -8,16 +8,17 @@
 #define nsLayoutStylesheetCache_h__
 
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/StaticPtr.h"
+#include "mozilla/StyleBackendType.h"
 #include "mozilla/css/Loader.h"
 
 class nsIFile;
 class nsIURI;
 
 namespace mozilla {
 class CSSStyleSheet;
 } // namespace mozilla
@@ -25,80 +26,92 @@ class CSSStyleSheet;
 class nsLayoutStylesheetCache final
  : public nsIObserver
  , public nsIMemoryReporter
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIMEMORYREPORTER
 
-  static mozilla::CSSStyleSheet* ScrollbarsSheet();
-  static mozilla::CSSStyleSheet* FormsSheet();
+  /**
+   * Returns the nsLayoutStylesheetCache for the given style backend type.
+   * Callers should pass in a value for aType that matches the style system
+   * backend type for the style set in use.  (A process may call For
+   * and obtain nsLayoutStylesheetCache objects for both backend types,
+   * and a particular UA style sheet might be cached in both, one or neither
+   * nsLayoutStylesheetCache.)
+   */
+  static nsLayoutStylesheetCache* For(mozilla::StyleBackendType aType);
+
+  mozilla::StyleSheetHandle ScrollbarsSheet();
+  mozilla::StyleSheetHandle FormsSheet();
   // This function is expected to return nullptr when the dom.forms.number
   // pref is disabled.
-  static mozilla::CSSStyleSheet* NumberControlSheet();
-  static mozilla::CSSStyleSheet* UserContentSheet();
-  static mozilla::CSSStyleSheet* UserChromeSheet();
-  static mozilla::CSSStyleSheet* UASheet();
-  static mozilla::CSSStyleSheet* HTMLSheet();
-  static mozilla::CSSStyleSheet* MinimalXULSheet();
-  static mozilla::CSSStyleSheet* XULSheet();
-  static mozilla::CSSStyleSheet* QuirkSheet();
-  static mozilla::CSSStyleSheet* SVGSheet();
-  static mozilla::CSSStyleSheet* MathMLSheet();
-  static mozilla::CSSStyleSheet* CounterStylesSheet();
-  static mozilla::CSSStyleSheet* NoScriptSheet();
-  static mozilla::CSSStyleSheet* NoFramesSheet();
-  static mozilla::CSSStyleSheet* ChromePreferenceSheet(nsPresContext* aPresContext);
-  static mozilla::CSSStyleSheet* ContentPreferenceSheet(nsPresContext* aPresContext);
-  static mozilla::CSSStyleSheet* ContentEditableSheet();
-  static mozilla::CSSStyleSheet* DesignModeSheet();
+  mozilla::StyleSheetHandle NumberControlSheet();
+  mozilla::StyleSheetHandle UserContentSheet();
+  mozilla::StyleSheetHandle UserChromeSheet();
+  mozilla::StyleSheetHandle UASheet();
+  mozilla::StyleSheetHandle HTMLSheet();
+  mozilla::StyleSheetHandle MinimalXULSheet();
+  mozilla::StyleSheetHandle XULSheet();
+  mozilla::StyleSheetHandle QuirkSheet();
+  mozilla::StyleSheetHandle SVGSheet();
+  mozilla::StyleSheetHandle MathMLSheet();
+  mozilla::StyleSheetHandle CounterStylesSheet();
+  mozilla::StyleSheetHandle NoScriptSheet();
+  mozilla::StyleSheetHandle NoFramesSheet();
+  mozilla::StyleSheetHandle ChromePreferenceSheet(nsPresContext* aPresContext);
+  mozilla::StyleSheetHandle ContentPreferenceSheet(nsPresContext* aPresContext);
+  mozilla::StyleSheetHandle ContentEditableSheet();
+  mozilla::StyleSheetHandle DesignModeSheet();
 
   static void InvalidatePreferenceSheets();
 
   static void Shutdown();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
-  nsLayoutStylesheetCache();
+  explicit nsLayoutStylesheetCache(mozilla::StyleBackendType aImpl);
   ~nsLayoutStylesheetCache();
 
-  static void EnsureGlobal();
   void InitFromProfile();
   void InitMemoryReporter();
   static void LoadSheetURL(const char* aURL,
-                           RefPtr<mozilla::CSSStyleSheet>& aSheet,
+                           mozilla::StyleSheetHandle::RefPtr& aSheet,
                            mozilla::css::SheetParsingMode aParsingMode);
   static void LoadSheetFile(nsIFile* aFile,
-                            RefPtr<mozilla::CSSStyleSheet>& aSheet,
+                            mozilla::StyleSheetHandle::RefPtr& aSheet,
                             mozilla::css::SheetParsingMode aParsingMode);
-  static void LoadSheet(nsIURI* aURI, RefPtr<mozilla::CSSStyleSheet>& aSheet,
+  static void LoadSheet(nsIURI* aURI, mozilla::StyleSheetHandle::RefPtr& aSheet,
                         mozilla::css::SheetParsingMode aParsingMode);
-  static void InvalidateSheet(RefPtr<mozilla::CSSStyleSheet>& aSheet);
+  static void InvalidateSheet(mozilla::StyleSheetHandle::RefPtr* aGeckoSheet,
+                              mozilla::StyleSheetHandle::RefPtr* aServoSheet);
   static void DependentPrefChanged(const char* aPref, void* aData);
-  void BuildPreferenceSheet(RefPtr<mozilla::CSSStyleSheet>& aSheet,
+  void BuildPreferenceSheet(mozilla::StyleSheetHandle::RefPtr& aSheet,
                             nsPresContext* aPresContext);
 
-  static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache;
+  static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Gecko;
+  static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Servo;
   static mozilla::css::Loader* gCSSLoader;
-  RefPtr<mozilla::CSSStyleSheet> mChromePreferenceSheet;
-  RefPtr<mozilla::CSSStyleSheet> mContentEditableSheet;
-  RefPtr<mozilla::CSSStyleSheet> mContentPreferenceSheet;
-  RefPtr<mozilla::CSSStyleSheet> mCounterStylesSheet;
-  RefPtr<mozilla::CSSStyleSheet> mDesignModeSheet;
-  RefPtr<mozilla::CSSStyleSheet> mFormsSheet;
-  RefPtr<mozilla::CSSStyleSheet> mHTMLSheet;
-  RefPtr<mozilla::CSSStyleSheet> mMathMLSheet;
-  RefPtr<mozilla::CSSStyleSheet> mMinimalXULSheet;
-  RefPtr<mozilla::CSSStyleSheet> mNoFramesSheet;
-  RefPtr<mozilla::CSSStyleSheet> mNoScriptSheet;
-  RefPtr<mozilla::CSSStyleSheet> mNumberControlSheet;
-  RefPtr<mozilla::CSSStyleSheet> mQuirkSheet;
-  RefPtr<mozilla::CSSStyleSheet> mSVGSheet;
-  RefPtr<mozilla::CSSStyleSheet> mScrollbarsSheet;
-  RefPtr<mozilla::CSSStyleSheet> mUASheet;
-  RefPtr<mozilla::CSSStyleSheet> mUserChromeSheet;
-  RefPtr<mozilla::CSSStyleSheet> mUserContentSheet;
-  RefPtr<mozilla::CSSStyleSheet> mXULSheet;
+  mozilla::StyleBackendType mBackendType;
+  mozilla::StyleSheetHandle::RefPtr mChromePreferenceSheet;
+  mozilla::StyleSheetHandle::RefPtr mContentEditableSheet;
+  mozilla::StyleSheetHandle::RefPtr mContentPreferenceSheet;
+  mozilla::StyleSheetHandle::RefPtr mCounterStylesSheet;
+  mozilla::StyleSheetHandle::RefPtr mDesignModeSheet;
+  mozilla::StyleSheetHandle::RefPtr mFormsSheet;
+  mozilla::StyleSheetHandle::RefPtr mHTMLSheet;
+  mozilla::StyleSheetHandle::RefPtr mMathMLSheet;
+  mozilla::StyleSheetHandle::RefPtr mMinimalXULSheet;
+  mozilla::StyleSheetHandle::RefPtr mNoFramesSheet;
+  mozilla::StyleSheetHandle::RefPtr mNoScriptSheet;
+  mozilla::StyleSheetHandle::RefPtr mNumberControlSheet;
+  mozilla::StyleSheetHandle::RefPtr mQuirkSheet;
+  mozilla::StyleSheetHandle::RefPtr mSVGSheet;
+  mozilla::StyleSheetHandle::RefPtr mScrollbarsSheet;
+  mozilla::StyleSheetHandle::RefPtr mUASheet;
+  mozilla::StyleSheetHandle::RefPtr mUserChromeSheet;
+  mozilla::StyleSheetHandle::RefPtr mUserContentSheet;
+  mozilla::StyleSheetHandle::RefPtr mXULSheet;
 };
 
 #endif
--- a/layout/style/nsMediaFeatures.cpp
+++ b/layout/style/nsMediaFeatures.cpp
@@ -14,16 +14,18 @@
 #include "nsCSSValue.h"
 #ifdef XP_WIN
 #include "mozilla/LookAndFeel.h"
 #endif
 #include "nsCSSRuleProcessor.h"
 #include "nsDeviceContext.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
+#include "mozilla/StyleSheetHandle.h"
+#include "mozilla/StyleSheetHandleInlines.h"
 
 using namespace mozilla;
 
 static const nsCSSProps::KTableEntry kOrientationKeywords[] = {
   { eCSSKeyword_portrait,                 NS_STYLE_ORIENTATION_PORTRAIT },
   { eCSSKeyword_landscape,                NS_STYLE_ORIENTATION_LANDSCAPE },
   { eCSSKeyword_UNKNOWN,                  -1 }
 };
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -740,35 +740,56 @@ nsStyleSet::AddDocStyleSheet(CSSStyleShe
 
     // If the sheet is not owned by the document it can be an author
     // sheet registered at nsStyleSheetService or an additional author
     // sheet on the document, which means the new 
     // doc sheet should end up before it.
     if (sheetDocIndex < 0) {
       if (sheetService) {
         auto& authorSheets = *sheetService->AuthorStyleSheets();
-        if (authorSheets.IndexOf(sheet) != authorSheets.NoIndex) {
+        StyleSheetHandle handle = sheet;
+        if (authorSheets.IndexOf(handle) != authorSheets.NoIndex) {
           break;
         }
       }
-      if (sheet == aDocument->FirstAdditionalAuthorSheet()) {
+      MOZ_ASSERT(!aDocument->FirstAdditionalAuthorSheet() ||
+                 aDocument->FirstAdditionalAuthorSheet()->IsGecko(),
+                 "why do we have a ServoStyleSheet for an nsStyleSet?");
+      if (sheet == aDocument->FirstAdditionalAuthorSheet()->GetAsGecko()) {
         break;
       }
     }
   }
 
   sheets.InsertElementAt(index, aSheet);
 
   if (!present) {
     aSheet->AddStyleSet(this);
   }
 
   return DirtyRuleProcessors(type);
 }
 
+void
+nsStyleSet::AppendAllXBLStyleSheets(nsTArray<mozilla::CSSStyleSheet*>& aArray) const
+{
+  if (mBindingManager) {
+    // XXXheycam stylo: AppendAllSheets will need to be able to return either
+    // CSSStyleSheets or ServoStyleSheets, on request (and then here requesting
+    // CSSStyleSheets).
+    AutoTArray<StyleSheetHandle, 32> sheets;
+    mBindingManager->AppendAllSheets(sheets);
+    for (StyleSheetHandle handle : sheets) {
+      MOZ_ASSERT(handle->IsGecko(), "stylo: AppendAllSheets shouldn't give us "
+                                    "ServoStyleSheets yet");
+      aArray.AppendElement(handle->AsGecko());
+    }
+  }
+}
+
 nsresult
 nsStyleSet::RemoveDocStyleSheet(CSSStyleSheet* aSheet)
 {
   bool isScoped = aSheet->GetScopeElement();
   return RemoveStyleSheet(isScoped ? SheetType::ScopedDoc : SheetType::Doc,
                           aSheet);
 }
 
@@ -2492,17 +2513,26 @@ nsStyleSet::EnsureUniqueInnerOnCSSSheets
   AutoTArray<CSSStyleSheet*, 32> queue;
   for (SheetType type : gCSSSheetTypes) {
     for (CSSStyleSheet* sheet : mSheets[type]) {
       queue.AppendElement(sheet);
     }
   }
 
   if (mBindingManager) {
-    mBindingManager->AppendAllSheets(queue);
+    AutoTArray<StyleSheetHandle, 32> sheets;
+    // XXXheycam stylo: AppendAllSheets will need to be able to return either
+    // CSSStyleSheets or ServoStyleSheets, on request (and then here requesting
+    // CSSStyleSheets).
+    mBindingManager->AppendAllSheets(sheets);
+    for (StyleSheetHandle sheet : sheets) {
+      MOZ_ASSERT(sheet->IsGecko(), "stylo: AppendAllSheets shouldn't give us "
+                                   "ServoStyleSheets yet");
+      queue.AppendElement(sheet->AsGecko());
+    }
   }
 
   while (!queue.IsEmpty()) {
     uint32_t idx = queue.Length() - 1;
     CSSStyleSheet* sheet = queue[idx];
     queue.RemoveElementAt(idx);
 
     sheet->EnsureUniqueInner();
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -333,21 +333,17 @@ class nsStyleSet final
     return mSheets[aType].Length();
   }
 
   mozilla::CSSStyleSheet* StyleSheetAt(mozilla::SheetType aType,
                                        int32_t aIndex) const {
     return mSheets[aType][aIndex];
   }
 
-  void AppendAllXBLStyleSheets(nsTArray<mozilla::CSSStyleSheet*>& aArray) const {
-    if (mBindingManager) {
-      mBindingManager->AppendAllSheets(aArray);
-    }
-  }
+  void AppendAllXBLStyleSheets(nsTArray<mozilla::CSSStyleSheet*>& aArray) const;
 
   nsresult RemoveDocStyleSheet(mozilla::CSSStyleSheet* aSheet);
   nsresult AddDocStyleSheet(mozilla::CSSStyleSheet* aSheet,
                             nsIDocument* aDocument);
 
   void     BeginUpdate();
   nsresult EndUpdate();