Backed out 3 changesets (bug 1449321, bug 1449566, bug 1449565) as per developer request.
authorCosmin Sabou <csabou@mozilla.com>
Wed, 28 Mar 2018 18:10:11 +0300
changeset 410489 9eee0f48055b055ca94655772745ad6fec963163
parent 410488 7a4f627e88ea22e46da8b94f445069317d8784cf
child 410490 9be3b370ae62e248626b62f3bb8d2af941423cab
push id33729
push userrgurzau@mozilla.com
push dateWed, 28 Mar 2018 21:55:49 +0000
treeherdermozilla-central@6aa3b57955fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1449321, 1449566, 1449565
milestone61.0a1
backs outc31de7e26809522daca72a6050cd3ab665e8f6ff
72f9188800afb4dec5b69d0a9066bb0453c61fbc
763277b299e42d8ee7eafede027ee690b66a7a2a
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1449321, bug 1449566, bug 1449565) as per developer request. Backed out changeset c31de7e26809 (bug 1449565) Backed out changeset 72f9188800af (bug 1449566) Backed out changeset 763277b299e4 (bug 1449321)
dom/animation/EffectCompositor.cpp
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/canvas/CanvasRenderingContext2D.cpp
dom/html/HTMLBodyElement.cpp
dom/html/HTMLFontElement.cpp
dom/html/HTMLHRElement.cpp
dom/html/HTMLTableElement.cpp
dom/html/nsGenericHTMLElement.cpp
dom/smil/nsSMILAnimationController.cpp
dom/svg/nsSVGElement.cpp
dom/xbl/nsXBLResourceLoader.cpp
editor/libeditor/HTMLEditor.cpp
layout/base/PresShell.cpp
layout/base/RestyleManager.cpp
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsFrameManager.cpp
layout/base/nsPresContext.cpp
layout/base/nsStyleChangeList.cpp
layout/base/nsStyleChangeList.h
layout/generic/nsFrame.cpp
layout/style/DeclarationBlockInlines.h
layout/style/ErrorReporter.cpp
layout/style/ErrorReporter.h
layout/style/GenericSpecifiedValues.h
layout/style/GenericSpecifiedValuesInlines.h
layout/style/Loader.cpp
layout/style/Loader.h
layout/style/MediaList.h
layout/style/ServoBindings.cpp
layout/style/ServoMediaList.h
layout/style/ServoStyleRule.cpp
layout/style/ServoStyleSheet.cpp
layout/style/ServoUtils.h
layout/style/StreamLoader.cpp
layout/style/StyleSetHandle.h
layout/style/StyleSetHandleInlines.h
layout/style/StyleSheet.cpp
layout/style/nsCSSCounterStyleRule.cpp
layout/style/nsDOMCSSDeclaration.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
layout/style/nsStyleStruct.cpp
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -306,36 +306,37 @@ EffectCompositor::PostRestyleForAnimatio
   if (!element) {
     return;
   }
 
   nsRestyleHint hint = aCascadeLevel == CascadeLevel::Transitions ?
                                         eRestyle_CSSTransitions :
                                         eRestyle_CSSAnimations;
 
-  MOZ_ASSERT(NS_IsMainThread(),
-             "Restyle request during restyling should be requested only on "
-             "the main-thread. e.g. after the parallel traversal");
-  if (ServoStyleSet::IsInServoTraversal() || mIsInPreTraverse) {
-    MOZ_ASSERT(hint == eRestyle_CSSAnimations ||
-               hint == eRestyle_CSSTransitions);
+  if (mPresContext->StyleSet()->IsServo()) {
+    MOZ_ASSERT(NS_IsMainThread(),
+               "Restyle request during restyling should be requested only on "
+               "the main-thread. e.g. after the parallel traversal");
+    if (ServoStyleSet::IsInServoTraversal() || mIsInPreTraverse) {
+      MOZ_ASSERT(hint == eRestyle_CSSAnimations ||
+                 hint == eRestyle_CSSTransitions);
 
-    // We can't call Servo_NoteExplicitHints here since AtomicRefCell does not
-    // allow us mutate ElementData of the |aElement| in SequentialTask.
-    // Instead we call Servo_NoteExplicitHints for the element in PreTraverse()
-    // which will be called right before the second traversal that we do for
-    // updating CSS animations.
-    // In that case PreTraverse() will return true so that we know to do the
-    // second traversal so we don't need to post any restyle requests to the
-    // PresShell.
-    return;
+      // We can't call Servo_NoteExplicitHints here since AtomicRefCell does not
+      // allow us mutate ElementData of the |aElement| in SequentialTask.
+      // Instead we call Servo_NoteExplicitHints for the element in PreTraverse()
+      // which will be called right before the second traversal that we do for
+      // updating CSS animations.
+      // In that case PreTraverse() will return true so that we know to do the
+      // second traversal so we don't need to post any restyle requests to the
+      // PresShell.
+      return;
+    } else {
+      MOZ_ASSERT(!mPresContext->RestyleManager()->IsInStyleRefresh());
+    }
   }
-
-  MOZ_ASSERT(!mPresContext->RestyleManager()->IsInStyleRefresh());
-
   mPresContext->PresShell()->RestyleForAnimation(element, hint);
 }
 
 void
 EffectCompositor::PostRestyleForThrottledAnimations()
 {
   for (size_t i = 0; i < kCascadeLevelCount; i++) {
     CascadeLevel cascadeLevel = CascadeLevel(i);
@@ -806,16 +807,17 @@ EffectCompositor::PreTraverse(ServoTrave
   return PreTraverseInSubtree(aFlags, nullptr);
 }
 
 bool
 EffectCompositor::PreTraverseInSubtree(ServoTraversalFlags aFlags,
                                        Element* aRoot)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
   MOZ_ASSERT(!aRoot || nsContentUtils::GetPresShellForContent(aRoot),
              "Traversal root, if provided, should be bound to a display "
              "document");
 
   // Convert the root element to the parent element if the root element is
   // pseudo since we check each element in mElementsToRestyle is in the subtree
   // of the root element later in this function, but for pseudo elements the
   // element in mElementsToRestyle is the parent of the pseudo.
@@ -954,16 +956,17 @@ EffectCompositor::PreTraverseInSubtree(S
   return foundElementsNeedingRestyle;
 }
 
 bool
 EffectCompositor::PreTraverse(dom::Element* aElement,
                               CSSPseudoElementType aPseudoType)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
 
   // If |aElement|'s document does not have a pres shell, e.g. it is document
   // without a browsing context such as we might get from an XMLHttpRequest, we
   // should not run animations on it.
   if (!nsContentUtils::GetPresShellForContent(aElement)) {
     return false;
   }
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1309,19 +1309,25 @@ nsIDocument::SelectorCache::SelectorCach
 nsIDocument::SelectorCache::~SelectorCache()
 {
   AgeAllGenerations();
 }
 
 void
 nsIDocument::SelectorCache::SelectorList::Reset()
 {
-  if (mServo) {
-    Servo_SelectorList_Drop(mServo);
-    mServo = nullptr;
+  if (mIsServo) {
+    if (mServo) {
+      Servo_SelectorList_Drop(mServo);
+      mServo = nullptr;
+    }
+  } else {
+    if (mGecko) {
+      MOZ_CRASH("old style system disabled");
+    }
   }
 }
 
 
 void nsIDocument::SelectorCache::CacheList(
   const nsAString& aSelector,
   UniquePtr<RawServoSelectorList>&& aSelectorList)
 {
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1500,61 +1500,75 @@ public:
   class SelectorCache final
     : public nsExpirationTracker<SelectorCacheKey, 4>
   {
     public:
       class SelectorList
       {
       public:
         SelectorList()
-          : mGecko(nullptr)
+          : mIsServo(false)
+          , mGecko(nullptr)
         {}
 
         SelectorList(SelectorList&& aOther)
         {
           *this = mozilla::Move(aOther);
         }
 
         SelectorList& operator=(SelectorList&& aOther)
         {
           Reset();
-          mServo = aOther.mServo;
-          aOther.mServo = nullptr;
+          mIsServo = aOther.mIsServo;
+          if (mIsServo) {
+            mServo = aOther.mServo;
+            aOther.mServo = nullptr;
+          } else {
+            MOZ_CRASH("old style system disabled");
+          }
           return *this;
         }
 
         SelectorList(const SelectorList& aOther) = delete;
 
         explicit SelectorList(mozilla::UniquePtr<RawServoSelectorList>&& aList)
-          : mServo(aList.release())
+          : mIsServo(true)
+          , mServo(aList.release())
         {}
 
 
         ~SelectorList() {
           Reset();
         }
 
+        bool IsServo() const { return mIsServo; }
+        bool IsGecko() const { return !IsServo(); }
+
         explicit operator bool() const
         {
-          return !!AsServo();
+          return IsServo() ? !!AsServo() : !!AsGecko();
         }
 
         nsCSSSelectorList* AsGecko() const
         {
+          MOZ_ASSERT(IsGecko());
           return mGecko;
         }
 
         RawServoSelectorList* AsServo() const
         {
+          MOZ_ASSERT(IsServo());
           return mServo;
         }
 
       private:
         void Reset();
 
+        bool mIsServo;
+
         union {
           nsCSSSelectorList* mGecko;
           RawServoSelectorList* mServo;
         };
       };
 
       explicit SelectorCache(nsIEventTarget* aEventTarget);
 
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2684,16 +2684,18 @@ CreateFontDeclarationForServo(const nsAS
 }
 
 static already_AddRefed<ComputedStyle>
 GetFontStyleForServo(Element* aElement, const nsAString& aFont,
                      nsIPresShell* aPresShell,
                      nsAString& aOutUsedFont,
                      ErrorResult& aError)
 {
+  MOZ_ASSERT(aPresShell->StyleSet()->IsServo());
+
   RefPtr<RawServoDeclarationBlock> declarations =
     CreateFontDeclarationForServo(aFont, aPresShell->GetDocument());
   if (!declarations) {
     // We got a syntax error.  The spec says this value must be ignored.
     return nullptr;
   }
 
   // In addition to unparseable values, the spec says we need to reject
@@ -2753,16 +2755,18 @@ CreateFilterDeclarationForServo(const ns
 }
 
 static already_AddRefed<ComputedStyle>
 ResolveFilterStyleForServo(const nsAString& aFilterString,
                            const ComputedStyle* aParentStyle,
                            nsIPresShell* aPresShell,
                            ErrorResult& aError)
 {
+  MOZ_ASSERT(aPresShell->StyleSet()->IsServo());
+
   RefPtr<RawServoDeclarationBlock> declarations =
     CreateFilterDeclarationForServo(aFilterString, aPresShell->GetDocument());
   if (!declarations) {
     // Refuse to accept the filter, but do not throw an error.
     return nullptr;
   }
 
   // In addition to unparseable values, the spec says we need to reject
@@ -2791,17 +2795,24 @@ CanvasRenderingContext2D::ParseFilter(co
   }
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell) {
     aError.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
-  nsString usedFont; // unused
+  nsString usedFont;
+  if (presShell->StyleSet()->IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+    return false;
+  }
+
+  // For stylo
+  MOZ_ASSERT(presShell->StyleSet()->IsServo());
 
   RefPtr<ComputedStyle> parentStyle =
     GetFontStyleForServo(mCanvasElement,
                          GetFont(),
                          presShell,
                          usedFont,
                          aError);
   if (!parentStyle) {
@@ -3719,33 +3730,38 @@ CanvasRenderingContext2D::SetFontInterna
   }
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell) {
     aError.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
+  RefPtr<ComputedStyle> sc;
   nsString usedFont;
-  RefPtr<ComputedStyle> sc =
-    GetFontStyleForServo(mCanvasElement, aFont, presShell, usedFont, aError);
+  if (presShell->StyleSet()->IsServo()) {
+    sc =
+      GetFontStyleForServo(mCanvasElement, aFont, presShell, usedFont, aError);
+  } else {
+    MOZ_CRASH("old style system disabled");
+  }
   if (!sc) {
     return false;
   }
 
   const nsStyleFont* fontStyle = sc->StyleFont();
   nsPresContext* c = presShell->GetPresContext();
 
   // Purposely ignore the font size that respects the user's minimum
   // font preference (fontStyle->mFont.size) in favor of the computed
   // size (fontStyle->mSize).  See
   // https://bugzilla.mozilla.org/show_bug.cgi?id=698652.
   // FIXME: Nobody initializes mAllowZoom for servo?
-  //MOZ_ASSERT(!fontStyle->mAllowZoom,
-  //           "expected text zoom to be disabled on this nsStyleFont");
+  MOZ_ASSERT(presShell->StyleSet()->IsServo() || !fontStyle->mAllowZoom,
+             "expected text zoom to be disabled on this nsStyleFont");
   nsFont resizedFont(fontStyle->mFont);
   // Create a font group working in units of CSS pixels instead of the usual
   // device pixels, to avoid being affected by page zoom. nsFontMetrics will
   // convert nsFont size in app units to device pixels for the font group, so
   // here we first apply to the size the equivalent of a conversion from device
   // pixels to CSS pixels, to adjust for the difference in expectations from
   // other nsFontMetrics clients.
   resizedFont.size =
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -211,17 +211,18 @@ HTMLBodyElement::MapAttributesIntoRule(c
       value = aAttributes->GetAttr(nsGkAtoms::vlink);
       if (value && value->GetColorValue(color)) {
         styleSheet->SetVisitedLinkColor(color);
       }
     }
   }
 
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
-    if (!aData->PropertyIsSet(eCSSProperty_color)) {
+    if (!aData->PropertyIsSet(eCSSProperty_color) &&
+        !aData->ShouldIgnoreColors()) {
       // color: color
       nscolor color;
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::text);
       if (value && value->GetColorValue(color)) {
         aData->SetColorValue(eCSSProperty_color, color);
       }
     }
   }
--- a/dom/html/HTMLFontElement.cpp
+++ b/dom/html/HTMLFontElement.cpp
@@ -70,17 +70,18 @@ HTMLFontElement::MapAttributesIntoRule(c
     // size: int
     if (!aData->PropertyIsSet(eCSSProperty_font_size)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
       if (value && value->Type() == nsAttrValue::eInteger)
         aData->SetKeywordValue(eCSSProperty_font_size, value->GetIntegerValue());
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
-    if (!aData->PropertyIsSet(eCSSProperty_color)) {
+    if (!aData->PropertyIsSet(eCSSProperty_color) &&
+        !aData->ShouldIgnoreColors()) {
       // color: color
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
       nscolor color;
       if (value && value->GetColorValue(color)) {
         aData->SetColorValue(eCSSProperty_color, color);
       }
     }
   }
--- a/dom/html/HTMLHRElement.cpp
+++ b/dom/html/HTMLHRElement.cpp
@@ -162,17 +162,17 @@ HTMLHRElement::MapAttributesIntoRule(con
            *props != eCSSProperty_UNKNOWN; ++props) {
         aData->SetPixelValueIfUnset(*props, 10000.0f);
       }
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
     // color: a color
     // (we got the color attribute earlier)
-    if (colorIsSet) {
+    if (colorIsSet && !aData->ShouldIgnoreColors()) {
       aData->SetColorValueIfUnset(eCSSProperty_color, color);
     }
   }
 
   nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -985,17 +985,17 @@ HTMLTableElement::MapAttributesIntoRule(
         aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)value->GetIntegerValue());
       }
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))) {
     // bordercolor
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
     nscolor color;
-    if (value && value->GetColorValue(color)) {
+    if (value && !aData->ShouldIgnoreColors() && value->GetColorValue(color)) {
       aData->SetColorValueIfUnset(eCSSProperty_border_top_color, color);
       aData->SetColorValueIfUnset(eCSSProperty_border_left_color, color);
       aData->SetColorValueIfUnset(eCSSProperty_border_bottom_color, color);
       aData->SetColorValueIfUnset(eCSSProperty_border_right_color, color);
     }
 
     // border
     const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1470,34 +1470,36 @@ nsGenericHTMLElement::MapImageBorderAttr
 void
 nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
 
   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
     return;
 
-  if (!aData->PropertyIsSet(eCSSProperty_background_image)) {
+  if (!aData->PropertyIsSet(eCSSProperty_background_image) &&
+      !aData->ShouldIgnoreColors()) {
     // background
     nsAttrValue* value =
       const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
     if (value) {
       aData->SetBackgroundImage(*value);
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
                                      GenericSpecifiedValues* aData)
 {
   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
     return;
 
-  if (!aData->PropertyIsSet(eCSSProperty_background_color)) {
+  if (!aData->PropertyIsSet(eCSSProperty_background_color) &&
+      !aData->ShouldIgnoreColors()) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
     nscolor color;
     if (value && value->GetColorValue(color)) {
       aData->SetColorValue(eCSSProperty_background_color, color);
     }
   }
 }
 
@@ -2952,17 +2954,23 @@ nsGenericHTMLElement::NewURIFromString(c
   }
 
   return NS_OK;
 }
 
 static bool
 IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell)
 {
-  return !aElement->HasServoData() || Servo_Element_IsDisplayNone(aElement);
+  if (aPresShell->StyleSet()->IsServo()) {
+    return !aElement->HasServoData() || Servo_Element_IsDisplayNone(aElement);
+  }
+
+  MOZ_CRASH("Old style system disabled");
+
+  return false;
 }
 
 void
 nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue,
                                    mozilla::ErrorResult& aError)
 {
   if (!GetPrimaryFrame(FlushType::Layout)) {
     nsIPresShell* presShell = nsContentUtils::GetPresShellForContent(this);
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -710,16 +710,18 @@ nsSMILAnimationController::PreTraverseIn
   if (!mMightHavePendingStyleUpdates) {
     return false;
   }
 
   nsPresContext* context = mDocument->GetPresContext();
   if (!context) {
     return false;
   }
+  MOZ_ASSERT(context->RestyleManager()->IsServo(),
+             "PreTraverse should only be called for the servo style system");
 
   bool foundElementsNeedingRestyle = false;
   for (auto iter = mAnimationElementTable.Iter(); !iter.Done(); iter.Next()) {
     SVGAnimationElement* animElement = iter.Get()->GetKey();
 
     nsSMILTargetIdentifier key;
     if (!GetTargetIdentifierForAnimation(animElement, key)) {
       // Something's wrong/missing about animation's target; skip this animation
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -113,17 +113,17 @@ nsSVGElement::WrapNode(JSContext *aCx, J
 
 void
 nsSVGElement::DidAnimateClass()
 {
   // For Servo, snapshot the element before we change it.
   nsIPresShell* shell = OwnerDoc()->GetShell();
   if (shell) {
     nsPresContext* presContext = shell->GetPresContext();
-    if (presContext) {
+    if (presContext && presContext->RestyleManager()->IsServo()) {
       presContext->RestyleManager()
                  ->AsServo()
                  ->ClassAttributeWillBeChangedBySMIL(this);
     }
   }
 
   nsAutoString src;
   mClassAttribute.GetAnimValue(src, this);
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -177,18 +177,22 @@ nsXBLResourceLoader::StyleSheetLoaded(St
 
   mResources->AppendStyleSheet(aSheet);
 
   if (!mInLoadResourcesFunc)
     mPendingSheets--;
 
   if (mPendingSheets == 0) {
     // All stylesheets are loaded.
-    mResources->ComputeServoStyles(
-      *mBoundDocument->GetShell()->StyleSet()->AsServo());
+    if (aSheet->IsGecko()) {
+      MOZ_CRASH("old style system disabled");
+    } else {
+      mResources->ComputeServoStyles(
+        *mBoundDocument->GetShell()->StyleSet()->AsServo());
+    }
 
     // XXX Check for mPendingScripts when scripts also come online.
     if (!mInLoadResourcesFunc)
       NotifyBoundElements();
   }
   return NS_OK;
 }
 
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3008,18 +3008,22 @@ HTMLEditor::EnableExistingStyleSheet(con
   if (!sheet) {
     return false;
   }
 
   // Ensure the style sheet is owned by our document.
   nsCOMPtr<nsIDocument> document = GetDocument();
   sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
 
-  // FIXME: This used to do sheet->SetDisabled(false), figure out if we can
-  // just remove all this code in bug 1449522, since it seems unused.
+  if (sheet->IsServo()) {
+    // XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
+    NS_ERROR("stylo: ServoStyleSheets can't be disabled yet");
+    return true;
+  }
+  MOZ_CRASH("old style system disabled");
   return true;
 }
 
 nsresult
 HTMLEditor::AddNewStyleSheetToList(const nsAString& aURL,
                                    StyleSheet* aStyleSheet)
 {
   uint32_t countSS = mStyleSheets.Length();
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -599,17 +599,21 @@ mozilla::TimeStamp PresShell::sLastInput
 
 bool PresShell::sProcessInteractable = false;
 
 #ifdef DEBUG
 static void
 VerifyStyleTree(nsPresContext* aPresContext, nsFrameManager* aFrameManager)
 {
   if (nsFrame::GetVerifyStyleTreeEnable()) {
-    NS_ERROR("stylo: cannot verify style tree with a ServoRestyleManager");
+    if (aPresContext->RestyleManager()->IsServo()) {
+      NS_ERROR("stylo: cannot verify style tree with a ServoRestyleManager");
+      return;
+    }
+    MOZ_CRASH("old style system disabled");
   }
 }
 #define VERIFY_STYLE_TREE ::VerifyStyleTree(mPresContext, mFrameConstructor)
 #else
 #define VERIFY_STYLE_TREE
 #endif
 
 static bool gVerifyReflowEnabled;
@@ -4363,17 +4367,21 @@ PresShell::ContentStateChanged(nsIDocume
 void
 PresShell::DocumentStatesChanged(nsIDocument* aDocument, EventStates aStateMask)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected DocumentStatesChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
   MOZ_ASSERT(!aStateMask.IsEmpty());
 
   if (mDidInitialize) {
-    mStyleSet->AsServo()->InvalidateStyleForDocumentStateChanges(aStateMask);
+    if (mStyleSet->IsServo()) {
+      mStyleSet->AsServo()->InvalidateStyleForDocumentStateChanges(aStateMask);
+    } else {
+      MOZ_CRASH("old style system disabled");
+    }
   }
 
   if (aStateMask.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
     if (nsIFrame* root = mFrameConstructor->GetRootFrame()) {
       root->SchedulePaint();
     }
   }
 }
@@ -4583,16 +4591,17 @@ nsIPresShell::RestyleForCSSRuleChanges()
 }
 
 void
 PresShell::RecordStyleSheetChange(StyleSheet* aStyleSheet,
                                   StyleSheet::ChangeType aChangeType)
 {
   // too bad we can't check that the update is UPDATE_STYLE
   NS_ASSERTION(mUpdateCount != 0, "must be in an update");
+  MOZ_ASSERT(aStyleSheet->IsServo() == mStyleSet->IsServo());
 
   mStyleSet->RecordStyleSheetChange(aStyleSheet, aChangeType);
 }
 
 void
 PresShell::StyleSheetAdded(StyleSheet* aStyleSheet,
                            bool aDocumentSheet)
 {
@@ -9628,19 +9637,24 @@ PresShell::VerifyIncrementalReflow()
   vm->SetRootView(view);
 
   // Make the new presentation context the same size as our
   // presentation context.
   cx->SetVisibleArea(mPresContext->GetVisibleArea());
 
   // Create a new presentation shell to view the document. Use the
   // exact same style information that this document has.
-  nsAutoPtr<ServoStyleSet> newServoSet(CloneStyleSet(mStyleSet->AsServo()));
-  StyleSetHandle newSet(newServoSet);
-
+  nsAutoPtr<ServoStyleSet> newServoSet;
+  StyleSetHandle newSet;
+  if (mStyleSet->IsServo()) {
+    newServoSet = CloneStyleSet(mStyleSet->AsServo());
+    newSet = newServoSet;
+  } else {
+    MOZ_CRASH("old style system disabled");
+  }
   nsCOMPtr<nsIPresShell> sh = mDocument->CreateShell(cx, vm, newSet);
   NS_ENSURE_TRUE(sh, false);
   newServoSet.forget();
   // Note that after we create the shell, we must make sure to destroy it
   sh->SetVerifyReflowEnable(false); // turn off verify reflow while we're reflowing the test frame tree
   vm->SetPresShell(sh);
   {
     nsAutoCauseReflowNotifier crNotifier(this);
@@ -10361,17 +10375,21 @@ PresShell::AddSizeOfIncludingThis(nsWind
   aSizes.mLayoutPresShellSize += mallocSizeOf(this);
   if (mCaret) {
     aSizes.mLayoutPresShellSize += mCaret->SizeOfIncludingThis(mallocSizeOf);
   }
   aSizes.mLayoutPresShellSize +=
     mApproximatelyVisibleFrames.ShallowSizeOfExcludingThis(mallocSizeOf) +
     mFramesToDirty.ShallowSizeOfExcludingThis(mallocSizeOf);
 
-  StyleSet()->AsServo()->AddSizeOfIncludingThis(aSizes);
+  if (StyleSet()->IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    StyleSet()->AsServo()->AddSizeOfIncludingThis(aSizes);
+  }
 
   aSizes.mLayoutTextRunsSize += SizeOfTextRuns(mallocSizeOf);
 
   aSizes.mLayoutPresContextSize +=
     mPresContext->SizeOfIncludingThis(mallocSizeOf);
 
   mFrameConstructor->AddSizeOfIncludingThis(aSizes);
 }
@@ -10558,16 +10576,19 @@ ToSheetType(uint32_t aServiceSheetType)
   }
 }
 
 nsresult
 nsIPresShell::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
                                                       bool* aRetVal)
 {
   *aRetVal = false;
+  if (mStyleSet->IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  }
   return NS_OK;
 }
 
 void
 PresShell::NotifyStyleSheetServiceSheetAdded(StyleSheet* aSheet,
                                              uint32_t aSheetType)
 {
   if (!mStyleSet) {
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -369,17 +369,17 @@ RestyleManager::RestyleForInsertOrChange
 
 void
 RestyleManager::ContentRemoved(nsINode* aContainer,
                                nsIContent* aOldChild,
                                nsIContent* aFollowingSibling)
 {
   // Computed style data isn't useful for detached nodes, and we'll need to
   // recompute it anyway if we ever insert the nodes back into a document.
-  if (aOldChild->IsElement()) {
+  if (IsServo() && aOldChild->IsElement()) {
     ServoRestyleManager::ClearServoDataFromSubtree(aOldChild->AsElement());
   }
 
   // The container might be a document or a ShadowRoot.
   if (!aContainer->IsElement()) {
     return;
   }
   Element* container = aContainer->AsElement();
@@ -624,19 +624,23 @@ RestyleManager::ChangeHintToString(nsCha
 static bool gInApplyRenderingChangeToTree = false;
 #endif
 
 #ifdef DEBUG
 
 void
 RestyleManager::DebugVerifyStyleTree(nsIFrame* aFrame)
 {
-  // XXXheycam For now, we know that we don't use the same inheritance
-  // hierarchy for certain cases, so just skip these assertions until
-  // we work out what we want to assert (bug 1322570).
+  if (IsServo()) {
+    // XXXheycam For now, we know that we don't use the same inheritance
+    // hierarchy for certain cases, so just skip these assertions until
+    // we work out what we want to assert (bug 1322570).
+    return;
+  }
+  MOZ_CRASH("old style system disabled");
 }
 
 #endif // DEBUG
 
 /**
  * Sync views on aFrame and all of aFrame's descendants (following placeholders),
  * if aChange has nsChangeHint_SyncFrameView.
  * Calls DoApplyRenderingChangeToTree on all aFrame's out-of-flow descendants
@@ -1741,19 +1745,24 @@ RestyleManager::GetAnimationGenerationFo
 }
 
 void
 RestyleManager::IncrementAnimationGeneration()
 {
   // We update the animation generation at start of each call to
   // ProcessPendingRestyles so we should ignore any subsequent (redundant)
   // calls that occur while we are still processing restyles.
-  if (!mInStyleRefresh) {
-    ++mAnimationGeneration;
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    if (mInStyleRefresh) {
+      return;
+    }
   }
+  ++mAnimationGeneration;
 }
 
 /* static */ void
 RestyleManager::AddLayerChangesForAnimation(nsIFrame* aFrame,
                                             nsIContent* aContent,
                                             nsStyleChangeList&
                                               aChangeListToProcess)
 {
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -1146,17 +1146,17 @@ ServoRestyleManager::DoProcessPendingRes
 
   if (mRestyleForCSSRuleChanges) {
     aFlags |= ServoTraversalFlags::ForCSSRuleChanges;
   }
 
   while (styleSet->StyleDocument(aFlags)) {
     ClearSnapshots();
 
-    nsStyleChangeList currentChanges;
+    nsStyleChangeList currentChanges(StyleBackendType::Servo);
     bool anyStyleChanged = false;
 
     // Recreate styles , and queue up change hints (which also handle lazy frame
     // construction).
     {
       AutoRestyleTimelineMarker marker(presContext->GetDocShell(), false);
       DocumentStyleRootIterator iter(doc->GetServoRestyleRoot());
       while (Element* root = iter.GetNextStyleRoot()) {
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -300,16 +300,19 @@ private:
   struct TextPostTraversalState;
   bool ProcessPostTraversalForText(nsIContent* aTextNode,
                                    TextPostTraversalState& aState,
                                    ServoRestyleState& aRestyleState,
                                    ServoPostTraversalFlags aFlags);
 
   inline ServoStyleSet* StyleSet() const
   {
+    MOZ_ASSERT(PresContext()->StyleSet()->IsServo(),
+               "ServoRestyleManager should only be used with a Servo-flavored "
+               "style backend");
     return PresContext()->StyleSet()->AsServo();
   }
 
   const SnapshotTable& Snapshots() const { return mSnapshots; }
   void ClearSnapshots();
   ServoElementSnapshot& SnapshotFor(mozilla::dom::Element* aElement);
   void TakeSnapshotForAttributeChange(mozilla::dom::Element* aElement,
                                       int32_t aNameSpaceID,
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -466,17 +466,22 @@ static void
 ReparentFrame(RestyleManager* aRestyleManager,
               nsContainerFrame* aNewParentFrame,
               nsIFrame* aFrame,
               bool aForceStyleReparent)
 {
   aFrame->SetParent(aNewParentFrame);
   // We reparent frames for two reasons: to put them inside ::first-line, and to
   // put them inside some wrapper anonymous boxes.
-  if (aForceStyleReparent) {
+  //
+  // The latter shouldn't affect any styles in practice, so only needs style
+  // context reparenting in the Gecko backend.
+  //
+  // FIXME(emilio): Remove old Gecko stuff.
+  if (aForceStyleReparent || aRestyleManager->IsGecko()) {
     aRestyleManager->ReparentComputedStyle(aFrame);
   }
 }
 
 static void
 ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
                nsContainerFrame* aNewParentFrame,
                const nsFrameList& aFrameList,
@@ -10622,16 +10627,21 @@ nsCSSFrameConstructor::CheckForFirstLine
 
   if (aFrameItems.IsEmpty()) {
     // Happens often enough, with the caption stuff.  No need to do the ancestor
     // walk here.
     return;
   }
 
   class RestyleManager* restyleManager = RestyleManager();
+  if (!restyleManager->IsServo()) {
+    // Gecko's style resolution is frame-based, so already has the right styles
+    // even in the ::first-line case.
+    return;
+  }
 
   // Check whether there's a ::first-line on the path up from aParentFrame.
   // Note that we can't stop until we've run out of ancestors with
   // pseudo-element data, because the first-letter might be somewhere way up the
   // tree; in particular it might be past our containing block.
   nsIFrame* ancestor = aParentFrame;
   while (ancestor) {
     if (!ancestor->Style()->HasPseudoElementData()) {
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -80,17 +80,17 @@ public:
    *
    * All functions that are entry points into code that handles "parent"
    * objects (used as the hash table keys) must ensure that the parent objects
    * that they act on (and pass to other code) have been normalized by calling
    * this method.
    */
   static nsIContent* GetApplicableParent(nsIContent* aParent);
 
-  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
+  void AddSizeOfIncludingThis(nsWindowSizes& aSizes, bool aIsServo) const;
 
 protected:
   LinkedList<UndisplayedNode>* GetListFor(nsIContent* aParentContent);
   LinkedList<UndisplayedNode>* GetOrCreateListFor(nsIContent* aParentContent);
   void AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
 };
 
 //----------------------------------------------------------------------
@@ -688,22 +688,23 @@ nsFrameManager::DestroyAnonymousContent(
 
     content->UnbindFromTree();
   }
 }
 
 void
 nsFrameManager::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
 {
+  bool isServo = mPresShell->StyleSet()->IsServo();
   aSizes.mLayoutPresShellSize += aSizes.mState.mMallocSizeOf(this);
   if (mDisplayNoneMap) {
-    mDisplayNoneMap->AddSizeOfIncludingThis(aSizes);
+    mDisplayNoneMap->AddSizeOfIncludingThis(aSizes, isServo);
   }
   if (mDisplayContentsMap) {
-    mDisplayContentsMap->AddSizeOfIncludingThis(aSizes);
+    mDisplayContentsMap->AddSizeOfIncludingThis(aSizes, isServo);
   }
 }
 
 //----------------------------------------------------------------------
 
 nsFrameManager::UndisplayedMap::UndisplayedMap()
 {
   MOZ_COUNT_CTOR(nsFrameManager::UndisplayedMap);
@@ -834,25 +835,30 @@ nsFrameManager::UndisplayedMap::RemoveNo
     while (auto* node = list->popFirst()) {
       delete node;
     }
   }
 }
 
 void
 nsFrameManager::UndisplayedMap::
-AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
+AddSizeOfIncludingThis(nsWindowSizes& aSizes, bool aIsServo) const
 {
   MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
   aSizes.mLayoutPresShellSize += ShallowSizeOfIncludingThis(mallocSizeOf);
 
   nsWindowSizes staleSizes(aSizes.mState);
   for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
     const LinkedList<UndisplayedNode>* list = iter.UserData();
     aSizes.mLayoutPresShellSize += list->sizeOfExcludingThis(mallocSizeOf);
+    if (!aIsServo) {
+      // Computed values and style structs can only be stale when using
+      // Servo style system.
+      continue;
+    }
     for (const UndisplayedNode* node = list->getFirst();
           node; node = node->getNext()) {
       ComputedStyle* computedStyle = node->mStyle;
       if (!aSizes.mState.HaveSeenPtr(computedStyle)) {
         computedStyle->AddSizeOfIncludingThis(
           staleSizes, &aSizes.mLayoutComputedValuesStale);
       }
     }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1202,17 +1202,19 @@ nsPresContext::CompatibilityModeChanged(
   }
 
   nsIDocument* doc = mShell->GetDocument();
   if (!doc) {
     return;
   }
 
   StyleSetHandle styleSet = mShell->StyleSet();
-  styleSet->AsServo()->CompatibilityModeChanged();
+  if (styleSet->IsServo()) {
+    styleSet->AsServo()->CompatibilityModeChanged();
+  }
 
   if (doc->IsSVGDocument()) {
     // SVG documents never load quirk.css.
     return;
   }
 
   bool needsQuirkSheet = CompatibilityMode() == eCompatibility_NavQuirks;
   if (mQuirkSheetAdded == needsQuirkSheet) {
--- a/layout/base/nsStyleChangeList.cpp
+++ b/layout/base/nsStyleChangeList.cpp
@@ -40,31 +40,40 @@ nsStyleChangeList::AppendChange(nsIFrame
              "doing lazy frame construction");
   MOZ_ASSERT(!(aHint & nsChangeHint_AllReflowHints) ||
              (aHint & nsChangeHint_NeedReflow),
              "Reflow hint bits set without actually asking for a reflow");
 
   if (aHint & nsChangeHint_ReconstructFrame) {
     // If Servo fires reconstruct at a node, it is the only change hint fired at
     // that node.
-
-    // Note: Because we check whether |aHint| is a reconstruct above (which is
-    // necessary to avoid debug test timeouts on certain crashtests), this check
-    // will not find bugs where we add a non-reconstruct hint for an element after
-    // adding a reconstruct. This is ok though, since ProcessRestyledFrames will
-    // handle that case via mDestroyedFrames.
+    if (IsServo()) {
+      // Note: Because we check whether |aHint| is a reconstruct above (which is
+      // necessary to avoid debug test timeouts on certain crashtests), this check
+      // will not find bugs where we add a non-reconstruct hint for an element after
+      // adding a reconstruct. This is ok though, since ProcessRestyledFrames will
+      // handle that case via mDestroyedFrames.
 #ifdef DEBUG
-    for (size_t i = 0; i < Length(); ++i) {
-      MOZ_ASSERT(aContent != (*this)[i].mContent ||
-                 !((*this)[i].mHint & nsChangeHint_ReconstructFrame),
-                 "Should not append a non-ReconstructFrame hint after \
-                 appending a ReconstructFrame hint for the same \
-                 content.");
+      for (size_t i = 0; i < Length(); ++i) {
+        MOZ_ASSERT(aContent != (*this)[i].mContent ||
+                   !((*this)[i].mHint & nsChangeHint_ReconstructFrame),
+                   "Should not append a non-ReconstructFrame hint after \
+                   appending a ReconstructFrame hint for the same \
+                   content.");
+      }
+#endif
+    } else {
+      // Filter out all other changes for same content for Gecko (Servo asserts against this
+      // case above).
+      // NOTE: This is captured by reference to please static analysis.
+      // Capturing it by value as a pointer should be fine in this case.
+      RemoveElementsBy([&](const nsStyleChangeData& aData) {
+        return aData.mContent == aContent;
+      });
     }
-#endif
   }
 
   if (!IsEmpty() && aFrame && aFrame == LastElement().mFrame) {
     LastElement().mHint |= aHint;
     return;
   }
 
   AppendElement(nsStyleChangeData { aFrame, aContent, aHint });
--- a/layout/base/nsStyleChangeList.h
+++ b/layout/base/nsStyleChangeList.h
@@ -36,25 +36,30 @@ class nsStyleChangeList : private AutoTA
 public:
   using base_type::begin;
   using base_type::end;
   using base_type::IsEmpty;
   using base_type::Clear;
   using base_type::Length;
   using base_type::operator[];
 
-  nsStyleChangeList() {
-    MOZ_COUNT_CTOR(nsStyleChangeList);
-  }
+  explicit nsStyleChangeList(mozilla::StyleBackendType aType) :
+    mType(aType) { MOZ_COUNT_CTOR(nsStyleChangeList); }
   ~nsStyleChangeList() { MOZ_COUNT_DTOR(nsStyleChangeList); }
   void AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint);
 
   // Starting from the end of the list, removes all changes until the list is
   // empty or an element with |mContent != aContent| is found.
   void PopChangesForContent(nsIContent* aContent)
   {
     while (!IsEmpty() && LastElement().mContent == aContent) {
       RemoveLastElement();
     }
   }
+
+  bool IsGecko() const { return mType == mozilla::StyleBackendType::Gecko; }
+  bool IsServo() const { return mType == mozilla::StyleBackendType::Servo; }
+
+private:
+  mozilla::StyleBackendType mType;
 };
 
 #endif /* nsStyleChangeList_h___ */
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -763,16 +763,24 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
     if (placeholder) {
       placeholder->SetOutOfFlowFrame(nullptr);
     }
   }
 
   if (IsPrimaryFrame()) {
     // This needs to happen before we clear our Properties() table.
     ActiveLayerTracker::TransferActivityToContent(this, mContent);
+
+    // Unfortunately, we need to do this for all frames being reframed
+    // and not only those whose current style involves CSS transitions,
+    // because what matters is whether the new style (not the old)
+    // specifies CSS transitions.
+    if (presContext->RestyleManager()->IsGecko()) {
+      MOZ_CRASH("old style system disabled");
+    }
   }
 
   if (HasCSSAnimations() || HasCSSTransitions() ||
       EffectSet::GetEffectSet(this)) {
     // If no new frame for this element is created by the end of the
     // restyling process, stop animations and transitions for this frame
     RestyleManager::AnimationsWithDestroyedFrame* adf =
       presContext->RestyleManager()->GetAnimationsWithDestroyedFrame();
--- a/layout/style/DeclarationBlockInlines.h
+++ b/layout/style/DeclarationBlockInlines.h
@@ -23,23 +23,31 @@ MozExternalRefCountType
 DeclarationBlock::Release()
 {
   MOZ_STYLO_FORWARD(Release, ())
 }
 
 already_AddRefed<DeclarationBlock>
 DeclarationBlock::Clone() const
 {
-  return do_AddRef(new ServoDeclarationBlock(*AsServo()));
+  RefPtr<DeclarationBlock> result;
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    result = new ServoDeclarationBlock(*AsServo());
+  }
+  return result.forget();
 }
 
 already_AddRefed<DeclarationBlock>
 DeclarationBlock::EnsureMutable()
 {
-  if (!IsDirty()) {
+#ifdef DEBUG
+#endif
+  if (IsServo() && !IsDirty()) {
     // In stylo, the old DeclarationBlock is stored in element's rule node tree
     // directly, to avoid new values replacing the DeclarationBlock in the tree
     // directly, we need to copy the old one here if we haven't yet copied.
     // As a result the new value does not replace rule node tree until traversal
     // happens.
     return Clone();
   }
 
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -133,22 +133,30 @@ namespace css {
 ErrorReporter::ReleaseGlobals()
 {
   NS_IF_RELEASE(sConsoleService);
   NS_IF_RELEASE(sScriptErrorFactory);
   NS_IF_RELEASE(sStringBundle);
   NS_IF_RELEASE(sSpecCache);
 }
 
-ErrorReporter::ErrorReporter(const StyleSheet* aSheet,
+ErrorReporter::ErrorReporter(const nsCSSScanner& aScanner,
+                             const StyleSheet* aSheet,
                              const Loader* aLoader,
                              nsIURI* aURI)
-  : mSheet(aSheet)
-  , mLoader(aLoader)
-  , mURI(aURI),
+  : mScanner(&aScanner), mSheet(aSheet), mLoader(aLoader), mURI(aURI),
+    mInnerWindowID(0), mErrorLineNumber(0), mPrevErrorLineNumber(0),
+    mErrorColNumber(0)
+{
+}
+
+ErrorReporter::ErrorReporter(const ServoStyleSheet* aSheet,
+                             const Loader* aLoader,
+                             nsIURI* aURI)
+  : mScanner(nullptr), mSheet(aSheet), mLoader(aLoader), mURI(aURI),
     mInnerWindowID(0), mErrorLineNumber(0), mPrevErrorLineNumber(0),
     mErrorColNumber(0)
 {
 }
 
 ErrorReporter::~ErrorReporter()
 {
   // Schedule deferred cleanup for cached data. We want to strike a
@@ -275,16 +283,33 @@ ErrorReporter::ClearError()
 
 void
 ErrorReporter::AddToError(const nsString &aErrorText)
 {
   if (!ShouldReportErrors()) return;
 
   if (mError.IsEmpty()) {
     mError = aErrorText;
+    // If this error reporter is being used from Stylo, the equivalent operation occurs
+    // in the OutputError variant that provides source information.
+    if (!IsServo()) {
+      mErrorLineNumber = mScanner->GetLineNumber();
+      mErrorColNumber = mScanner->GetColumnNumber();
+      // Retrieve the error line once per line, and reuse the same nsString
+      // for all errors on that line.  That causes the text of the line to
+      // be shared among all the nsIScriptError objects.
+      if (mErrorLine.IsEmpty() || mErrorLineNumber != mPrevErrorLineNumber) {
+        // Be careful here: the error line might be really long and OOM
+        // when we try to make a copy here.  If so, just leave it empty.
+        if (!mErrorLine.Assign(mScanner->GetCurrentLine(), fallible)) {
+          mErrorLine.Truncate();
+        }
+        mPrevErrorLineNumber = mErrorLineNumber;
+      }
+    }
   } else {
     mError.AppendLiteral("  ");
     mError.Append(aErrorText);
   }
 }
 
 void
 ErrorReporter::ReportUnexpected(const char *aMessage)
@@ -398,12 +423,18 @@ ErrorReporter::ReportUnexpectedEOF(char1
   const char16_t *params[1] = { expectedStr };
 
   nsAutoString str;
   sStringBundle->FormatStringFromName("PEUnexpEOF2", params,
                                       ArrayLength(params), str);
   AddToError(str);
 }
 
+bool
+ErrorReporter::IsServo() const
+{
+  return !mScanner;
+}
+
 } // namespace css
 } // namespace mozilla
 
 #endif
--- a/layout/style/ErrorReporter.h
+++ b/layout/style/ErrorReporter.h
@@ -10,33 +10,38 @@
 #define mozilla_css_ErrorReporter_h_
 
 // XXX turn this off for minimo builds
 #define CSS_REPORT_PARSE_ERRORS
 
 #include "nsString.h"
 
 struct nsCSSToken;
+class nsCSSScanner;
 class nsIURI;
 
 namespace mozilla {
 class ServoStyleSheet;
 class StyleSheet;
 
 namespace css {
 
 class Loader;
 
 // If CSS_REPORT_PARSE_ERRORS is not defined, all of this class's
 // methods become inline stubs.
 class ErrorReporter {
 public:
-  ErrorReporter(const StyleSheet* aSheet,
-                const Loader* aLoader,
-                nsIURI* aURI);
+  ErrorReporter(const nsCSSScanner &aScanner,
+                const StyleSheet *aSheet,
+                const Loader *aLoader,
+                nsIURI *aURI);
+  ErrorReporter(const ServoStyleSheet *aSheet,
+                const Loader *aLoader,
+                nsIURI *aURI);
   ~ErrorReporter();
 
   static void ReleaseGlobals();
 
   void OutputError();
   void OutputError(uint32_t aLineNumber, uint32_t aLineOffset);
   void OutputError(uint32_t aLineNumber, uint32_t aLineOffset, const nsACString& aSource);
   void ClearError();
@@ -65,32 +70,36 @@ public:
   // name or a single character.  In the former case there may not be
   // any format parameters.
   void ReportUnexpectedEOF(const char *aExpected);
   void ReportUnexpectedEOF(char16_t aExpected);
 
 private:
   void AddToError(const nsString &aErrorText);
 
+  bool IsServo() const;
+
 #ifdef CSS_REPORT_PARSE_ERRORS
   nsAutoString mError;
   nsString mErrorLine;
   nsString mFileName;
+  const nsCSSScanner *mScanner;
   const StyleSheet *mSheet;
   const Loader *mLoader;
   nsIURI *mURI;
   uint64_t mInnerWindowID;
   uint32_t mErrorLineNumber;
   uint32_t mPrevErrorLineNumber;
   uint32_t mErrorColNumber;
 #endif
 };
 
 #ifndef CSS_REPORT_PARSE_ERRORS
-inline ErrorReporter::ErrorReporter(const StyleSheet*,
+inline ErrorReporter::ErrorReporter(const nsCSSScanner&,
+                                    const StyleSheet*,
                                     const Loader*,
                                     nsIURI*) {}
 inline ErrorReporter::~ErrorReporter() {}
 
 inline void ErrorReporter::ReleaseGlobals() {}
 
 inline void ErrorReporter::OutputError() {}
 inline void ErrorReporter::ClearError() {}
--- a/layout/style/GenericSpecifiedValues.h
+++ b/layout/style/GenericSpecifiedValues.h
@@ -41,16 +41,19 @@ protected:
 public:
   MOZ_DECL_STYLO_METHODS(nsRuleData, ServoSpecifiedValues)
 
   nsIDocument* Document()
   {
     return mDocument;
   }
 
+  // Whether we should ignore document colors.
+  inline bool ShouldIgnoreColors() const;
+
   // Check if we already contain a certain longhand
   inline bool PropertyIsSet(nsCSSPropertyID aId);
 
   // Check if we are able to hold longhands from a given
   // style struct. Pass the result of NS_STYLE_INHERIT_BIT to this
   // function. Can accept multiple inherit bits or'd together.
   inline bool ShouldComputeStyleStruct(uint64_t aInheritBits)
   {
--- a/layout/style/GenericSpecifiedValuesInlines.h
+++ b/layout/style/GenericSpecifiedValuesInlines.h
@@ -19,16 +19,29 @@
 
 namespace mozilla {
 
 MOZ_DEFINE_STYLO_METHODS(GenericSpecifiedValues,
                          nsRuleData,
                          ServoSpecifiedValues)
 
 bool
+GenericSpecifiedValues::ShouldIgnoreColors() const
+{
+  if (IsServo()) {
+    // Servo handles this during cascading.
+    //
+    // FIXME(emilio): We should eventually move it to the document though.
+    return false;
+  }
+
+  MOZ_CRASH("old style system disabled");
+}
+
+bool
 GenericSpecifiedValues::PropertyIsSet(nsCSSPropertyID aId)
 {
   MOZ_STYLO_FORWARD(PropertyIsSet, (aId))
 }
 
 void
 GenericSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
                                             const nsString& aValue)
@@ -59,17 +72,20 @@ GenericSpecifiedValues::SetIdentAtomValu
     SetIdentAtomValue(aId, aValue);
   }
 }
 
 void
 GenericSpecifiedValues::SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
 {
 
-  return AsServo()->SetKeywordValue(aId, aValue);
+  if (IsServo()) {
+    return AsServo()->SetKeywordValue(aId, aValue);
+  }
+  MOZ_CRASH("old style system disabled");
 }
 
 void
 GenericSpecifiedValues::SetKeywordValueIfUnset(nsCSSPropertyID aId,
                                                int32_t aValue)
 {
   if (!PropertyIsSet(aId)) {
     SetKeywordValue(aId, aValue);
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1193,25 +1193,30 @@ Loader::InsertSheetInDoc(StyleSheet* aSh
  * 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(StyleSheet* aSheet,
-                         StyleSheet* aParentSheet)
+                         StyleSheet* aParentSheet,
+                         ImportRule* aGeckoParentRule)
 {
   LOG(("css::Loader::InsertChildSheet"));
   MOZ_ASSERT(aSheet, "Nothing to insert");
   MOZ_ASSERT(aParentSheet, "Need a parent to insert into");
+  MOZ_ASSERT(aSheet->IsGecko() == !!aGeckoParentRule);
 
   // child sheets should always start out enabled, even if they got
   // cloned off of top-level sheets which were disabled
   aSheet->SetEnabled(true);
+  if (aGeckoParentRule) {
+    MOZ_CRASH("old style system disabled");
+  }
   aParentSheet->PrependStyleSheet(aSheet);
 
   LOG(("  Inserting into parent sheet"));
   return NS_OK;
 }
 
 /**
  * LoadSheet handles the actual load of a sheet.  If the load is
@@ -2076,21 +2081,23 @@ HaveAncestorDataWithURI(SheetLoadData *a
   return false;
 }
 
 nsresult
 Loader::LoadChildSheet(StyleSheet* aParentSheet,
                        SheetLoadData* aParentData,
                        nsIURI* aURL,
                        dom::MediaList* aMedia,
+                       ImportRule* aGeckoParentRule,
                        LoaderReusableStyleSheets* aReusableSheets)
 {
   LOG(("css::Loader::LoadChildSheet"));
   NS_PRECONDITION(aURL, "Must have a URI to load");
   NS_PRECONDITION(aParentSheet, "Must have a parent sheet");
+  MOZ_ASSERT(aParentSheet->IsGecko() == !!aGeckoParentRule);
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   LOG_URI("  Child uri: '%s'", aURL);
 
@@ -2146,33 +2153,36 @@ Loader::LoadChildSheet(StyleSheet* aPare
     observer = aParentSheet;
   }
 
   // Now that we know it's safe to load this (passes security check and not a
   // loop) do so.
   RefPtr<StyleSheet> sheet;
   StyleSheetState state;
   if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
+    if (aParentSheet->IsGecko()) {
+      MOZ_CRASH("old style system disabled");
+    }
     state = eSheetComplete;
   } else {
     bool isAlternate;
     const nsAString& empty = EmptyString();
     // For now, use CORS_NONE for child sheets
     rv = CreateSheet(aURL, nullptr, principal,
                      aParentSheet->ParsingMode(),
                      CORS_NONE, aParentSheet->GetReferrerPolicy(),
                      EmptyString(), // integrity is only checked on main sheet
                      aParentData ? aParentData->mSyncLoad : false,
                      false, empty, state, &isAlternate, &sheet);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PrepareSheet(sheet, empty, empty, aMedia, isAlternate);
   }
 
-  rv = InsertChildSheet(sheet, aParentSheet);
+  rv = InsertChildSheet(sheet, aParentSheet, aGeckoParentRule);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
     // We're completely done.  No need to notify, even, since the
     // @import rule addition/modification will trigger the right style
     // changes automatically.
     return NS_OK;
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -296,23 +296,27 @@ public:
    * child sheet is already complete when this method returns, no
    * nsICSSLoaderObserver notification will be sent.
    *
    * @param aParentSheet the parent of this child sheet
    * @param aParentData the SheetLoadData corresponding to the load of the
    *                    parent sheet.
    * @param aURL the URL of the child sheet
    * @param aMedia the already-parsed media list for the child sheet
+   * @param aGeckoParentRule the @import rule importing this child, when using
+   *                         Gecko's style system. 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(StyleSheet* aParentSheet,
                           SheetLoadData* aParentData,
                           nsIURI* aURL,
                           dom::MediaList* aMedia,
+                          ImportRule* aGeckoParentRule,
                           LoaderReusableStyleSheets* aSavedSheets);
 
   /**
    * Synchronously load and return the stylesheet at aURL.  Any child sheets
    * will also be loaded synchronously.  Note that synchronous loads over some
    * protocols may involve spinning up a new event loop, so use of this method
    * does NOT guarantee not receiving any events before the sheet loads.  This
    * method can be used to load sheets not associated with a document.
@@ -522,17 +526,18 @@ private:
                     dom::MediaList* aMediaList,
                     bool aIsAlternate);
 
   nsresult InsertSheetInDoc(StyleSheet* aSheet,
                             nsIContent* aLinkingContent,
                             nsIDocument* aDocument);
 
   nsresult InsertChildSheet(StyleSheet* aSheet,
-                            StyleSheet* aParentSheet);
+                            StyleSheet* aParentSheet,
+                            ImportRule* aGeckoParentRule);
 
   nsresult InternalLoadNonDocumentSheet(
     nsIURI* aURL,
     bool aIsPreload,
     SheetParsingMode aParsingMode,
     bool aUseSystemPrincipal,
     nsIPrincipal* aOriginPrincipal,
     const Encoding* aPreloadEncoding,
--- a/layout/style/MediaList.h
+++ b/layout/style/MediaList.h
@@ -52,16 +52,20 @@ public:
 
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
   nsISupports* GetParentObject() const { return nullptr; }
 
   virtual void GetText(nsAString& aMediaText) = 0;
   virtual void SetText(const nsAString& aMediaText) = 0;
   virtual bool Matches(nsPresContext* aPresContext) const = 0;
 
+#ifdef DEBUG
+  virtual bool IsServo() const = 0;
+#endif
+
   void SetStyleSheet(StyleSheet* aSheet);
 
   // WebIDL
   void GetMediaText(nsAString& aMediaText);
   void SetMediaText(const nsAString& aMediaText);
   virtual uint32_t Length() = 0;
   virtual void IndexedGetter(uint32_t aIndex, bool& aFound,
                              nsAString& aReturn) = 0;
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -400,26 +400,38 @@ Gecko_HaveSeenPtr(SeenPtrs* aTable, cons
 
 RawServoDeclarationBlockStrongBorrowedOrNull
 Gecko_GetStyleAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
 {
   DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
   if (!decl) {
     return nullptr;
   }
+  if (decl->IsGecko()) {
+    // XXX This can happen when nodes are adopted from a Gecko-style-backend
+    //     document into a Servo-style-backend document.  See bug 1330051.
+    NS_WARNING("stylo: requesting a Gecko declaration block?");
+    return nullptr;
+  }
   return decl->AsServo()->RefRawStrong();
 }
 
 void
 Gecko_UnsetDirtyStyleAttr(RawGeckoElementBorrowed aElement)
 {
   DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
   if (!decl) {
     return;
   }
+  if (decl->IsGecko()) {
+    // XXX This can happen when nodes are adopted from a Gecko-style-backend
+    //     document into a Servo-style-backend document.  See bug 1330051.
+    NS_WARNING("stylo: requesting a Gecko declaration block?");
+    return;
+  }
   decl->UnsetDirty();
 }
 
 static const RawServoDeclarationBlockStrong*
 AsRefRawStrong(const RefPtr<RawServoDeclarationBlock>& aDecl)
 {
   static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
                 sizeof(RawServoDeclarationBlockStrong),
@@ -2525,17 +2537,17 @@ Gecko_LoadStyleSheet(css::Loader* aLoade
   nsDependentCSubstring urlSpec(reinterpret_cast<const char*>(aURLString),
                                 aURLStringLength);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nullptr,
                           aURLExtraData->BaseURI());
 
   StyleSheet* previousFirstChild = aParent->GetFirstChild();
   if (NS_SUCCEEDED(rv)) {
-    rv = aLoader->LoadChildSheet(aParent, aParentLoadData, uri, media, aReusableSheets);
+    rv = aLoader->LoadChildSheet(aParent, aParentLoadData, uri, media, nullptr, aReusableSheets);
   }
 
   if (NS_FAILED(rv) ||
       !aParent->GetFirstChild() ||
       aParent->GetFirstChild() == previousFirstChild) {
     // Servo and Gecko have different ideas of what a valid URL is, so we might
     // get in here with a URL string that NS_NewURI can't handle.  We may also
     // reach here via an import cycle.  For the import cycle case, we need some
--- a/layout/style/ServoMediaList.h
+++ b/layout/style/ServoMediaList.h
@@ -28,16 +28,20 @@ public:
   void SetText(const nsAString& aMediaText) final;
 
   uint32_t Length() final;
   void IndexedGetter(uint32_t aIndex, bool& aFound,
                      nsAString& aReturn) final;
 
   bool Matches(nsPresContext*) const final;
 
+#ifdef DEBUG
+  bool IsServo() const final { return true; }
+#endif
+
   RawServoMediaList& RawList() { return *mRawList; }
 
 protected:
   nsresult Delete(const nsAString& aOldMedium) final;
   nsresult Append(const nsAString& aNewMedium) final;
   void SetTextInternal(const nsAString& aMediaText, dom::CallerType);
 
   ~ServoMediaList() {}
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -67,16 +67,18 @@ ServoStyleRuleDeclaration::GetCSSDeclara
   return mDecls;
 }
 
 nsresult
 ServoStyleRuleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
 {
   ServoStyleRule* rule = Rule();
   if (RefPtr<StyleSheet> sheet = rule->GetStyleSheet()) {
+    MOZ_ASSERT(sheet->IsServo(), "Servo style rules should have "
+                                 "servo stylesheets.");
     nsCOMPtr<nsIDocument> doc = sheet->GetAssociatedDocument();
     mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true);
     if (aDecl != mDecls) {
       mDecls->SetOwningRule(nullptr);
       RefPtr<ServoDeclarationBlock> decls = aDecl->AsServo();
       Servo_StyleRule_SetStyle(rule->Raw(), decls->Raw());
       mDecls = decls.forget();
       mDecls->SetOwningRule(rule);
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -203,16 +203,17 @@ ServoStyleSheet::ParseSheet(css::Loader*
                             nsIPrincipal* aSheetPrincipal,
                             css::SheetLoadData* aLoadData,
                             uint32_t aLineNumber,
                             nsCompatibility aCompatMode,
                             css::LoaderReusableStyleSheets* aReusableSheets)
 {
   MOZ_ASSERT(mParsePromise.IsEmpty());
   RefPtr<StyleSheetParsePromise> p = mParsePromise.Ensure(__func__);
+  MOZ_ASSERT(!mMedia || mMedia->IsServo());
   Inner()->mURLData = new URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal); // RefPtr
   Inner()->mContents = Servo_StyleSheet_FromUTF8Bytes(aLoader,
                                                       this,
                                                       aLoadData,
                                                       aInput.Elements(),
                                                       aInput.Length(),
                                                       mParsingMode,
                                                       Inner()->mURLData,
@@ -231,16 +232,17 @@ ServoStyleSheet::ParseSheetSync(css::Loa
                                 nsIURI* aSheetURI,
                                 nsIURI* aBaseURI,
                                 nsIPrincipal* aSheetPrincipal,
                                 css::SheetLoadData* aLoadData,
                                 uint32_t aLineNumber,
                                 nsCompatibility aCompatMode,
                                 css::LoaderReusableStyleSheets* aReusableSheets)
 {
+  MOZ_ASSERT(!mMedia || mMedia->IsServo());
   Inner()->mURLData = new URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal); // RefPtr
 
   Inner()->mContents = Servo_StyleSheet_FromUTF8Bytes(aLoader,
                                                       this,
                                                       aLoadData,
                                                       aInput.Elements(),
                                                       aInput.Length(),
                                                       mParsingMode,
@@ -368,16 +370,19 @@ ServoStyleSheet::ReparseSheet(const nsAS
 }
 
 // nsICSSLoaderObserver implementation
 NS_IMETHODIMP
 ServoStyleSheet::StyleSheetLoaded(StyleSheet* aSheet,
                                   bool aWasAlternate,
                                   nsresult aStatus)
 {
+  MOZ_ASSERT(aSheet->IsServo(),
+             "why we were called back with a CSSStyleSheet?");
+
   ServoStyleSheet* sheet = aSheet->AsServo();
   if (!sheet->GetParentSheet()) {
     return NS_OK; // ignore if sheet has been detached already
   }
   NS_ASSERTION(this == sheet->GetParentSheet(),
                "We are being notified of a sheet load for a sheet that is not our child!");
 
   if (NS_SUCCEEDED(aStatus)) {
--- a/layout/style/ServoUtils.h
+++ b/layout/style/ServoUtils.h
@@ -30,16 +30,20 @@ inline bool IsInServoTraversal()
   // are generally unprepared to deal with non-Servo-but-also-non-main-thread
   // callers, and are likely to take the main-thread codepath if this function
   // returns false. So we assert against other non-main-thread callers here.
   MOZ_ASSERT(sInServoTraversal || NS_IsMainThread());
   return sInServoTraversal;
 }
 } // namespace mozilla
 
+# define MOZ_DECL_STYLO_CHECK_METHODS \
+  bool IsGecko() const { return false; } \
+  bool IsServo() const { return true; }
+
 #define MOZ_DECL_STYLO_CONVERT_METHODS_SERVO(servotype_) \
   inline servotype_* AsServo();                         \
   inline const servotype_* AsServo() const;             \
   inline servotype_* GetAsServo();                      \
   inline const servotype_* GetAsServo() const;
 
 #define MOZ_DECL_STYLO_CONVERT_METHODS_GECKO(geckotype_) \
   inline geckotype_* AsGecko();                         \
@@ -50,44 +54,49 @@ inline bool IsInServoTraversal()
 #define MOZ_DECL_STYLO_CONVERT_METHODS(geckotype_, servotype_) \
   MOZ_DECL_STYLO_CONVERT_METHODS_SERVO(servotype_)
 
 /**
  * Macro used in a base class of |geckotype_| and |servotype_|.
  * The class should define |StyleBackendType mType;| itself.
  */
 #define MOZ_DECL_STYLO_METHODS(geckotype_, servotype_)  \
+  MOZ_DECL_STYLO_CHECK_METHODS                          \
   MOZ_DECL_STYLO_CONVERT_METHODS(geckotype_, servotype_)
 
 #define MOZ_DEFINE_STYLO_METHODS_GECKO(type_, geckotype_) \
   geckotype_* type_::AsGecko() {                                \
+    MOZ_ASSERT(IsGecko());                                      \
     return static_cast<geckotype_*>(this);                      \
   }                                                             \
   const geckotype_* type_::AsGecko() const {                    \
+    MOZ_ASSERT(IsGecko());                                      \
     return static_cast<const geckotype_*>(this);                \
   }                                                             \
   geckotype_* type_::GetAsGecko() {                             \
-    return nullptr;                                             \
+    return IsGecko() ? AsGecko() : nullptr;                     \
   }                                                             \
   const geckotype_* type_::GetAsGecko() const {                 \
-    return nullptr;                                             \
+    return IsGecko() ? AsGecko() : nullptr;                     \
   }
 
 #define MOZ_DEFINE_STYLO_METHODS_SERVO(type_, servotype_) \
   servotype_* type_::AsServo() {                                \
+    MOZ_ASSERT(IsServo());                                      \
     return static_cast<servotype_*>(this);                      \
   }                                                             \
   const servotype_* type_::AsServo() const {                    \
+    MOZ_ASSERT(IsServo());                                      \
     return static_cast<const servotype_*>(this);                \
   }                                                             \
   servotype_* type_::GetAsServo() {                             \
-    return AsServo();                                           \
+    return IsServo() ? AsServo() : nullptr;                     \
   }                                                             \
   const servotype_* type_::GetAsServo() const {                 \
-    return AsServo();                                           \
+    return IsServo() ? AsServo() : nullptr;                     \
   }
 
 
 /**
  * Macro used in inline header of class |type_| with its Gecko and Servo
  * subclasses named |geckotype_| and |servotype_| correspondingly for
  * implementing the inline methods defined by MOZ_DECL_STYLO_METHODS.
  */
--- a/layout/style/StreamLoader.cpp
+++ b/layout/style/StreamLoader.cpp
@@ -15,16 +15,17 @@ using namespace mozilla;
 
 namespace mozilla {
 namespace css {
 
 StreamLoader::StreamLoader(mozilla::css::SheetLoadData* aSheetLoadData)
   : mSheetLoadData(aSheetLoadData)
   , mStatus(NS_OK)
 {
+  MOZ_ASSERT(!aSheetLoadData->mSheet->IsGecko());
 }
 
 StreamLoader::~StreamLoader()
 {
 }
 
 NS_IMPL_ISUPPORTS(StreamLoader, nsIStreamListener)
 
--- a/layout/style/StyleSetHandle.h
+++ b/layout/style/StyleSetHandle.h
@@ -38,52 +38,68 @@ class ServoStyleSet;
 namespace dom {
 class Element;
 class ShadowRoot;
 } // namespace dom
 namespace css {
 class Rule;
 } // namespace css
 
+#define SERVO_BIT 0x1
+
 /**
  * Smart pointer class that can hold a pointer to either an nsStyleSet
  * or a ServoStyleSet.
  */
 class StyleSetHandle
 {
 public:
   // We define this Ptr class with a StyleSet API that forwards on to the
   // wrapped pointer, rather than putting these methods on StyleSetHandle
   // itself, so that we can have StyleSetHandle behave like a smart pointer and
   // be dereferenced with operator->.
   class Ptr
   {
   public:
     friend class ::mozilla::StyleSetHandle;
 
+    bool IsGecko() const
+    {
+      return false;
+    }
+
+    bool IsServo() const
+    {
+      MOZ_ASSERT(mValue, "StyleSetHandle null pointer dereference");
+      return mValue & SERVO_BIT;
+    }
+
     StyleBackendType BackendType() const
     {
-      return StyleBackendType::Servo;
+      return IsGecko() ? StyleBackendType::Gecko :
+                         StyleBackendType::Servo;
     }
 
 
     ServoStyleSet* AsServo()
     {
-      return reinterpret_cast<ServoStyleSet*>(mValue);
+      MOZ_ASSERT(IsServo());
+      return reinterpret_cast<ServoStyleSet*>(mValue & ~SERVO_BIT);
     }
 
-    ServoStyleSet* GetAsServo() { return AsServo(); }
+    ServoStyleSet* GetAsServo() { return IsServo() ? AsServo() : nullptr; }
 
 
     const ServoStyleSet* AsServo() const
     {
+      MOZ_ASSERT(IsServo());
       return const_cast<Ptr*>(this)->AsServo();
     }
 
-    const ServoStyleSet* GetAsServo() const { return AsServo(); }
+    const ServoStyleSet* GetAsServo() const { return IsServo() ? AsServo() : nullptr; }
 
     // These inline methods are defined in StyleSetHandleInlines.h.
     inline void Delete();
 
     // Style set interface.  These inline methods are defined in
     // StyleSetHandleInlines.h and just forward to the underlying
     // nsStyleSet or ServoStyleSet.  See corresponding comments in
     // nsStyleSet.h for descriptions of these methods.
@@ -157,16 +173,18 @@ public:
     inline nsRestyleHint MediumFeaturesChanged(mozilla::MediaFeatureChangeReason);
     inline already_AddRefed<ComputedStyle>
     ProbePseudoElementStyle(dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType,
                             ComputedStyle* aParentContext);
     inline already_AddRefed<ComputedStyle>
     ProbePseudoElementStyle(dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType);
+    inline void RootComputedStyleAdded();
+    inline void RootComputedStyleRemoved();
 
     inline bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
     inline nsCSSCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
     inline already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
 
     inline bool EnsureUniqueInnerOnCSSSheets();
     inline void SetNeedsRestyleAfterEnsureUniqueInner();
 
@@ -180,24 +198,28 @@ public:
 
   StyleSetHandle() { mPtr.mValue = 0; }
   StyleSetHandle(const StyleSetHandle& aOth) { mPtr.mValue = aOth.mPtr.mValue; }
   MOZ_IMPLICIT StyleSetHandle(nsStyleSet* aSet) { *this = aSet; }
   MOZ_IMPLICIT StyleSetHandle(ServoStyleSet* aSet) { *this = aSet; }
 
   StyleSetHandle& operator=(nsStyleSet* aStyleSet)
   {
+    MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT),
+               "least significant bit shouldn't be set; we use it for state");
     mPtr.mValue = reinterpret_cast<uintptr_t>(aStyleSet);
     return *this;
   }
 
   StyleSetHandle& operator=(ServoStyleSet* aStyleSet)
   {
+    MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aStyleSet) & SERVO_BIT),
+               "least significant bit shouldn't be set; we use it for state");
     mPtr.mValue =
-      aStyleSet ? reinterpret_cast<uintptr_t>(aStyleSet) : 0;
+      aStyleSet ? (reinterpret_cast<uintptr_t>(aStyleSet) | SERVO_BIT) : 0;
     return *this;
   }
 
   // Make StyleSetHandle usable in boolean contexts.
   explicit operator bool() const { return !!mPtr.mValue; }
   bool operator!() const { return !mPtr.mValue; }
   bool operator==(const StyleSetHandle& aOth) const
   {
@@ -208,11 +230,13 @@ public:
   // Make StyleSetHandle behave like a smart pointer.
   Ptr* operator->() { return &mPtr; }
   const Ptr* operator->() const { return &mPtr; }
 
 private:
   Ptr mPtr;
 };
 
+#undef SERVO_BIT
+
 } // namespace mozilla
 
 #endif // mozilla_StyleSetHandle_h
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -20,16 +20,19 @@
 #define FORWARD(method_, args_) FORWARD_CONCRETE(method_, args_, args_)
 
 namespace mozilla {
 
 void
 StyleSetHandle::Ptr::Delete()
 {
   if (mValue) {
+    if (IsGecko()) {
+      MOZ_CRASH("old style system disabled");
+    }
     delete AsServo();
   }
 }
 
 void
 StyleSetHandle::Ptr::Init(nsPresContext* aPresContext)
 {
   FORWARD(Init, (aPresContext));
@@ -153,16 +156,20 @@ StyleSetHandle::Ptr::RemoveStyleSheet(Sh
   FORWARD_CONCRETE(RemoveStyleSheet, (aType, aSheet->AsGecko()),
                                      (aType, aSheet->AsServo()));
 }
 
 nsresult
 StyleSetHandle::Ptr::ReplaceSheets(SheetType aType,
                        const nsTArray<RefPtr<StyleSheet>>& aNewSheets)
 {
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  }
+
   nsTArray<RefPtr<ServoStyleSheet>> newSheets(aNewSheets.Length());
   for (auto& sheet : aNewSheets) {
     newSheets.AppendElement(sheet->AsServo());
   }
   return AsServo()->ReplaceSheets(aType, newSheets);
 }
 
 nsresult
@@ -264,16 +271,36 @@ StyleSetHandle::Ptr::InvalidateStyleForC
 already_AddRefed<ComputedStyle>
 StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
                                              CSSPseudoElementType aType,
                                              ComputedStyle* aParentStyle)
 {
   FORWARD(ProbePseudoElementStyle, (aParentElement, aType, aParentStyle));
 }
 
+void
+StyleSetHandle::Ptr::RootComputedStyleAdded()
+{
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  }
+
+  // Not needed.
+}
+
+void
+StyleSetHandle::Ptr::RootComputedStyleRemoved()
+{
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  }
+
+  // Not needed.
+}
+
 bool
 StyleSetHandle::Ptr::
 AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
 {
   FORWARD(AppendFontFaceRules, (aArray));
 }
 
 nsCSSCounterStyleRule*
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -75,17 +75,21 @@ StyleSheet::~StyleSheet()
 
 void
 StyleSheet::LastRelease()
 {
   MOZ_ASSERT(mInner, "Should have an mInner at time of destruction.");
   MOZ_ASSERT(mInner->mSheets.Contains(this), "Our mInner should include us.");
 
   UnparentChildren();
-  AsServo()->LastRelease();
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    AsServo()->LastRelease();
+  }
 
   mInner->RemoveSheet(this);
   mInner = nullptr;
 
   DropMedia();
 }
 
 void
@@ -388,20 +392,24 @@ StyleSheet::EnsureUniqueInner()
     return;
   }
 
   StyleSheetInfo* clone = mInner->CloneFor(this);
   MOZ_ASSERT(clone);
   mInner->RemoveSheet(this);
   mInner = clone;
 
-  // Fixup the child lists and parent links in the Servo sheet. This is done
-  // here instead of in StyleSheetInner::CloneFor, because it's just more
-  // convenient to do so instead.
-  AsServo()->BuildChildListAfterInnerClone();
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    // Fixup the child lists and parent links in the Servo sheet. This is done
+    // here instead of in StyleSheetInner::CloneFor, because it's just more
+    // convenient to do so instead.
+    AsServo()->BuildChildListAfterInnerClone();
+  }
 
   // let our containing style sets know that if we call
   // nsPresContext::EnsureSafeToHandOutCSSRules we will need to restyle the
   // document
   for (StyleSetHandle& setHandle : mStyleSets) {
     setHandle->SetNeedsRestyleAfterEnsureUniqueInner();
   }
 }
@@ -412,17 +420,20 @@ StyleSheet::AppendAllChildSheets(nsTArra
   for (StyleSheet* child = GetFirstChild(); child; child = child->mNext) {
     aArray.AppendElement(child);
   }
 }
 
 // WebIDL CSSStyleSheet API
 
 #define FORWARD_INTERNAL(method_, args_) \
-  return AsServo()->method_ args_;
+  if (IsServo()) { \
+    return AsServo()->method_ args_; \
+  } \
+  MOZ_CRASH("old style system disabled");
 
 dom::CSSRuleList*
 StyleSheet::GetCssRules(nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aRv)
 {
   if (!AreRulesAvailable(aSubjectPrincipal, aRv)) {
     return nullptr;
   }
@@ -588,18 +599,22 @@ StyleSheet::InsertRuleIntoGroup(const ns
     return NS_ERROR_INVALID_ARG;
   }
 
   // parse and grab the rule
   mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
 
   WillDirty();
 
-  nsresult result =
-    AsServo()->InsertRuleIntoGroupInternal(aRule, aGroup, aIndex);
+  nsresult result;
+  if (IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    result = AsServo()->InsertRuleIntoGroupInternal(aRule, aGroup, aIndex);
+  }
   NS_ENSURE_SUCCESS(result, result);
   RuleAdded(*aGroup->GetStyleRuleAt(aIndex));
 
   return NS_OK;
 }
 
 uint64_t
 StyleSheet::FindOwningWindowInnerID() const
--- a/layout/style/nsCSSCounterStyleRule.cpp
+++ b/layout/style/nsCSSCounterStyleRule.cpp
@@ -384,22 +384,29 @@ nsCSSCounterStyleRule::CheckDescValue(in
   }
 }
 
 void
 nsCSSCounterStyleRule::SetDescriptor(nsCSSCounterDesc aDescID,
                                      const nsAString& aValue)
 {
   nsCSSValue value;
+  bool ok;
 
   StyleSheet* sheet = GetStyleSheet();
 
-  URLExtraData* data = sheet ? sheet->AsServo()->URLData() : nullptr;
-  bool ok = ServoCSSParser::ParseCounterStyleDescriptor(aDescID, aValue, data,
-                                                        value);
+  bool useServo = !sheet || sheet->IsServo();
+
+  if (useServo) {
+    URLExtraData* data = sheet ? sheet->AsServo()->URLData() : nullptr;
+    ok = ServoCSSParser::ParseCounterStyleDescriptor(aDescID, aValue, data,
+                                                     value);
+  } else {
+    MOZ_CRASH("old style system disabled");
+  }
 
   if (ok && CheckDescValue(GetSystem(), aDescID, value)) {
     SetDesc(aDescID, value);
   }
 }
 
 #define CSS_COUNTER_DESC_SETTER(name_)                        \
 void                                                          \
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -116,27 +116,31 @@ nsDOMCSSDeclaration::SetCssText(const ns
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
 
-  ServoCSSParsingEnvironment servoEnv =
-    GetServoCSSParsingEnvironment(aSubjectPrincipal);
-  if (!servoEnv.mUrlExtraData) {
-    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
-    return;
+  RefPtr<DeclarationBlock> newdecl;
+  if (olddecl->IsServo()) {
+    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
+        aSubjectPrincipal);
+    if (!servoEnv.mUrlExtraData) {
+      aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+      return;
+    }
+
+    newdecl = ServoDeclarationBlock::FromCssText(aCssText, servoEnv.mUrlExtraData,
+                                                 servoEnv.mCompatMode, servoEnv.mLoader);
+  } else {
+    MOZ_CRASH("old style system disabled");
   }
 
-  RefPtr<DeclarationBlock> newdecl =
-    ServoDeclarationBlock::FromCssText(aCssText, servoEnv.mUrlExtraData,
-                                       servoEnv.mCompatMode, servoEnv.mLoader);
-
   aRv = SetCSSDeclaration(newdecl);
 }
 
 uint32_t
 nsDOMCSSDeclaration::Length()
 {
   DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read);
 
@@ -286,24 +290,27 @@ nsDOMCSSDeclaration::ModifyDeclaration(n
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
 
   bool changed;
-  ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
-      aSubjectPrincipal);
-  if (!servoEnv.mUrlExtraData) {
-    return NS_ERROR_NOT_AVAILABLE;
+  if (decl->IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
+        aSubjectPrincipal);
+    if (!servoEnv.mUrlExtraData) {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+
+    changed = aServoFunc(decl->AsServo(), servoEnv);
   }
-
-  changed = aServoFunc(decl->AsServo(), servoEnv);
-
   if (!changed) {
     // Parsing failed -- but we don't throw an exception for that.
     return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
 
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -111,20 +111,24 @@ nsHTMLStyleSheet::ImplLinkColorSetter(
     nscolor aColor)
 {
   if (!mDocument || !mDocument->GetShell()) {
     return NS_OK;
   }
 
   RestyleManager* restyle = mDocument->GetPresContext()->RestyleManager();
 
-  MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
-  aDecl = Servo_DeclarationBlock_CreateEmpty().Consume();
-  Servo_DeclarationBlock_SetColorValue(aDecl.get(), eCSSProperty_color,
-                                       aColor);
+  if (restyle->IsServo()) {
+    MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
+    aDecl = Servo_DeclarationBlock_CreateEmpty().Consume();
+    Servo_DeclarationBlock_SetColorValue(aDecl.get(), eCSSProperty_color,
+                                         aColor);
+  } else {
+    MOZ_CRASH("old style system disabled");
+  }
 
   // Now make sure we restyle any links that might need it.  This
   // shouldn't happen often, so just rebuilding everything is ok.
   Element* root = mDocument->GetRootElement();
   if (root) {
     restyle->PostRestyleEvent(root, eRestyle_Subtree, nsChangeHint(0));
   }
   return NS_OK;
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -816,16 +816,77 @@ nsLayoutStylesheetCache::LoadSheet(nsIUR
   if (NS_FAILED(rv)) {
     ErrorLoadingSheet(aURI,
       nsPrintfCString("LoadSheetSync failed with error %" PRIx32, static_cast<uint32_t>(rv)).get(),
       aFailureAction);
   }
 }
 
 /* static */ void
+nsLayoutStylesheetCache::InvalidateSheet(RefPtr<StyleSheet>* aGeckoSheet,
+                                         RefPtr<StyleSheet>* aServoSheet)
+{
+  MOZ_ASSERT(gCSSLoader_Gecko || gCSSLoader_Servo,
+             "pref changed before we loaded a sheet?");
+
+  const bool gotGeckoSheet = aGeckoSheet && *aGeckoSheet;
+  const bool gotServoSheet = aServoSheet && *aServoSheet;
+
+  // Make sure sheets have the expected types
+  MOZ_ASSERT(!gotGeckoSheet || (*aGeckoSheet)->IsGecko());
+  MOZ_ASSERT(!gotServoSheet || (*aServoSheet)->IsServo());
+  // Make sure the URIs match
+  MOZ_ASSERT(!gotServoSheet || !gotGeckoSheet ||
+             (*aGeckoSheet)->GetSheetURI() == (*aServoSheet)->GetSheetURI(),
+             "Sheets passed should have the same URI");
+
+  nsIURI* uri;
+  if (gotGeckoSheet) {
+    uri = (*aGeckoSheet)->GetSheetURI();
+  } else if (gotServoSheet) {
+    uri = (*aServoSheet)->GetSheetURI();
+  } else {
+    return;
+  }
+
+  if (gCSSLoader_Gecko) {
+    gCSSLoader_Gecko->ObsoleteSheet(uri);
+  }
+  if (gCSSLoader_Servo) {
+    gCSSLoader_Servo->ObsoleteSheet(uri);
+  }
+  if (gotGeckoSheet) {
+    *aGeckoSheet = nullptr;
+  }
+  if (gotServoSheet) {
+    *aServoSheet = nullptr;
+  }
+}
+
+/* static */ void
+nsLayoutStylesheetCache::DependentPrefChanged(const char* aPref, void* aData)
+{
+  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_{Gecko,Servo}'s cache
+  // then setting our cached sheet pointer to null.  This will only work for
+  // sheets that are loaded lazily.
+
+#define INVALIDATE(sheet_) \
+  InvalidateSheet(gStyleCache_Gecko ? &gStyleCache_Gecko->sheet_ : nullptr, \
+                  gStyleCache_Servo ? &gStyleCache_Servo->sheet_ : nullptr);
+
+  // INVALIDATE(mUASheet);  // for layout.css.example-pref.enabled
+
+#undef INVALIDATE
+}
+
+/* static */ void
 nsLayoutStylesheetCache::InvalidatePreferenceSheets()
 {
   if (gStyleCache_Gecko) {
     gStyleCache_Gecko->mContentPreferenceSheet = nullptr;
     gStyleCache_Gecko->mChromePreferenceSheet = nullptr;
   }
   if (gStyleCache_Servo) {
     gStyleCache_Servo->mContentPreferenceSheet = nullptr;
@@ -932,20 +993,24 @@ 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");
 
-  ServoStyleSheet* servoSheet = sheet->AsServo();
-  // NB: The pref sheet never has @import rules.
-  servoSheet->ParseSheetSync(
-    nullptr, sheetText, uri, uri, nullptr, /* aLoadData = */ nullptr, 0, eCompatibility_FullStandards);
+  if (sheet->IsGecko()) {
+    MOZ_CRASH("old style system disabled");
+  } else {
+    ServoStyleSheet* servoSheet = sheet->AsServo();
+    // NB: The pref sheet never has @import rules.
+    servoSheet->ParseSheetSync(
+      nullptr, sheetText, uri, uri, nullptr, /* aLoadData = */ nullptr, 0, eCompatibility_FullStandards);
+  }
 
 #undef NS_GET_R_G_B
 }
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
 nsLayoutStylesheetCache::gStyleCache_Gecko;
 
 mozilla::StaticRefPtr<nsLayoutStylesheetCache>
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -95,16 +95,19 @@ private:
                     mozilla::css::FailureAction aFailureAction);
   void LoadSheetFile(nsIFile* aFile,
                      RefPtr<mozilla::StyleSheet>* aSheet,
                      mozilla::css::SheetParsingMode aParsingMode,
                      mozilla::css::FailureAction aFailureAction);
   void LoadSheet(nsIURI* aURI, RefPtr<mozilla::StyleSheet>* aSheet,
                  mozilla::css::SheetParsingMode aParsingMode,
                  mozilla::css::FailureAction aFailureAction);
+  static void InvalidateSheet(RefPtr<mozilla::StyleSheet>* aGeckoSheet,
+                              RefPtr<mozilla::StyleSheet>* aServoSheet);
+  static void DependentPrefChanged(const char* aPref, void* aData);
   void BuildPreferenceSheet(RefPtr<mozilla::StyleSheet>* aSheet,
                             nsPresContext* aPresContext);
 
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Gecko;
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache_Servo;
   static mozilla::StaticRefPtr<mozilla::css::Loader> gCSSLoader_Gecko;
   static mozilla::StaticRefPtr<mozilla::css::Loader> gCSSLoader_Servo;
   static mozilla::StaticRefPtr<nsIURI> gUserContentSheetURL_Gecko;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -391,16 +391,17 @@ nsStyleBorder::~nsStyleBorder()
 {
   MOZ_COUNT_DTOR(nsStyleBorder);
 }
 
 void
 nsStyleBorder::FinishStyle(nsPresContext* aPresContext, const nsStyleBorder* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   mBorderImageSource.ResolveImage(
     aPresContext, aOldStyle ? &aOldStyle->mBorderImageSource : nullptr);
 }
 
 nsMargin
 nsStyleBorder::GetImageOutset() const
 {
@@ -611,16 +612,17 @@ nsStyleList::nsStyleList(const nsStyleLi
 {
   MOZ_COUNT_CTOR(nsStyleList);
 }
 
 void
 nsStyleList::FinishStyle(nsPresContext* aPresContext, const nsStyleList* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   if (mListStyleImage && !mListStyleImage->IsResolved()) {
     mListStyleImage->Resolve(
       aPresContext, aOldStyle ? aOldStyle->mListStyleImage.get() : nullptr);
   }
   mCounterStyle.Resolve(aPresContext->CounterStyleManager());
 }
 
@@ -1298,16 +1300,17 @@ nsStyleSVGReset::Destroy(nsPresContext* 
   aContext->PresShell()->
     FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
 }
 
 void
 nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext, const nsStyleSVGReset* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
     nsStyleImage& image = mMask.mLayers[i].mImage;
     if (image.GetType() == eStyleImageType_Image) {
       // If the url of mask resource contains a reference('#'), it should be a
       // <mask-source>, mostly. For a <mask-source>, there is no need to
       // resolve this style image, since we do not depend on it to get the
       // SVG mask resource.
@@ -3365,16 +3368,17 @@ nsStyleBackground::Destroy(nsPresContext
     FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
 }
 
 void
 nsStyleBackground::FinishStyle(
   nsPresContext* aPresContext, const nsStyleBackground* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   mImage.ResolveImages(aPresContext, aOldStyle ? &aOldStyle->mImage : nullptr);
 }
 
 nsChangeHint
 nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
@@ -3744,16 +3748,17 @@ nsStyleDisplay::~nsStyleDisplay()
   MOZ_COUNT_DTOR(nsStyleDisplay);
 }
 
 void
 nsStyleDisplay::FinishStyle(
     nsPresContext* aPresContext, const nsStyleDisplay* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   if (mShapeOutside.GetType() == StyleShapeSourceType::Image) {
     const UniquePtr<nsStyleImage>& shapeImage = mShapeOutside.GetShapeImage();
     if (shapeImage) {
       // Bug 1434963: The CORS mode should instead be set when the
       // ImageValue is created, in both Gecko and Stylo. That will
       // avoid doing a mutation here.
       if (shapeImage->GetType() == eStyleImageType_Image) {
@@ -4667,16 +4672,17 @@ nsStyleUserInterface::~nsStyleUserInterf
   MOZ_COUNT_DTOR(nsStyleUserInterface);
 }
 
 void
 nsStyleUserInterface::FinishStyle(
   nsPresContext* aPresContext, const nsStyleUserInterface* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   for (size_t i = 0; i < mCursorImages.Length(); ++i) {
     nsCursorImage& cursor = mCursorImages[i];
 
     if (cursor.mImage && !cursor.mImage->IsResolved()) {
       const nsCursorImage* oldCursor =
         (aOldStyle && aOldStyle->mCursorImages.Length() > i)
         ? &aOldStyle->mCursorImages[i]