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 334079 51b6a0ea1b61c90a6b757d9a2d0e2589cc9e8a77
parent 334078 edbcfc242e24861a2404c09deaee0cf8626e5a6a
child 334080 12e4449dd3d1afc725f84059677bf1087f0be369
push id11446
push userjmaher@mozilla.com
push dateWed, 24 Feb 2016 11:34:35 +0000
reviewersdholbert
bugs1244074
milestone47.0a1
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();