Bug 1381844: Be more explicit about the kind of style context we handle all the time. r=bholley
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 21 Jul 2017 03:22:00 +0200
changeset 419079 e8691885ec732b4e49ac660db8e939fcef1f4275
parent 419078 c9ee2503c1202a05b7a0c9899fac00ccb64e34c0
child 419080 f3058956dcd3da97e6a0d9b3b1d0266c58d55694
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1381844
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1381844: Be more explicit about the kind of style context we handle all the time. r=bholley MozReview-Commit-ID: E0mdkhU3XBz
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/KeyframeEffectReadOnly.h
dom/base/nsDOMWindowUtils.cpp
dom/canvas/CanvasRenderingContext2D.cpp
dom/smil/nsSMILCSSProperty.cpp
dom/smil/nsSMILCSSValueType.cpp
layout/base/GeckoRestyleManager.cpp
layout/base/GeckoRestyleManager.h
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFrame.cpp
layout/style/GeckoStyleContext.cpp
layout/style/GeckoStyleContext.h
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
layout/style/StyleSetHandleInlines.h
layout/style/nsAnimationManager.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
layout/xul/tree/nsTreeStyleCache.cpp
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -452,17 +452,17 @@ KeyframeEffectReadOnly::EnsureBaseStyles
   const nsTArray<AnimationProperty>& aProperties)
 {
   if (!mTarget) {
     return;
   }
 
   mBaseStyleValues.Clear();
 
-  RefPtr<nsStyleContext> cachedBaseStyleContext;
+  RefPtr<GeckoStyleContext> cachedBaseStyleContext;
 
   for (const AnimationProperty& property : aProperties) {
     for (const AnimationPropertySegment& segment : property.mSegments) {
       if (segment.HasReplaceableValues()) {
         continue;
       }
 
       EnsureBaseStyle(property.mProperty,
@@ -472,17 +472,17 @@ KeyframeEffectReadOnly::EnsureBaseStyles
     }
   }
 }
 
 void
 KeyframeEffectReadOnly::EnsureBaseStyle(
   nsCSSPropertyID aProperty,
   GeckoStyleContext* aStyleContext,
-  RefPtr<nsStyleContext>& aCachedBaseStyleContext)
+  RefPtr<GeckoStyleContext>& aCachedBaseStyleContext)
 {
   if (mBaseStyleValues.Contains(aProperty)) {
     return;
   }
 
   if (!aCachedBaseStyleContext) {
     aCachedBaseStyleContext =
       aStyleContext->PresContext()->StyleSet()->AsGecko()->
@@ -1637,75 +1637,76 @@ KeyframeEffectReadOnly::SetPerformanceWa
 void
 KeyframeEffectReadOnly::RecordFrameSizeTelemetry(uint32_t aPixelArea) {
   if (!mRecordedFrameSize) {
     Telemetry::Accumulate(Telemetry::ASYNC_ANIMATION_FRAME_SIZE, aPixelArea);
     mRecordedFrameSize = true;
   }
 }
 
-static already_AddRefed<nsStyleContext>
+static already_AddRefed<GeckoStyleContext>
 CreateStyleContextForAnimationValue(nsCSSPropertyID aProperty,
                                     const StyleAnimationValue& aValue,
-                                    nsStyleContext* aBaseStyleContext)
+                                    GeckoStyleContext* aBaseStyleContext)
 {
   MOZ_ASSERT(aBaseStyleContext,
              "CreateStyleContextForAnimationValue needs to be called "
              "with a valid nsStyleContext");
 
   RefPtr<AnimValuesStyleRule> styleRule = new AnimValuesStyleRule();
   styleRule->AddValue(aProperty, aValue);
 
   nsCOMArray<nsIStyleRule> rules;
   rules.AppendObject(styleRule);
 
   MOZ_ASSERT(aBaseStyleContext->PresContext()->StyleSet()->IsGecko(),
              "ServoStyleSet should not use StyleAnimationValue for animations");
   nsStyleSet* styleSet =
     aBaseStyleContext->PresContext()->StyleSet()->AsGecko();
 
-  RefPtr<nsStyleContext> styleContext =
+  RefPtr<GeckoStyleContext> styleContext =
     styleSet->ResolveStyleByAddingRules(aBaseStyleContext, rules);
 
   // We need to call StyleData to generate cached data for the style context.
   // Otherwise CalcStyleDifference returns no meaningful result.
-  styleContext->AsGecko()->StyleData(nsCSSProps::kSIDTable[aProperty]);
+  styleContext->StyleData(nsCSSProps::kSIDTable[aProperty]);
 
   return styleContext.forget();
 }
 
 void
 KeyframeEffectReadOnly::CalculateCumulativeChangeHint(
-  nsStyleContext *aStyleContext)
+  nsStyleContext* aStyleContext)
 {
   if (mDocument->IsStyledByServo()) {
     // FIXME (bug 1303235): Do this for Servo too
     return;
   }
   mCumulativeChangeHint = nsChangeHint(0);
 
+  auto* geckoContext = aStyleContext ? aStyleContext->AsGecko() : nullptr;
   for (const AnimationProperty& property : mProperties) {
     for (const AnimationPropertySegment& segment : property.mSegments) {
       // In case composite operation is not 'replace' or value is null,
       // we can't throttle animations which will not cause any layout changes
       // on invisible elements because we can't calculate the change hint for
       // such properties until we compose it.
       if (!segment.HasReplaceableValues()) {
         mCumulativeChangeHint = ~nsChangeHint_Hints_CanIgnoreIfNotVisible;
         return;
       }
-      RefPtr<nsStyleContext> fromContext =
+      RefPtr<GeckoStyleContext> fromContext =
         CreateStyleContextForAnimationValue(property.mProperty,
                                             segment.mFromValue.mGecko,
-                                            aStyleContext);
+                                            geckoContext);
 
-      RefPtr<nsStyleContext> toContext =
+      RefPtr<GeckoStyleContext> toContext =
         CreateStyleContextForAnimationValue(property.mProperty,
                                             segment.mToValue.mGecko,
-                                            aStyleContext);
+                                            geckoContext);
 
       uint32_t equalStructs = 0;
       uint32_t samePointerStructs = 0;
       nsChangeHint changeHint =
         fromContext->CalcStyleDifference(toContext,
                                          &equalStructs,
                                          &samePointerStructs);
 
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -375,17 +375,17 @@ protected:
 
   // If no base style is already stored for |aProperty|, resolves the base style
   // for |aProperty| using |aStyleContext| and stores it in mBaseStyleValues.
   // If |aCachedBaseStyleContext| is non-null, it will be used, otherwise the
   // base style context will be resolved and stored in
   // |aCachedBaseStyleContext|.
   void EnsureBaseStyle(nsCSSPropertyID aProperty,
                        GeckoStyleContext* aStyleContext,
-                       RefPtr<nsStyleContext>& aCachedBaseStyleContext);
+                       RefPtr<GeckoStyleContext>& aCachedBaseStyleContext);
   // Stylo version of the above function that also first checks for an additive
   // value in |aProperty|'s list of segments.
   void EnsureBaseStyle(const AnimationProperty& aProperty,
                        CSSPseudoElementType aPseudoType,
                        nsPresContext* aPresContext,
                        const ServoStyleContext* aComputedValues,
                        RefPtr<mozilla::ServoStyleContext>& aBaseComputedValues);
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2928,17 +2928,18 @@ nsDOMWindowUtils::GetUnanimatedComputedS
 
   // We will support Servo in bug 1311257.
   if (shell->StyleSet()->IsServo()) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   StyleAnimationValue computedValue;
   if (!StyleAnimationValue::ExtractComputedValue(propertyID,
-                                                 styleContext, computedValue)) {
+                                                 styleContext->AsGecko(),
+                                                 computedValue)) {
     return NS_ERROR_FAILURE;
   }
 
   // Note: ExtractComputedValue can return 'unset', 'initial', or 'inherit' in
   // its "computedValue" outparam, even though these technically aren't valid
   // computed values. (It has this behavior for discretely-animatable
   // properties, e.g. 'align-content', when these keywords are explicitly
   // specified or when there is no specified value.)  But we need to return a
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2685,45 +2685,45 @@ CreateFontDeclaration(const nsAString& a
                       bool* aOutFontChanged)
 {
   bool lineHeightChanged;
   return CreateDeclaration(aNode,
     eCSSProperty_font, aFont, aOutFontChanged,
     eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged);
 }
 
-static already_AddRefed<nsStyleContext>
+static already_AddRefed<GeckoStyleContext>
 GetFontParentStyleContext(Element* aElement, nsIPresShell* aPresShell,
                           ErrorResult& aError)
 {
   if (aElement && aElement->IsInUncomposedDoc()) {
     // Inherit from the canvas element.
     RefPtr<nsStyleContext> result =
       nsComputedDOMStyle::GetStyleContext(aElement, nullptr, aPresShell);
     if (!result) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
-    return result.forget();
+    return already_AddRefed<GeckoStyleContext>(result.forget().take()->AsGecko());
   }
 
   // otherwise inherit from default (10px sans-serif)
 
   bool changed;
   RefPtr<css::Declaration> parentRule =
     CreateFontDeclaration(NS_LITERAL_STRING("10px sans-serif"),
                           aPresShell->GetDocument(), &changed);
 
   nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
   parentRules.AppendElement(parentRule);
 
   nsStyleSet* styleSet = aPresShell->StyleSet()->GetAsGecko();
   MOZ_RELEASE_ASSERT(styleSet);
 
-  RefPtr<nsStyleContext> result =
+  RefPtr<GeckoStyleContext> result =
     styleSet->ResolveStyleForRules(nullptr, parentRules);
 
   if (!result) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   return result.forget();
 }
@@ -2735,17 +2735,17 @@ PropertyIsInheritOrInitial(Declaration* 
   // GetNormalBlock().
   const nsCSSValue* filterVal =
     aDeclaration->GetNormalBlock()->ValueFor(aProperty);
   return (!filterVal || (filterVal->GetUnit() == eCSSUnit_Unset ||
                          filterVal->GetUnit() == eCSSUnit_Inherit ||
                          filterVal->GetUnit() == eCSSUnit_Initial));
 }
 
-static already_AddRefed<nsStyleContext>
+static already_AddRefed<GeckoStyleContext>
 GetFontStyleContext(Element* aElement, const nsAString& aFont,
                     nsIPresShell* aPresShell,
                     nsAString& aOutUsedFont,
                     ErrorResult& aError)
 {
   bool fontParsedSuccessfully = false;
   RefPtr<css::Declaration> decl =
     CreateFontDeclaration(aFont, aPresShell->GetDocument(),
@@ -2761,17 +2761,17 @@ GetFontStyleContext(Element* aElement, c
   // at font-size-adjust, which the font shorthand resets to either 'none' or
   // '-moz-system-font'.
   if (PropertyIsInheritOrInitial(decl, eCSSProperty_font_size_adjust)) {
     return nullptr;
   }
 
   // have to get a parent style context for inherit-like relative
   // values (2em, bolder, etc.)
-  RefPtr<nsStyleContext> parentContext =
+  RefPtr<GeckoStyleContext> parentContext =
     GetFontParentStyleContext(aElement, aPresShell, aError);
 
   if (aError.Failed()) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   MOZ_RELEASE_ASSERT(parentContext,
@@ -2783,17 +2783,17 @@ GetFontStyleContext(Element* aElement, c
   nsTArray<nsCOMPtr<nsIStyleRule>> rules;
   rules.AppendElement(decl);
   // add a rule to prevent text zoom from affecting the style
   rules.AppendElement(new nsDisableTextZoomStyleRule);
 
   nsStyleSet* styleSet = aPresShell->StyleSet()->GetAsGecko();
   MOZ_RELEASE_ASSERT(styleSet);
 
-  RefPtr<nsStyleContext> sc =
+  RefPtr<GeckoStyleContext> sc =
     styleSet->ResolveStyleForRules(parentContext, rules);
 
   // The font getter is required to be reserialized based on what we
   // parsed (including having line-height removed).  (Older drafts of
   // the spec required font sizes be converted to pixels, but that no
   // longer seems to be required.)
   decl->GetPropertyValueByID(eCSSProperty_font, aOutUsedFont);
 
@@ -2920,20 +2920,20 @@ CreateFilterDeclaration(const nsAString&
                         bool* aOutFilterChanged)
 {
   bool dummy;
   return CreateDeclaration(aNode,
     eCSSProperty_filter, aFilter, aOutFilterChanged,
     eCSSProperty_UNKNOWN, EmptyString(), &dummy);
 }
 
-static already_AddRefed<nsStyleContext>
+static already_AddRefed<GeckoStyleContext>
 ResolveFilterStyle(const nsAString& aFilterString,
                    nsIPresShell* aPresShell,
-                   nsStyleContext* aParentContext,
+                   GeckoStyleContext* aParentContext,
                    ErrorResult& aError)
 {
   nsIDocument* document = aPresShell->GetDocument();
   bool filterChanged = false;
   RefPtr<css::Declaration> decl =
     CreateFilterDeclaration(aFilterString, document, &filterChanged);
 
   if (!filterChanged) {
@@ -2948,17 +2948,17 @@ ResolveFilterStyle(const nsAString& aFil
   }
 
   nsTArray<nsCOMPtr<nsIStyleRule>> rules;
   rules.AppendElement(decl);
 
   nsStyleSet* styleSet = aPresShell->StyleSet()->GetAsGecko();
   MOZ_RELEASE_ASSERT(styleSet);
 
-  RefPtr<nsStyleContext> sc =
+  RefPtr<GeckoStyleContext> sc =
     styleSet->ResolveStyleForRules(aParentContext, rules);
 
   return sc.forget();
 }
 
 static already_AddRefed<RawServoDeclarationBlock>
 CreateFilterDeclarationForServo(const nsAString& aFilter,
                                 nsIDocument* aDocument)
@@ -3009,24 +3009,24 @@ CanvasRenderingContext2D::ParseFilter(co
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell) {
     aError.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   nsString usedFont;
   if (presShell->StyleSet()->IsGecko()) {
-    RefPtr<nsStyleContext> parentContext =
+    RefPtr<GeckoStyleContext> parentContext =
       GetFontStyleContext(mCanvasElement, GetFont(),
                           presShell, usedFont, aError);
     if (!parentContext) {
       aError.Throw(NS_ERROR_FAILURE);
       return false;
     }
-    RefPtr<nsStyleContext> sc =
+    RefPtr<GeckoStyleContext> sc =
       ResolveFilterStyle(aString, presShell, parentContext, aError);
 
     if (!sc) {
       return false;
     }
     aFilterChain = sc->StyleEffects()->mFilters;
     return true;
   }
@@ -3956,41 +3956,29 @@ CanvasRenderingContext2D::SetFontInterna
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell) {
     aError.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   RefPtr<nsStyleContext> sc;
-  RefPtr<ServoStyleContext> computedValues;
   nsString usedFont;
-  const nsStyleFont* fontStyle;
   if (presShell->StyleSet()->IsServo()) {
-    computedValues = GetFontStyleForServo(mCanvasElement,
-                                          aFont,
-                                          presShell,
-                                          usedFont,
-                                          aError);
-    if (!computedValues) {
-      return false;
-    }
-    fontStyle = computedValues->ComputedData()->GetStyleFont();
+    sc =
+      GetFontStyleForServo(mCanvasElement, aFont, presShell, usedFont, aError);
   } else {
-    sc = GetFontStyleContext(mCanvasElement,
-                             aFont,
-                             presShell,
-                             usedFont,
-                             aError);
-    if (!sc) {
-      return false;
-    }
-    fontStyle = sc->StyleFont();
-  }
-
+    sc =
+      GetFontStyleContext(mCanvasElement, aFont, presShell, usedFont, aError);
+  }
+  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(presShell->StyleSet()->IsServo() || !fontStyle->mAllowZoom,
--- a/dom/smil/nsSMILCSSProperty.cpp
+++ b/dom/smil/nsSMILCSSProperty.cpp
@@ -70,17 +70,17 @@ nsSMILCSSProperty::GetBaseValue() const
   if (mElement->IsStyledByServo()) {
     computedValue.mServo =
       Servo_ComputedValues_ExtractAnimationValue(mBaseStyleContext->AsServo(), mPropID)
       .Consume();
     if (!computedValue.mServo) {
       return baseValue;
     }
   } else if (!StyleAnimationValue::ExtractComputedValue(mPropID,
-                                                        mBaseStyleContext,
+                                                        mBaseStyleContext->AsGecko(),
                                                         computedValue.mGecko)) {
     return baseValue;
   }
 
   baseValue =
     nsSMILCSSValueType::ValueFromAnimationValue(mPropID, mElement,
                                                 computedValue);
   return baseValue;
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -635,17 +635,17 @@ GetNonNegativePropValue(const nsAString&
   return Substring(aString, subStringBegin);
 }
 
 // Helper function to parse a string into a StyleAnimationValue
 static bool
 ValueFromStringHelper(nsCSSPropertyID aPropID,
                       Element* aTargetElement,
                       nsPresContext* aPresContext,
-                      nsStyleContext* aStyleContext,
+                      mozilla::GeckoStyleContext* aStyleContext,
                       const nsAString& aString,
                       StyleAnimationValue& aStyleAnimValue,
                       bool* aIsContextSensitive)
 {
   bool isNegative = false;
   const nsDependentSubstring subString =
     GetNonNegativePropValue(aString, aPropID, isNegative);
 
@@ -746,17 +746,17 @@ nsSMILCSSValueType::ValueFromString(nsCS
 
   RefPtr<nsStyleContext> styleContext =
     nsComputedDOMStyle::GetStyleContext(aTargetElement, nullptr,
                                         presContext->PresShell());
   if (!styleContext) {
     return;
   }
 
-  if (aTargetElement->IsStyledByServo()) {
+  if (styleContext->IsServo()) {
     ServoAnimationValues parsedValues =
       ValueFromStringHelper(aPropID, aTargetElement, presContext,
                             styleContext, aString);
     if (aIsContextSensitive) {
       // FIXME: Bug 1358955 - detect context-sensitive values and set this value
       // appropriately.
       *aIsContextSensitive = false;
     }
@@ -764,18 +764,19 @@ nsSMILCSSValueType::ValueFromString(nsCS
     if (!parsedValues.IsEmpty()) {
       sSingleton.Init(aValue);
       aValue.mU.mPtr = new ValueWrapper(aPropID, Move(parsedValues));
     }
     return;
   }
 
   StyleAnimationValue parsedValue;
-  if (ValueFromStringHelper(aPropID, aTargetElement, presContext, styleContext,
-                            aString, parsedValue, aIsContextSensitive)) {
+  if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
+                            styleContext->AsGecko(), aString, parsedValue,
+                            aIsContextSensitive)) {
     sSingleton.Init(aValue);
     aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue);
   }
 }
 
 // static
 nsSMILValue
 nsSMILCSSValueType::ValueFromAnimationValue(nsCSSPropertyID aPropID,
--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -98,16 +98,93 @@ GeckoRestyleManager::GeckoRestyleManager
   , mIsProcessingRestyles(false)
 #ifdef RESTYLE_LOGGING
   , mLoggingDepth(0)
 #endif
 {
   mPendingRestyles.Init(this);
 }
 
+static nsIFrame*
+GetNearestAncestorFrame(nsIContent* aContent)
+{
+  nsIFrame* ancestorFrame = nullptr;
+  for (nsIContent* ancestor = aContent->GetParent();
+       ancestor && !ancestorFrame;
+       ancestor = ancestor->GetParent()) {
+    ancestorFrame = ancestor->GetPrimaryFrame();
+  }
+  return ancestorFrame;
+}
+
+static nsIFrame*
+GetNextBlockInInlineSibling(nsIFrame* aFrame)
+{
+  NS_ASSERTION(!aFrame->GetPrevContinuation(),
+               "must start with the first continuation");
+  // Might we have ib-split siblings?
+  if (!(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
+    // nothing more to do here
+    return nullptr;
+  }
+
+  return aFrame->GetProperty(nsIFrame::IBSplitSibling());
+}
+
+/**
+ * Get the next continuation or similar ib-split sibling (assuming
+ * block/inline alternation), conditionally on it having the same style.
+ *
+ * Since this is used when deciding to copy the new style context, it
+ * takes as an argument the old style context to check if the style is
+ * the same.  When it is used in other contexts (i.e., where the next
+ * continuation would already have the new style context), the current
+ * style context should be passed.
+ */
+static nsIFrame*
+GetNextContinuationWithSameStyle(nsIFrame* aFrame,
+                                 nsStyleContext* aOldStyleContext,
+                                 bool* aHaveMoreContinuations = nullptr)
+{
+  // See GetPrevContinuationWithSameStyle about {ib} splits.
+
+  nsIFrame* nextContinuation = aFrame->GetNextContinuation();
+  if (!nextContinuation &&
+      (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
+    // We're the last continuation, so we have to hop back to the first
+    // before getting the frame property
+    nextContinuation =
+      aFrame->FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
+    if (nextContinuation) {
+      nextContinuation =
+        nextContinuation->GetProperty(nsIFrame::IBSplitSibling());
+    }
+  }
+
+  if (!nextContinuation) {
+    return nullptr;
+  }
+
+  NS_ASSERTION(nextContinuation->GetContent() == aFrame->GetContent(),
+               "unexpected content mismatch");
+
+  nsStyleContext* nextStyle = nextContinuation->StyleContext();
+  if (nextStyle != aOldStyleContext) {
+    NS_ASSERTION(aOldStyleContext->GetPseudo() != nextStyle->GetPseudo() ||
+                 aOldStyleContext->GetParent() != nextStyle->GetParent(),
+                 "continuations should have the same style context");
+    nextContinuation = nullptr;
+    if (aHaveMoreContinuations) {
+      *aHaveMoreContinuations = true;
+    }
+  }
+  return nextContinuation;
+}
+
+
 void
 GeckoRestyleManager::RestyleElement(Element*               aElement,
                                     nsIFrame*              aPrimaryFrame,
                                     nsChangeHint           aMinHint,
                                     RestyleTracker&        aRestyleTracker,
                                     nsRestyleHint          aRestyleHint,
                                     const RestyleHintData& aRestyleHintData)
 {
@@ -121,19 +198,19 @@ GeckoRestyleManager::RestyleElement(Elem
   }
   NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aElement,
                "frame/content mismatch");
 
   // If we're restyling the root element and there are 'rem' units in
   // use, handle dynamic changes to the definition of a 'rem' here.
   if (PresContext()->UsesRootEMUnits() && aPrimaryFrame &&
       !mInRebuildAllStyleData) {
-    nsStyleContext* oldContext = aPrimaryFrame->StyleContext();
+    GeckoStyleContext* oldContext = aPrimaryFrame->StyleContext()->AsGecko();
     if (!oldContext->GetParent()) { // check that we're the root element
-      RefPtr<nsStyleContext> newContext = StyleSet()->
+      RefPtr<GeckoStyleContext> newContext = StyleSet()->
         ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
       if (oldContext->StyleFont()->mFont.size !=
           newContext->StyleFont()->mFont.size) {
         // The basis for 'rem' units has changed.
         mRebuildAllRestyleHint |= aRestyleHint;
         if (aRestyleHint & eRestyle_SomeDescendants) {
           mRebuildAllRestyleHint |= eRestyle_Subtree;
         }
@@ -159,17 +236,17 @@ GeckoRestyleManager::RestyleElement(Elem
     // we have *some* restyling for this frame.  This means we'll
     // potentially get ahead of ourselves in that case, but not as much
     // as we would if we didn't check the restyle hint.
     nsStyleContext* newContext =
       FrameConstructor()->MaybeRecreateFramesForElement(aElement);
     if (newContext &&
         newContext->StyleDisplay()->mDisplay == StyleDisplay::Contents) {
       // Style change for a display:contents node that did not recreate frames.
-      ComputeAndProcessStyleChange(newContext, aElement, aMinHint,
+      ComputeAndProcessStyleChange(newContext->AsGecko(), aElement, aMinHint,
                                    aRestyleTracker, aRestyleHint,
                                    aRestyleHintData);
     }
   }
 }
 
 GeckoRestyleManager::ReframingStyleContexts
                    ::ReframingStyleContexts(
@@ -669,27 +746,27 @@ GeckoRestyleManager::PostRebuildAllStyle
   PostRestyleEventInternal();
 }
 
 // aContent must be the content for the frame in question, which may be
 // :before/:after content
 /* static */ bool
 GeckoRestyleManager::TryInitiatingTransition(nsPresContext* aPresContext,
                                              nsIContent* aContent,
-                                             nsStyleContext* aOldStyleContext,
-                                             RefPtr<nsStyleContext>*
+                                             GeckoStyleContext* aOldStyleContext,
+                                             RefPtr<GeckoStyleContext>*
                                                aNewStyleContext /* inout */)
 {
   if (!aContent || !aContent->IsElement()) {
     return false;
   }
 
   // Notify the transition manager.  If it starts a transition,
   // it might modify the new style context.
-  RefPtr<nsStyleContext> sc = *aNewStyleContext;
+  RefPtr<GeckoStyleContext> sc = *aNewStyleContext;
   aPresContext->TransitionManager()->StyleContextChanged(
     aContent->AsElement(), aOldStyleContext, aNewStyleContext);
   return *aNewStyleContext != sc;
 }
 
 static dom::Element*
 ElementForStyleContext(nsIContent* aParentContent,
                        nsIFrame* aFrame,
@@ -871,21 +948,22 @@ GeckoRestyleManager::ReparentStyleContex
   } else if (frameType == LayoutFrameType::Backdrop) {
     // Style context of backdrop frame has no parent style context, and
     // thus we do not need to reparent it.
     return NS_OK;
   }
 
   // DO NOT verify the style tree before reparenting.  The frame
   // tree has already been changed, so this check would just fail.
-  nsStyleContext* oldContext = aFrame->StyleContext();
-
-  RefPtr<nsStyleContext> newContext;
+  GeckoStyleContext* oldContext = aFrame->StyleContext()->AsGecko();
+
+  RefPtr<GeckoStyleContext> newContext;
   nsIFrame* providerFrame;
-  nsStyleContext* newParentContext = aFrame->GetParentStyleContext(&providerFrame);
+  nsStyleContext* newParentContext =
+    aFrame->GetParentStyleContext(&providerFrame);
   bool isChild = providerFrame && providerFrame->GetParent() == aFrame;
   nsIFrame* providerChild = nullptr;
   if (isChild) {
     ReparentStyleContext(providerFrame);
     // Get the style context again after ReparentStyleContext() which might have
     // changed it.
     newParentContext = providerFrame->StyleContext();
     providerChild = providerFrame;
@@ -934,36 +1012,36 @@ GeckoRestyleManager::ReparentStyleContex
   // XXX need to do something here to produce the correct style context for
   // an IB split whose first inline part is inside a first-line frame.
   // Currently the first IB anonymous block's style context takes the first
   // part's style context as parent, which is wrong since first-line style
   // should not apply to the anonymous block.
 
   nsIFrame* prevContinuation =
     GetPrevContinuationWithPossiblySameStyle(aFrame);
-  nsStyleContext* prevContinuationContext;
+  GeckoStyleContext* prevContinuationContext;
   bool copyFromContinuation =
     prevContinuation &&
-    (prevContinuationContext = prevContinuation->StyleContext())
+    (prevContinuationContext = prevContinuation->StyleContext()->AsGecko())
       ->GetPseudo() == oldContext->GetPseudo() &&
      prevContinuationContext->GetParent() == newParentContext;
   if (copyFromContinuation) {
     // Just use the style context from the frame's previous
     // continuation (see assertion about aFrame->GetNextContinuation()
     // above, which we would have previously hit for aFrame's previous
     // continuation).
     newContext = prevContinuationContext;
   } else {
     nsIFrame* parentFrame = aFrame->GetParent();
     Element* element =
       ElementForStyleContext(parentFrame ? parentFrame->GetContent() : nullptr,
                              aFrame,
                              oldContext->GetPseudoType());
-    newContext = StyleSet()->
-                   ReparentStyleContext(oldContext, newParentContext, element);
+    newContext = StyleSet()->ReparentStyleContext(
+        oldContext, newParentContext->AsGecko(), element);
   }
 
   if (newContext) {
     if (newContext != oldContext) {
       // We probably don't want to initiate transitions from
       // ReparentStyleContext, since we call it during frame
       // construction rather than in response to dynamic changes.
       // Also see the comment at the start of
@@ -1018,19 +1096,19 @@ GeckoRestyleManager::ReparentStyleContex
         }
       }
 
       // do additional contexts
       int32_t contextIndex = 0;
       for (nsStyleContext* oldExtraContext;
            (oldExtraContext = aFrame->GetAdditionalStyleContext(contextIndex));
            ++contextIndex) {
-        RefPtr<nsStyleContext> newExtraContext;
+        RefPtr<GeckoStyleContext> newExtraContext;
         newExtraContext = StyleSet()->
-                            ReparentStyleContext(oldExtraContext,
+                            ReparentStyleContext(oldExtraContext->AsGecko(),
                                                  newContext, nullptr);
         if (newExtraContext) {
           if (newExtraContext != oldExtraContext) {
             // Ensure the new context ends up resolving all the structs the old
             // context resolved.
             newContext->AsGecko()->EnsureSameStructsCached(oldContext);
           }
 
@@ -1052,17 +1130,17 @@ ElementRestyler::ElementRestyler(nsPresC
                                  nsChangeHint aHintsHandledByAncestors,
                                  RestyleTracker& aRestyleTracker,
                                  nsTArray<nsCSSSelector*>&
                                    aSelectorsForDescendants,
                                  TreeMatchContext& aTreeMatchContext,
                                  nsTArray<nsIContent*>&
                                    aVisibleKidsOfHiddenElement,
                                  nsTArray<ContextToClear>& aContextsToClear,
-                                 nsTArray<RefPtr<nsStyleContext>>&
+                                 nsTArray<RefPtr<GeckoStyleContext>>&
                                    aSwappedStructOwners)
   : mPresContext(aPresContext)
   , mFrame(aFrame)
   , mParentContent(nullptr)
     // XXXldb Why does it make sense to use aParentContent?  (See
     // comment above assertion at start of ElementRestyler::Restyle.)
   , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mChangeList(aChangeList)
@@ -1188,17 +1266,17 @@ ElementRestyler::ElementRestyler(nsPresC
                                  nsStyleChangeList* aChangeList,
                                  nsChangeHint aHintsHandledByAncestors,
                                  RestyleTracker& aRestyleTracker,
                                  nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                                  TreeMatchContext& aTreeMatchContext,
                                  nsTArray<nsIContent*>&
                                    aVisibleKidsOfHiddenElement,
                                  nsTArray<ContextToClear>& aContextsToClear,
-                                 nsTArray<RefPtr<nsStyleContext>>&
+                                 nsTArray<RefPtr<GeckoStyleContext>>&
                                    aSwappedStructOwners)
   : mPresContext(aPresContext)
   , mFrame(nullptr)
   , mParentContent(nullptr)
   , mContent(aContent)
   , mChangeList(aChangeList)
   , mHintsHandledByAncestors(aHintsHandledByAncestors)
   , mHintsHandledBySelf(nsChangeHint(0))
@@ -1217,18 +1295,18 @@ ElementRestyler::ElementRestyler(nsPresC
 #endif
 {
   MOZ_ASSERT(!(mHintsHandledByAncestors & nsChangeHint_ReconstructFrame),
              "why restyle descendants if we are reconstructing the frame for "
              "an ancestor?");
 }
 
 void
-ElementRestyler::CaptureChange(nsStyleContext* aOldContext,
-                               nsStyleContext* aNewContext,
+ElementRestyler::CaptureChange(GeckoStyleContext* aOldContext,
+                               GeckoStyleContext* aNewContext,
                                nsChangeHint aChangeToAssume,
                                uint32_t* aEqualStructs,
                                uint32_t* aSamePointerStructs)
 {
   static_assert(nsStyleStructID_Length <= 32,
                 "aEqualStructs is not big enough");
 
   // Check some invariants about replacing one style context with another.
@@ -1375,17 +1453,17 @@ ElementRestyler::ConditionallyRestyleCon
   MOZ_ASSERT(aFrame->GetContent()->IsElement());
   MOZ_ASSERT(!aFrame->GetContent()->IsStyledByServo());
 
   if (aFrame->GetContent()->HasFlag(mRestyleTracker.RootBit())) {
     aRestyleRoot = aFrame->GetContent()->AsElement();
   }
 
   for (nsIFrame* f = aFrame; f;
-       f = GeckoRestyleManager::GetNextContinuationWithSameStyle(f, f->StyleContext())) {
+       f = GetNextContinuationWithSameStyle(f, f->StyleContext())) {
     nsIFrame::ChildListIterator lists(f);
     for (; !lists.IsDone(); lists.Next()) {
       for (nsIFrame* child : lists.CurrentList()) {
         // Out-of-flows are reached through their placeholders.  Continuations
         // and block-in-inline splits are reached through those chains.
         if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
             !GetPrevContinuationWithSameStyle(child)) {
           // only do frames that are in flow
@@ -1581,18 +1659,18 @@ ElementRestyler::MustCheckUndisplayedCon
 /**
  * Helper for MoveStyleContextsForChildren, below.  Appends the style
  * contexts to be moved to mFrame's current (new) style context to
  * aContextsToMove.
  */
 bool
 ElementRestyler::MoveStyleContextsForContentChildren(
     nsIFrame* aParent,
-    nsStyleContext* aOldContext,
-    nsTArray<nsStyleContext*>& aContextsToMove)
+    GeckoStyleContext* aOldContext,
+    nsTArray<GeckoStyleContext*>& aContextsToMove)
 {
   nsIFrame::ChildListIterator lists(aParent);
   for (; !lists.IsDone(); lists.Next()) {
     for (nsIFrame* child : lists.CurrentList()) {
       // Bail out if we have out-of-flow frames.
       // FIXME: It might be safe to just continue here instead of bailing out.
       if (child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
         return false;
@@ -1600,17 +1678,17 @@ ElementRestyler::MoveStyleContextsForCon
       if (GetPrevContinuationWithSameStyle(child)) {
         continue;
       }
       // Bail out if we have placeholder frames.
       // FIXME: It is probably safe to just continue here instead of bailing out.
       if (child->IsPlaceholderFrame()) {
         return false;
       }
-      nsStyleContext* sc = child->StyleContext();
+      GeckoStyleContext* sc = child->StyleContext()->AsGecko();
       if (sc->GetParent() != aOldContext) {
         return false;
       }
       LayoutFrameType type = child->Type();
       if (type == LayoutFrameType::Letter || type == LayoutFrameType::Line) {
         return false;
       }
       if (sc->HasChildThatUsesGrandancestorStyle()) {
@@ -1634,50 +1712,50 @@ ElementRestyler::MoveStyleContextsForCon
  * context.
  *
  * False is returned if it encounters any conditions on the child elements'
  * frames and style contexts that means it is impossible to move a
  * style context.  If false is returned, no style contexts will have been
  * moved.
  */
 bool
-ElementRestyler::MoveStyleContextsForChildren(nsStyleContext* aOldContext)
+ElementRestyler::MoveStyleContextsForChildren(GeckoStyleContext* aOldContext)
 {
   // Bail out if there are undisplayed or display:contents children.
   // FIXME: We could get this to work if we need to.
   nsIContent* undisplayedParent;
   if (MustCheckUndisplayedContent(mFrame, undisplayedParent)) {
     nsCSSFrameConstructor* fc = mPresContext->FrameConstructor();
     if (fc->GetAllUndisplayedContentIn(undisplayedParent) ||
         fc->GetAllDisplayContentsIn(undisplayedParent)) {
       return false;
     }
   }
 
-  nsTArray<nsStyleContext*> contextsToMove;
+  nsTArray<GeckoStyleContext*> contextsToMove;
 
   MOZ_ASSERT(!MustReframeForBeforePseudo(),
              "shouldn't need to reframe ::before as we would have had "
              "eRestyle_Subtree and wouldn't get in here");
 
   DebugOnly<nsIFrame*> lastContinuation;
   for (nsIFrame* f = mFrame; f;
-       f = GeckoRestyleManager::GetNextContinuationWithSameStyle(f, f->StyleContext())) {
+       f = GetNextContinuationWithSameStyle(f, f->StyleContext())) {
     lastContinuation = f;
     if (!MoveStyleContextsForContentChildren(f, aOldContext, contextsToMove)) {
       return false;
     }
   }
 
   MOZ_ASSERT(!MustReframeForAfterPseudo(lastContinuation),
              "shouldn't need to reframe ::after as we would have had "
              "eRestyle_Subtree and wouldn't get in here");
 
-  nsStyleContext* newParent = mFrame->StyleContext();
-  for (nsStyleContext* child : contextsToMove) {
+  GeckoStyleContext* newParent = mFrame->StyleContext()->AsGecko();
+  for (GeckoStyleContext* child : contextsToMove) {
     // We can have duplicate entries in contextsToMove, so only move
     // each style context once.
     if (child->GetParent() != newParent) {
       child->MoveTo(newParent);
     }
   }
 
   return true;
@@ -1812,18 +1890,18 @@ ElementRestyler::Restyle(nsRestyleHint a
 
     if (thisResult > result) {
       // We take the highest RestyleResult value when working out what to do
       // with this frame and its descendants.  Higher RestyleResult values
       // represent a superset of the work done by lower values.
       result = thisResult;
     }
 
-    f = GeckoRestyleManager::GetNextContinuationWithSameStyle(
-            f, oldContext, &haveMoreContinuations);
+    f = GetNextContinuationWithSameStyle(
+          f, oldContext, &haveMoreContinuations);
   }
 
   // Some changes to animations don't affect the computed style and yet still
   // require the layer to be updated. For example, pausing an animation via
   // the Web Animations API won't affect an element's style but still
   // requires to update the animation on the layer.
   //
   // Although we only expect this code path to be called when computed style
@@ -1842,17 +1920,18 @@ ElementRestyler::Restyle(nsRestyleHint a
                                              hintToRestore, nsChangeHint(0));
   }
 
   if (result == RestyleResult::eStop) {
     MOZ_ASSERT(mFrame->StyleContext() == oldContext,
                "frame should have been left with its old style context");
 
     nsIFrame* unused;
-    nsStyleContext* newParent = mFrame->GetParentStyleContext(&unused);
+    GeckoStyleContext* newParent =
+      mFrame->GetParentStyleContext(&unused)->AsGecko();
     if (oldContext->GetParent() != newParent) {
       // If we received RestyleResult::eStop, then the old style context was
       // left on mFrame.  Since we ended up restyling our parent, change
       // this old style context to point to its new parent.
       LOG_RESTYLE("moving style context %p from old parent %p to new parent %p",
                   oldContext.get(), oldContext->GetParent(), newParent);
       // We keep strong references to the new parent around until the end
       // of the restyle, in case:
@@ -1958,17 +2037,17 @@ ElementRestyler::Restyle(nsRestyleHint a
     // Much of the time we will not get in here; we do for example when the
     // style context is shared with a later IB split sibling (which we won't
     // restyle until a bit later) or if other code is holding a strong reference
     // to the style context (as is done by nsTransformedTextRun objects, which
     // can be referenced by a text frame's mTextRun longer than the frame's
     // mStyleContext).
     //
     // Also, we don't want this style context to get any more uses by being
-    // returned from nsStyleContext::FindChildWithRules, so we add the
+    // returned from GeckoStyleContext::FindChildWithRules, so we add the
     // NS_STYLE_INELIGIBLE_FOR_SHARING bit to it.
     oldContext->SetIneligibleForSharing();
 
     ContextToClear* toClear = mContextsToClear.AppendElement();
     toClear->mStyleContext = Move(oldContext);
     toClear->mStructs = swappedStructs;
   }
 
@@ -2033,33 +2112,33 @@ ElementRestyler::ComputeRestyleResultFro
 
   // Some style computations depend not on the parent's style, but a grandparent
   // or one the grandparent's ancestors.  An example is an explicit 'inherit'
   // value for align-self, where if the parent frame's value for the property is
   // 'auto' we end up inheriting the computed value from the grandparent.  We
   // can't stop the restyling process on this frame (the one with 'auto', in
   // this example), as the grandparent's computed value might have changed
   // and we need to recompute the child's 'inherit' to that new value.
-  nsStyleContext* oldContext = aSelf->StyleContext();
+  GeckoStyleContext* oldContext = aSelf->StyleContext()->AsGecko();
   if (oldContext->HasChildThatUsesGrandancestorStyle()) {
     LOG_RESTYLE_CONTINUE("the old context uses grandancestor style");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
   // We ignore all situations that involve :visited style.
   if (oldContext->GetStyleIfVisited()) {
     LOG_RESTYLE_CONTINUE("the old style context has StyleIfVisited");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
-  nsStyleContext* parentContext = oldContext->GetParent();
+  GeckoStyleContext* parentContext = oldContext->GetParent();
   if (parentContext && parentContext->GetStyleIfVisited()) {
     LOG_RESTYLE_CONTINUE("the old style context's parent has StyleIfVisited");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
   // We also ignore frames for pseudos, as their style contexts have
@@ -2097,17 +2176,17 @@ ElementRestyler::ComputeRestyleResultFro
       // continue to check them, in case we set aCanStopWithStyleChange to
       // false.
     }
   }
 }
 
 void
 ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
-                                                    nsStyleContext* aNewContext,
+                                                    GeckoStyleContext* aNewContext,
                                                     RestyleResult& aRestyleResult,
                                                     bool& aCanStopWithStyleChange)
 {
   // If we've already determined that we must continue styling, we don't
   // need to check anything.
   if (aRestyleResult == RestyleResult::eContinue && !aCanStopWithStyleChange) {
     return;
   }
@@ -2120,17 +2199,17 @@ ElementRestyler::ComputeRestyleResultFro
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
   // If link-related information has changed, or the pseudo for the frame has
   // changed, or the new style context points to a different rule node, we can't
   // leave the old style context on the frame.
-  nsStyleContext* oldContext = aSelf->StyleContext();
+  GeckoStyleContext* oldContext = aSelf->StyleContext()->AsGecko();
   if (oldContext->IsLinkContext() != aNewContext->IsLinkContext() ||
       oldContext->RelevantLinkVisited() != aNewContext->RelevantLinkVisited() ||
       oldContext->GetPseudo() != aNewContext->GetPseudo() ||
       oldContext->GetPseudoType() != aNewContext->GetPseudoType()) {
     LOG_RESTYLE_CONTINUE("the old and new style contexts have different link/"
                          "visited/pseudo");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
@@ -2374,75 +2453,76 @@ ElementRestyler::RestyleSelf(nsIFrame* a
     canStopWithStyleChange = false;
   }
 
   // Look at the frame and its current style context for conditions
   // that would change our RestyleResult.
   ComputeRestyleResultFromFrame(aSelf, result, canStopWithStyleChange);
 
   nsChangeHint assumeDifferenceHint = nsChangeHint(0);
-  RefPtr<nsStyleContext> oldContext = aSelf->StyleContext();
+  RefPtr<GeckoStyleContext> oldContext = aSelf->StyleContext()->AsGecko();
   nsStyleSet* styleSet = StyleSet();
 
 #ifdef ACCESSIBILITY
   mWasFrameVisible = nsIPresShell::IsAccessibilityActive() ?
     oldContext->StyleVisibility()->IsVisible() : false;
 #endif
 
   nsIAtom* const pseudoTag = oldContext->GetPseudo();
   const CSSPseudoElementType pseudoType = oldContext->GetPseudoType();
 
   // Get the frame providing the parent style context.  If it is a
   // child, then resolve the provider first.
   nsIFrame* providerFrame;
-  nsStyleContext* parentContext = aSelf->GetParentStyleContext(&providerFrame);
+  nsStyleContext* parentContext_ = aSelf->GetParentStyleContext(&providerFrame);
   bool isChild = providerFrame && providerFrame->GetParent() == aSelf;
   if (isChild) {
     MOZ_ASSERT(providerFrame->GetContent() == aSelf->GetContent(),
                "Postcondition for GetParentStyleContext() violated. "
                "That means we need to add the current element to the "
                "ancestor filter.");
 
     // resolve the provider here (before aSelf below).
     LOG_RESTYLE("resolving child provider frame");
 
     // assumeDifferenceHint forces the parent's change to be also
     // applied to this frame, no matter what
-    // nsStyleContext::CalcStyleDifference says. CalcStyleDifference
+    // GeckoStyleContext::CalcStyleDifference says. CalcStyleDifference
     // can't be trusted because it assumes any changes to the parent
     // style context provider will be automatically propagated to
     // the frame(s) with child style contexts.
 
     ElementRestyler providerRestyler(PARENT_CONTEXT_FROM_CHILD_FRAME,
                                      *this, providerFrame);
     providerRestyler.Restyle(aRestyleHint);
     assumeDifferenceHint = providerRestyler.HintsHandledForFrame();
 
     // The provider's new context becomes the parent context of
     // aSelf's context.
-    parentContext = providerFrame->StyleContext();
+    parentContext_ = providerFrame->StyleContext();
     // Set |mResolvedChild| so we don't bother resolving the
     // provider again.
     mResolvedChild = providerFrame;
     LOG_RESTYLE_CONTINUE("we had a provider frame");
     // Continue restyling past the odd style context inheritance.
     result = RestyleResult::eContinue;
     canStopWithStyleChange = false;
   }
 
+  auto* parentContext = parentContext_ ? parentContext_->AsGecko() : nullptr;
   LOG_RESTYLE("parentContext = %p", parentContext);
 
   // do primary context
-  RefPtr<nsStyleContext> newContext;
+  RefPtr<GeckoStyleContext> newContext;
   nsIFrame* prevContinuation =
     GetPrevContinuationWithPossiblySameStyle(aSelf);
-  nsStyleContext* prevContinuationContext;
+  GeckoStyleContext* prevContinuationContext;
   bool copyFromContinuation =
     prevContinuation &&
-    (prevContinuationContext = prevContinuation->StyleContext())
+    (prevContinuationContext = prevContinuation->StyleContext()->AsGecko())
       ->GetPseudo() == oldContext->GetPseudo() &&
      prevContinuationContext->GetParent() == parentContext;
   if (copyFromContinuation) {
     // Just use the style context from the frame's previous
     // continuation.
     LOG_RESTYLE("using previous continuation's context");
     newContext = prevContinuationContext;
   } else if (pseudoTag == nsCSSAnonBoxes::mozText) {
@@ -2507,17 +2587,17 @@ ElementRestyler::RestyleSelf(nsIFrame* a
                                       nsChangeHint_ReconstructFrame);
             // We're reframing anyway; just keep the same context
             newContext = oldContext;
 #ifdef DEBUG
             // oldContext's parent might have had its style structs swapped out
             // with parentContext, so to avoid any assertions that might
             // otherwise trigger in oldContext's parent's destructor, we set a
             // flag on oldContext to skip it and its descendants in
-            // nsStyleContext::AssertStructsNotUsedElsewhere.
+            // GeckoStyleContext::AssertStructsNotUsedElsewhere.
             if (oldContext->GetParent() != parentContext) {
               oldContext->AddStyleBit(NS_STYLE_IS_GOING_AWAY);
             }
 #endif
           }
         } else {
           // Don't expect XUL tree stuff here, since it needs a comparator and
           // all.
@@ -2797,48 +2877,48 @@ ElementRestyler::RestyleSelf(nsIFrame* a
   // XXXbz might be able to avoid selector matching here in some
   // cases; won't worry about it for now.
   int32_t contextIndex = 0;
   for (nsStyleContext* oldExtraContext;
        (oldExtraContext = aSelf->GetAdditionalStyleContext(contextIndex));
        ++contextIndex) {
     LOG_RESTYLE("extra context %d", contextIndex);
     LOG_RESTYLE_INDENT();
-    RefPtr<nsStyleContext> newExtraContext;
+    RefPtr<GeckoStyleContext> newExtraContext;
     nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
     const CSSPseudoElementType extraPseudoType =
       oldExtraContext->GetPseudoType();
     NS_ASSERTION(extraPseudoTag &&
                  !nsCSSAnonBoxes::IsNonElement(extraPseudoTag),
                  "extra style context is not pseudo element");
     Element* element =
       (extraPseudoType != CSSPseudoElementType::InheritingAnonBox &&
        extraPseudoType != CSSPseudoElementType::NonInheritingAnonBox)
       ? mContent->AsElement() : nullptr;
     if (extraPseudoType == CSSPseudoElementType::NonInheritingAnonBox) {
       newExtraContext =
         styleSet->ResolveNonInheritingAnonymousBoxStyle(extraPseudoTag);
     } else if (!MustRestyleSelf(aRestyleHint, element)) {
       if (CanReparentStyleContext(aRestyleHint)) {
         newExtraContext =
-          styleSet->ReparentStyleContext(oldExtraContext, newContext, element);
+          styleSet->ReparentStyleContext(oldExtraContext->AsGecko(), newContext, element);
       } else {
         // Use ResolveStyleWithReplacement as a substitute for
         // ReparentStyleContext that rebuilds the path in the rule tree
         // rather than reusing the rule node, as we need to do during a
         // rule tree reconstruct.
         Element* pseudoElement =
           PseudoElementForStyleContext(aSelf, extraPseudoType);
         MOZ_ASSERT(!element || element != pseudoElement,
                    "pseudo-element for selector matching should be "
                    "the anonymous content node that we create, "
                    "not the real element");
         newExtraContext =
           styleSet->ResolveStyleWithReplacement(element, pseudoElement,
-                                                newContext, oldExtraContext,
+                                                newContext, oldExtraContext->AsGecko(),
                                                 nsRestyleHint(0));
       }
     } else if (extraPseudoType == CSSPseudoElementType::InheritingAnonBox) {
       newExtraContext = styleSet->
         ResolveInheritingAnonymousBoxStyle(extraPseudoTag, newContext);
     } else {
       // Don't expect XUL tree stuff here, since it needs a comparator and
       // all.
@@ -2852,17 +2932,17 @@ ElementRestyler::RestyleSelf(nsIFrame* a
 
     MOZ_ASSERT(newExtraContext);
 
     LOG_RESTYLE("newExtraContext = %p", newExtraContext.get());
 
     if (oldExtraContext != newExtraContext) {
       uint32_t equalStructs;
       uint32_t samePointerStructs;
-      CaptureChange(oldExtraContext, newExtraContext, assumeDifferenceHint,
+      CaptureChange(oldExtraContext->AsGecko(), newExtraContext, assumeDifferenceHint,
                     &equalStructs, &samePointerStructs);
       if (!(mHintsHandledBySelf & nsChangeHint_ReconstructFrame)) {
         LOG_RESTYLE("setting new extra style context");
         aSelf->SetAdditionalStyleContext(contextIndex, newExtraContext);
       } else {
         LOG_RESTYLE("not setting new extra style context, since we'll reframe");
       }
     }
@@ -2916,17 +2996,17 @@ ElementRestyler::RestyleChildren(nsResty
   // kids would use mFrame->StyleContext(), which is out of date if
   // mHintsHandledBySelf has a ReconstructFrame hint; doing this could
   // trigger assertions about mismatched rule trees.
   nsIFrame* lastContinuation;
   if (!(mHintsHandledBySelf & nsChangeHint_ReconstructFrame)) {
     InitializeAccessibilityNotifications(mFrame->StyleContext());
 
     for (nsIFrame* f = mFrame; f;
-         f = GeckoRestyleManager::GetNextContinuationWithSameStyle(f, f->StyleContext())) {
+         f = GetNextContinuationWithSameStyle(f, f->StyleContext())) {
       lastContinuation = f;
       RestyleContentChildren(f, aChildRestyleHint);
     }
 
     SendAccessibilityNotifications();
   }
 
   // Check whether we might need to create a new ::after frame.
@@ -2935,17 +3015,17 @@ ElementRestyler::RestyleChildren(nsResty
       mightReframePseudos) {
     MaybeReframeForAfterPseudo(lastContinuation);
   }
 }
 
 void
 ElementRestyler::RestyleChildrenOfDisplayContentsElement(
   nsIFrame*              aParentFrame,
-  nsStyleContext*        aNewContext,
+  GeckoStyleContext*        aNewContext,
   nsChangeHint           aMinHint,
   RestyleTracker&        aRestyleTracker,
   nsRestyleHint          aRestyleHint,
   const RestyleHintData& aRestyleHintData)
 {
   MOZ_ASSERT(!(mHintsHandledBySelf & nsChangeHint_ReconstructFrame),
              "why call me?");
 
@@ -2992,17 +3072,17 @@ void
 ElementRestyler::ComputeStyleChangeFor(nsIFrame*          aFrame,
                                        nsStyleChangeList* aChangeList,
                                        nsChangeHint       aMinChange,
                                        RestyleTracker&    aRestyleTracker,
                                        nsRestyleHint      aRestyleHint,
                                        const RestyleHintData& aRestyleHintData,
                                        nsTArray<ContextToClear>&
                                          aContextsToClear,
-                                       nsTArray<RefPtr<nsStyleContext>>&
+                                       nsTArray<RefPtr<GeckoStyleContext>>&
                                          aSwappedStructOwners)
 {
   AUTO_PROFILER_LABEL("ElementRestyler::ComputeStyleChangeFor", CSS);
 
   nsIContent* content = aFrame->GetContent();
   if (aMinChange) {
     aChangeList->AppendChange(aFrame, content, aMinChange);
   }
@@ -3030,18 +3110,17 @@ ElementRestyler::ComputeStyleChangeFor(n
     content ? content->GetParentElementCrossingShadowRoot() : nullptr;
   treeMatchContext.InitAncestors(parent);
   nsTArray<nsCSSSelector*> selectorsForDescendants;
   selectorsForDescendants.AppendElements(
       aRestyleHintData.mSelectorsForDescendants);
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   nsIFrame* nextIBSibling;
   for (nsIFrame* ibSibling = aFrame; ibSibling; ibSibling = nextIBSibling) {
-    nextIBSibling =
-      GeckoRestyleManager::GetNextBlockInInlineSibling(ibSibling);
+    nextIBSibling = GetNextBlockInInlineSibling(ibSibling);
 
     if (nextIBSibling) {
       // Don't allow some ib-split siblings to be processed with
       // RestyleResult::eStopWithStyleChange and others not.
       aRestyleHint |= eRestyle_Force;
     }
 
     // Outer loop over ib-split siblings
@@ -3077,43 +3156,43 @@ ElementRestyler::ComputeStyleChangeFor(n
 // The structure of this method parallels ConditionallyRestyleUndisplayedDescendants.
 // If you update this method, you probably want to update that one too.
 void
 ElementRestyler::RestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint)
 {
   nsIContent* undisplayedParent;
   if (MustCheckUndisplayedContent(mFrame, undisplayedParent)) {
     DoRestyleUndisplayedDescendants(aChildRestyleHint, undisplayedParent,
-                                    mFrame->StyleContext());
+                                    mFrame->StyleContext()->AsGecko());
   }
 }
 
 // The structure of this method parallels DoConditionallyRestyleUndisplayedDescendants.
 // If you update this method, you probably want to update that one too.
 void
 ElementRestyler::DoRestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint,
                                                  nsIContent* aParent,
-                                                 nsStyleContext* aParentContext)
+                                                 GeckoStyleContext* aParentContext)
 {
   nsCSSFrameConstructor* fc = mPresContext->FrameConstructor();
   UndisplayedNode* nodes = fc->GetAllUndisplayedContentIn(aParent);
   RestyleUndisplayedNodes(aChildRestyleHint, nodes, aParent,
                           aParentContext, StyleDisplay::None);
   nodes = fc->GetAllDisplayContentsIn(aParent);
   RestyleUndisplayedNodes(aChildRestyleHint, nodes, aParent,
                           aParentContext, StyleDisplay::Contents);
 }
 
 // The structure of this method parallels ConditionallyRestyleUndisplayedNodes.
 // If you update this method, you probably want to update that one too.
 void
 ElementRestyler::RestyleUndisplayedNodes(nsRestyleHint      aChildRestyleHint,
                                          UndisplayedNode*   aUndisplayed,
                                          nsIContent*        aUndisplayedParent,
-                                         nsStyleContext*    aParentContext,
+                                         GeckoStyleContext*    aParentContext,
                                          const StyleDisplay aDisplay)
 {
   nsIContent* undisplayedParent = aUndisplayedParent;
   UndisplayedNode* undisplayed = aUndisplayed;
   TreeMatchContext::AutoAncestorPusher pusher(&mTreeMatchContext);
   if (undisplayed) {
     pusher.PushAncestorAndStyleScope(undisplayedParent);
   }
@@ -3141,121 +3220,121 @@ ElementRestyler::RestyleUndisplayedNodes
     nsRestyleHint thisChildHint = aChildRestyleHint;
     nsAutoPtr<RestyleTracker::RestyleData> undisplayedRestyleData;
     Element* element = undisplayed->mContent->AsElement();
     if (mRestyleTracker.GetRestyleData(element,
                                        undisplayedRestyleData)) {
       thisChildHint =
         nsRestyleHint(thisChildHint | undisplayedRestyleData->mRestyleHint);
     }
-    RefPtr<nsStyleContext> undisplayedContext;
+    RefPtr<GeckoStyleContext> undisplayedContext;
     nsStyleSet* styleSet = StyleSet();
     if (MustRestyleSelf(thisChildHint, element)) {
       undisplayedContext =
         styleSet->ResolveStyleFor(element, aParentContext, mTreeMatchContext);
     } else if (CanReparentStyleContext(thisChildHint)) {
       undisplayedContext =
-        styleSet->ReparentStyleContext(undisplayed->mStyle,
+        styleSet->ReparentStyleContext(undisplayed->mStyle->AsGecko(),
                                        aParentContext,
                                        element);
     } else {
       // Use ResolveStyleWithReplacement either for actual
       // replacements, or as a substitute for ReparentStyleContext
       // that rebuilds the path in the rule tree rather than reusing
       // the rule node, as we need to do during a rule tree
       // reconstruct.
       nsRestyleHint rshint = thisChildHint & ~eRestyle_SomeDescendants;
       undisplayedContext =
         styleSet->ResolveStyleWithReplacement(element, nullptr,
                                               aParentContext,
-                                              undisplayed->mStyle,
+                                              undisplayed->mStyle->AsGecko(),
                                               rshint);
     }
     const nsStyleDisplay* display = undisplayedContext->StyleDisplay();
     if (display->mDisplay != aDisplay) {
       NS_ASSERTION(element, "Must have undisplayed content");
       mChangeList->AppendChange(nullptr, element,
                                 nsChangeHint_ReconstructFrame);
       // The node should be removed from the undisplayed map when
       // we reframe it.
     } else {
       // update the undisplayed node with the new context
       undisplayed->mStyle = undisplayedContext;
 
       if (aDisplay == StyleDisplay::Contents) {
         DoRestyleUndisplayedDescendants(aChildRestyleHint, element,
-                                        undisplayed->mStyle);
+                                        undisplayed->mStyle->AsGecko());
       }
     }
   }
 }
 
 void
 ElementRestyler::MaybeReframeForBeforePseudo()
 {
   MaybeReframeForPseudo(CSSPseudoElementType::before,
                         mFrame, mFrame, mFrame->GetContent(),
-                        mFrame->StyleContext());
+                        mFrame->StyleContext()->AsGecko());
 }
 
 /**
  * aFrame is the last continuation or block-in-inline sibling that this
  * ElementRestyler is restyling.
  */
 void
 ElementRestyler::MaybeReframeForAfterPseudo(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame);
   MaybeReframeForPseudo(CSSPseudoElementType::after,
                         aFrame, aFrame, aFrame->GetContent(),
-                        aFrame->StyleContext());
+                        aFrame->StyleContext()->AsGecko());
 }
 
 #ifdef DEBUG
 bool
 ElementRestyler::MustReframeForBeforePseudo()
 {
   return MustReframeForPseudo(CSSPseudoElementType::before,
                               mFrame, mFrame, mFrame->GetContent(),
-                              mFrame->StyleContext());
+                              mFrame->StyleContext()->AsGecko());
 }
 
 bool
 ElementRestyler::MustReframeForAfterPseudo(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame);
   return MustReframeForPseudo(CSSPseudoElementType::after,
                               aFrame, aFrame, aFrame->GetContent(),
-                              aFrame->StyleContext());
+                              aFrame->StyleContext()->AsGecko());
 }
 #endif
 
 void
 ElementRestyler::MaybeReframeForPseudo(CSSPseudoElementType aPseudoType,
                                        nsIFrame* aGenConParentFrame,
                                        nsIFrame* aFrame,
                                        nsIContent* aContent,
-                                       nsStyleContext* aStyleContext)
+                                       GeckoStyleContext* aStyleContext)
 {
   if (MustReframeForPseudo(aPseudoType, aGenConParentFrame, aFrame, aContent,
                            aStyleContext)) {
     // Have to create the new ::before/::after frame.
     LOG_RESTYLE("MaybeReframeForPseudo, appending "
                 "nsChangeHint_ReconstructFrame");
     mHintsHandledBySelf |= nsChangeHint_ReconstructFrame;
     mChangeList->AppendChange(aFrame, aContent, nsChangeHint_ReconstructFrame);
   }
 }
 
 bool
 ElementRestyler::MustReframeForPseudo(CSSPseudoElementType aPseudoType,
                                       nsIFrame* aGenConParentFrame,
                                       nsIFrame* aFrame,
                                       nsIContent* aContent,
-                                      nsStyleContext* aStyleContext)
+                                      GeckoStyleContext* aStyleContext)
 {
   MOZ_ASSERT(aPseudoType == CSSPseudoElementType::before ||
              aPseudoType == CSSPseudoElementType::after);
 
   // Make sure not to do this for pseudo-frames...
   if (aStyleContext->GetPseudo()) {
     return false;
   }
@@ -3465,28 +3544,28 @@ GeckoRestyleManager::ComputeAndProcessSt
 {
   MOZ_ASSERT(mReframingStyleContexts, "should have rsc");
   nsStyleChangeList changeList(StyleBackendType::Gecko);
   nsTArray<ElementRestyler::ContextToClear> contextsToClear;
 
   // swappedStructOwners needs to be kept alive until after
   // ProcessRestyledFrames and ClearCachedInheritedStyleDataOnDescendants
   // calls; see comment in ElementRestyler::Restyle.
-  nsTArray<RefPtr<nsStyleContext>> swappedStructOwners;
+  nsTArray<RefPtr<GeckoStyleContext>> swappedStructOwners;
   ElementRestyler::ComputeStyleChangeFor(aFrame, &changeList, aMinChange,
                                          aRestyleTracker, aRestyleHint,
                                          aRestyleHintData,
                                          contextsToClear, swappedStructOwners);
   ProcessRestyledFrames(changeList);
   ClearCachedInheritedStyleDataOnDescendants(contextsToClear);
 }
 
 void
 GeckoRestyleManager::ComputeAndProcessStyleChange(
-    nsStyleContext*        aNewContext,
+    GeckoStyleContext*        aNewContext,
     Element*               aElement,
     nsChangeHint           aMinChange,
     RestyleTracker&        aRestyleTracker,
     nsRestyleHint          aRestyleHint,
     const RestyleHintData& aRestyleHintData)
 {
   MOZ_ASSERT(mReframingStyleContexts, "should have rsc");
   MOZ_ASSERT(aNewContext->StyleDisplay()->mDisplay == StyleDisplay::Contents);
@@ -3503,17 +3582,17 @@ GeckoRestyleManager::ComputeAndProcessSt
 
   nsTArray<nsCSSSelector*> selectorsForDescendants;
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   nsTArray<ElementRestyler::ContextToClear> contextsToClear;
 
   // swappedStructOwners needs to be kept alive until after
   // ProcessRestyledFrames and ClearCachedInheritedStyleDataOnDescendants
   // calls; see comment in ElementRestyler::Restyle.
-  nsTArray<RefPtr<nsStyleContext>> swappedStructOwners;
+  nsTArray<RefPtr<GeckoStyleContext>> swappedStructOwners;
   nsStyleChangeList changeList(StyleBackendType::Gecko);
   ElementRestyler r(frame->PresContext(), aElement, &changeList, aMinChange,
                     aRestyleTracker, selectorsForDescendants, treeMatchContext,
                     visibleKidsOfHiddenElement, contextsToClear,
                     swappedStructOwners);
   r.RestyleChildrenOfDisplayContentsElement(frame, aNewContext, aMinChange,
                                             aRestyleTracker,
                                             aRestyleHint, aRestyleHintData);
@@ -3579,17 +3658,17 @@ GeckoRestyleManager::StructsToLog()
     const char* value = getenv("MOZ_DEBUG_RESTYLE_STRUCTS");
     if (value) {
       nsCString s(value);
       while (!s.IsEmpty()) {
         int32_t index = s.FindChar(',');
         nsStyleStructID sid;
         bool found;
         if (index == -1) {
-          found = nsStyleContext::LookupStruct(s, sid);
+          found = GeckoStyleContext::LookupStruct(s, sid);
           s.Truncate();
         } else {
           found = nsStyleContext::LookupStruct(Substring(s, 0, index), sid);
           s = Substring(s, index + 1);
         }
         if (found) {
           structs |= nsCachedStyleData::GetBitForSID(sid);
         }
--- a/layout/base/GeckoRestyleManager.h
+++ b/layout/base/GeckoRestyleManager.h
@@ -100,17 +100,17 @@ private:
   // Used when restyling an element with a frame.
   void ComputeAndProcessStyleChange(nsIFrame*              aFrame,
                                     nsChangeHint           aMinChange,
                                     RestyleTracker&        aRestyleTracker,
                                     nsRestyleHint          aRestyleHint,
                                     const RestyleHintData& aRestyleHintData);
 
   // Used when restyling a display:contents element.
-  void ComputeAndProcessStyleChange(nsStyleContext*        aNewContext,
+  void ComputeAndProcessStyleChange(GeckoStyleContext*     aNewContext,
                                     Element*               aElement,
                                     nsChangeHint           aMinChange,
                                     RestyleTracker&        aRestyleTracker,
                                     nsRestyleHint          aRestyleHint,
                                     const RestyleHintData& aRestyleHintData);
 
 public:
 
@@ -120,44 +120,44 @@ public:
    * the reframing process.
    *
    * In all cases, the content node in the hash table is the real
    * content node, not the anonymous content node we create for ::before
    * or ::after.  The content node passed to the Get and Put methods is,
    * however, the content node to be associate with the frame's style
    * context.
    */
-  typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIContent>, nsStyleContext>
+  typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIContent>, GeckoStyleContext>
             ReframingStyleContextTable;
   class MOZ_STACK_CLASS ReframingStyleContexts final {
   public:
     /**
      * Construct a ReframingStyleContexts object.  The caller must
      * ensure that aRestyleManager lives at least as long as the
      * object.  (This is generally easy since the caller is typically a
      * method of RestyleManager.)
      */
     explicit ReframingStyleContexts(GeckoRestyleManager* aRestyleManager);
     ~ReframingStyleContexts();
 
-    void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
+    void Put(nsIContent* aContent, GeckoStyleContext* aStyleContext) {
       MOZ_ASSERT(aContent);
       CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
       if (pseudoType == CSSPseudoElementType::NotPseudo) {
         mElementContexts.Put(aContent, aStyleContext);
       } else if (pseudoType == CSSPseudoElementType::before) {
         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
         mBeforePseudoContexts.Put(aContent->GetParent(), aStyleContext);
       } else if (pseudoType == CSSPseudoElementType::after) {
         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
         mAfterPseudoContexts.Put(aContent->GetParent(), aStyleContext);
       }
     }
 
-    nsStyleContext* Get(nsIContent* aContent,
+    GeckoStyleContext* Get(nsIContent* aContent,
                         CSSPseudoElementType aPseudoType) {
       MOZ_ASSERT(aContent);
       if (aPseudoType == CSSPseudoElementType::NotPseudo) {
         return mElementContexts.GetWeak(aContent);
       }
       if (aPseudoType == CSSPseudoElementType::before) {
         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
         return mBeforePseudoContexts.GetWeak(aContent->GetParent());
@@ -191,18 +191,18 @@ public:
    * change the new style context if a transition is started.  Returns
    * true if it does change aNewStyleContext.
    *
    * For the pseudo-elements, aContent must be the anonymous content
    * that we're creating for that pseudo-element, not the real element.
    */
   static bool
   TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent,
-                          nsStyleContext* aOldStyleContext,
-                          RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
+                          GeckoStyleContext* aOldStyleContext,
+                          RefPtr<GeckoStyleContext>* aNewStyleContext /* inout */);
 
 public:
   // Process any pending restyles. This should be called after
   // CreateNeededFrames.
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessPendingRestyles call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
@@ -405,31 +405,31 @@ private:
  * recompute styles for.
  */
 class ElementRestyler final
 {
 public:
   typedef mozilla::dom::Element Element;
 
   struct ContextToClear {
-    RefPtr<nsStyleContext> mStyleContext;
+    RefPtr<GeckoStyleContext> mStyleContext;
     uint32_t mStructs;
   };
 
   // Construct for the root of the subtree that we're restyling.
   ElementRestyler(nsPresContext* aPresContext,
                   nsIFrame* aFrame,
                   nsStyleChangeList* aChangeList,
                   nsChangeHint aHintsHandledByAncestors,
                   RestyleTracker& aRestyleTracker,
                   nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                   TreeMatchContext& aTreeMatchContext,
                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                   nsTArray<ContextToClear>& aContextsToClear,
-                  nsTArray<RefPtr<nsStyleContext>>& aSwappedStructOwners);
+                  nsTArray<RefPtr<GeckoStyleContext>>& aSwappedStructOwners);
 
   // Construct for an element whose parent is being restyled.
   enum ConstructorFlags {
     FOR_OUT_OF_FLOW_CHILD = 1<<0
   };
   ElementRestyler(const ElementRestyler& aParentRestyler,
                   nsIFrame* aFrame,
                   uint32_t aConstructorFlags);
@@ -450,17 +450,17 @@ public:
                   nsIContent* aContent,
                   nsStyleChangeList* aChangeList,
                   nsChangeHint aHintsHandledByAncestors,
                   RestyleTracker& aRestyleTracker,
                   nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                   TreeMatchContext& aTreeMatchContext,
                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                   nsTArray<ContextToClear>& aContextsToClear,
-                  nsTArray<RefPtr<nsStyleContext>>& aSwappedStructOwners);
+                  nsTArray<RefPtr<GeckoStyleContext>>& aSwappedStructOwners);
 
   /**
    * Restyle our frame's element and its subtree.
    *
    * Use eRestyle_Self for the aRestyleHint argument to mean
    * "reresolve our style context but not kids", use eRestyle_Subtree
    * to mean "reresolve our style context and kids", and use
    * nsRestyleHint(0) to mean recompute a new style context for our
@@ -476,17 +476,17 @@ public:
    */
   nsChangeHint HintsHandledForFrame() { return mHintsHandledBySelf; }
 
   /**
    * Called from GeckoRestyleManager::ComputeAndProcessStyleChange to restyle
    * children of a display:contents element.
    */
   void RestyleChildrenOfDisplayContentsElement(nsIFrame*       aParentFrame,
-                                               nsStyleContext* aNewContext,
+                                               GeckoStyleContext* aNewContext,
                                                nsChangeHint    aMinHint,
                                                RestyleTracker& aRestyleTracker,
                                                nsRestyleHint   aRestyleHint,
                                                const RestyleHintData&
                                                  aRestyleHintData);
 
   /**
    * Re-resolve the style contexts for a frame tree, building aChangeList
@@ -494,17 +494,17 @@ public:
    */
   static void ComputeStyleChangeFor(nsIFrame*          aFrame,
                                     nsStyleChangeList* aChangeList,
                                     nsChangeHint       aMinChange,
                                     RestyleTracker&    aRestyleTracker,
                                     nsRestyleHint      aRestyleHint,
                                     const RestyleHintData& aRestyleHintData,
                                     nsTArray<ContextToClear>& aContextsToClear,
-                                    nsTArray<RefPtr<nsStyleContext>>&
+                                    nsTArray<RefPtr<GeckoStyleContext>>&
                                       aSwappedStructOwners);
 
 #ifdef RESTYLE_LOGGING
   bool ShouldLogRestyle() {
     return GeckoRestyleManager::ShouldLogRestyle(mPresContext);
   }
 #endif
 
@@ -531,18 +531,18 @@ private:
     eContinue,
 
     // continue restyling children with eRestyle_ForceDescendants set
     eContinueAndForceDescendants
   };
 
   struct SwapInstruction
   {
-    RefPtr<nsStyleContext> mOldContext;
-    RefPtr<nsStyleContext> mNewContext;
+    RefPtr<GeckoStyleContext> mOldContext;
+    RefPtr<GeckoStyleContext> mNewContext;
     uint32_t mStructsToSwap;
   };
 
   /**
    * First half of Restyle().
    */
   RestyleResult RestyleSelf(nsIFrame* aSelf,
                             nsRestyleHint aRestyleHint,
@@ -580,70 +580,70 @@ private:
    * ReparentStyleContext.
    */
   bool CanReparentStyleContext(nsRestyleHint aRestyleHint);
 
   /**
    * Helpers for Restyle().
    */
   bool MoveStyleContextsForContentChildren(nsIFrame* aParent,
-                                           nsStyleContext* aOldContext,
-                                           nsTArray<nsStyleContext*>& aContextsToMove);
-  bool MoveStyleContextsForChildren(nsStyleContext* aOldContext);
+                                           GeckoStyleContext* aOldContext,
+                                           nsTArray<GeckoStyleContext*>& aContextsToMove);
+  bool MoveStyleContextsForChildren(GeckoStyleContext* aOldContext);
 
   /**
    * Helpers for RestyleSelf().
    */
-  void CaptureChange(nsStyleContext* aOldContext,
-                     nsStyleContext* aNewContext,
+  void CaptureChange(GeckoStyleContext* aOldContext,
+                     GeckoStyleContext* aNewContext,
                      nsChangeHint aChangeToAssume,
                      uint32_t* aEqualStructs,
                      uint32_t* aSamePointerStructs);
   void ComputeRestyleResultFromFrame(nsIFrame* aSelf,
                                      RestyleResult& aRestyleResult,
                                      bool& aCanStopWithStyleChange);
   void ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
-                                          nsStyleContext* aNewContext,
+                                          GeckoStyleContext* aNewContext,
                                           RestyleResult& aRestyleResult,
                                           bool& aCanStopWithStyleChange);
 
   // Helpers for RestyleChildren().
   void RestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint);
   bool MustCheckUndisplayedContent(nsIFrame* aFrame,
                                    nsIContent*& aUndisplayedParent);
 
   /**
    * In the following two methods, aParentStyleContext is either
    * mFrame->StyleContext() if we have a frame, or a display:contents
    * style context if we don't.
    */
   void DoRestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint,
                                        nsIContent* aParent,
-                                       nsStyleContext* aParentStyleContext);
+                                       GeckoStyleContext* aParentStyleContext);
   void RestyleUndisplayedNodes(nsRestyleHint      aChildRestyleHint,
                                UndisplayedNode*   aUndisplayed,
                                nsIContent*        aUndisplayedParent,
-                               nsStyleContext*    aParentStyleContext,
+                               GeckoStyleContext*    aParentStyleContext,
                                const StyleDisplay aDisplay);
   void MaybeReframeForBeforePseudo();
   void MaybeReframeForAfterPseudo(nsIFrame* aFrame);
   void MaybeReframeForPseudo(CSSPseudoElementType aPseudoType,
                              nsIFrame* aGenConParentFrame,
                              nsIFrame* aFrame,
                              nsIContent* aContent,
-                             nsStyleContext* aStyleContext);
+                             GeckoStyleContext* aStyleContext);
 #ifdef DEBUG
   bool MustReframeForBeforePseudo();
   bool MustReframeForAfterPseudo(nsIFrame* aFrame);
 #endif
   bool MustReframeForPseudo(CSSPseudoElementType aPseudoType,
                             nsIFrame* aGenConParentFrame,
                             nsIFrame* aFrame,
                             nsIContent* aContent,
-                            nsStyleContext* aStyleContext);
+                            GeckoStyleContext* aStyleContext);
   void RestyleContentChildren(nsIFrame* aParent,
                               nsRestyleHint aChildRestyleHint);
   void InitializeAccessibilityNotifications(nsStyleContext* aNewContext);
   void SendAccessibilityNotifications();
 
   enum DesiredA11yNotifications {
     eSkipNotifications,
     eSendAllNotifications,
@@ -710,17 +710,17 @@ private:
   nsIFrame* mResolvedChild; // child that provides our parent style context
   // Array of style context subtrees in which we need to clear out cached
   // structs at the end of the restyle (after change hints have been
   // processed).
   nsTArray<ContextToClear>& mContextsToClear;
   // Style contexts that had old structs swapped into it and which should
   // stay alive until the end of the restyle.  (See comment in
   // ElementRestyler::Restyle.)
-  nsTArray<RefPtr<nsStyleContext>>& mSwappedStructOwners;
+  nsTArray<RefPtr<GeckoStyleContext>>& mSwappedStructOwners;
   // Whether this is the root of the restyle.
   bool mIsRootOfRestyle;
 
 #ifdef ACCESSIBILITY
   const DesiredA11yNotifications mDesiredA11yNotifications;
   DesiredA11yNotifications mKidsDesiredA11yNotifications;
   A11yNotificationType mOurA11yNotification;
   nsTArray<nsIContent*>& mVisibleKidsOfHiddenElement;
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1004,42 +1004,16 @@ NeedToReframeForAddingOrRemovingTransfor
        f = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(f)) {
     if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
       return true;
     }
   }
   return false;
 }
 
-/* static */ nsIFrame*
-RestyleManager::GetNearestAncestorFrame(nsIContent* aContent)
-{
-  nsIFrame* ancestorFrame = nullptr;
-  for (nsIContent* ancestor = aContent->GetParent();
-       ancestor && !ancestorFrame;
-       ancestor = ancestor->GetParent()) {
-    ancestorFrame = ancestor->GetPrimaryFrame();
-  }
-  return ancestorFrame;
-}
-
-/* static */ nsIFrame*
-RestyleManager::GetNextBlockInInlineSibling(nsIFrame* aFrame)
-{
-  NS_ASSERTION(!aFrame->GetPrevContinuation(),
-               "must start with the first continuation");
-  // Might we have ib-split siblings?
-  if (!(aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
-    // nothing more to do here
-    return nullptr;
-  }
-
-  return aFrame->GetProperty(nsIFrame::IBSplitSibling());
-}
-
 static void
 DoApplyRenderingChangeToTree(nsIFrame* aFrame,
                              nsChangeHint aChange)
 {
   NS_PRECONDITION(gInApplyRenderingChangeToTree,
                   "should only be called within ApplyRenderingChangeToTree");
 
   for ( ; aFrame; aFrame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame)) {
@@ -1287,57 +1261,16 @@ StyleChangeReflow(nsIFrame* aFrame, nsCh
 
   do {
     aFrame->PresContext()->PresShell()->FrameNeedsReflow(
       aFrame, dirtyType, dirtyBits, rootHandling);
     aFrame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame);
   } while (aFrame);
 }
 
-/* static */ nsIFrame*
-RestyleManager::GetNextContinuationWithSameStyle(
-  nsIFrame* aFrame, nsStyleContext* aOldStyleContext,
-  bool* aHaveMoreContinuations)
-{
-  // See GetPrevContinuationWithSameStyle about {ib} splits.
-
-  nsIFrame* nextContinuation = aFrame->GetNextContinuation();
-  if (!nextContinuation &&
-      (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) {
-    // We're the last continuation, so we have to hop back to the first
-    // before getting the frame property
-    nextContinuation =
-      aFrame->FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
-    if (nextContinuation) {
-      nextContinuation =
-        nextContinuation->GetProperty(nsIFrame::IBSplitSibling());
-    }
-  }
-
-  if (!nextContinuation) {
-    return nullptr;
-  }
-
-  NS_ASSERTION(nextContinuation->GetContent() == aFrame->GetContent(),
-               "unexpected content mismatch");
-
-  nsStyleContext* nextStyle = nextContinuation->StyleContext();
-  if (nextStyle != aOldStyleContext) {
-    NS_ASSERTION(aOldStyleContext->GetPseudo() != nextStyle->GetPseudo() ||
-                 aOldStyleContext->GetParentAllowServo() !=
-                   nextStyle->GetParentAllowServo(),
-                 "continuations should have the same style context");
-    nextContinuation = nullptr;
-    if (aHaveMoreContinuations) {
-      *aHaveMoreContinuations = true;
-    }
-  }
-  return nextContinuation;
-}
-
 void
 RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
 
   // See bug 1378219 comment 9:
   // Recursive calls here are a bit worrying, but apparently do happen in the
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -280,41 +280,16 @@ protected:
   bool mInStyleRefresh;
 
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   OverflowChangedTracker mOverflowChangedTracker;
 
-  /**
-   * These are protected static methods that help with the change hint
-   * processing bits of the restyle managers.
-   */
-  static nsIFrame*
-  GetNearestAncestorFrame(nsIContent* aContent);
-
-  static nsIFrame*
-  GetNextBlockInInlineSibling(nsIFrame* aFrame);
-
-  /**
-   * Get the next continuation or similar ib-split sibling (assuming
-   * block/inline alternation), conditionally on it having the same style.
-   *
-   * Since this is used when deciding to copy the new style context, it
-   * takes as an argument the old style context to check if the style is
-   * the same.  When it is used in other contexts (i.e., where the next
-   * continuation would already have the new style context), the current
-   * style context should be passed.
-   */
-  static nsIFrame*
-  GetNextContinuationWithSameStyle(nsIFrame* aFrame,
-                                   nsStyleContext* aOldStyleContext,
-                                   bool* aHaveMoreContinuations = nullptr);
-
   AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame = nullptr;
 
   friend class mozilla::GeckoRestyleManager;
   friend class mozilla::ServoRestyleManager;
 };
 
 } // namespace mozilla
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1921,43 +1921,42 @@ nsCSSFrameConstructor::CreateGeneratedCo
   }
 
   // Servo has already eagerly computed the style for the container, so we can
   // just stick the style on the element and avoid an additional traversal.
   //
   // We don't do this for pseudos that may trigger animations or transitions,
   // since those need to be kicked off by the traversal machinery.
   bool hasServoAnimations = false;
-  ServoStyleContext* servoStyle = pseudoStyleContext->GetAsServo();
+  auto* servoStyle = pseudoStyleContext->GetAsServo();
   if (servoStyle) {
     hasServoAnimations =
       Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle);
     if (!hasServoAnimations) {
       Servo_SetExplicitStyle(container, servoStyle);
     }
-  }
-
-  // stylo: ServoRestyleManager does not handle transitions yet, and when it
-  // does it probably won't need to track reframed style contexts to start
-  // transitions correctly.
-  if (mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->GetAsGecko()) {
+  } else {
+    mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->AsGecko();
     GeckoRestyleManager::ReframingStyleContexts* rsc =
       geckoRM->GetReframingStyleContexts();
+
     if (rsc) {
-      nsStyleContext* oldStyleContext = rsc->Get(container, aPseudoElement);
-      if (oldStyleContext) {
+      RefPtr<GeckoStyleContext> newContext =
+        GeckoStyleContext::TakeRef(pseudoStyleContext.forget());
+      if (auto* oldStyleContext = rsc->Get(container, aPseudoElement)) {
         GeckoRestyleManager::TryInitiatingTransition(aState.mPresContext,
                                                      container,
                                                      oldStyleContext,
-                                                     &pseudoStyleContext);
+                                                     &newContext);
       } else {
         aState.mPresContext->TransitionManager()->
           PruneCompletedTransitions(aParentContent->AsElement(),
-                                    aPseudoElement, pseudoStyleContext);
-      }
+                                    aPseudoElement, newContext);
+      }
+      pseudoStyleContext = newContext.forget();
     }
   }
 
   uint32_t contentCount = pseudoStyleContext->StyleContent()->ContentCount();
   bool createdChildElement = false;
   for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
     nsCOMPtr<nsIContent> content =
       CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
@@ -5203,26 +5202,29 @@ nsCSSFrameConstructor::ResolveStyleConte
 
   // ServoRestyleManager does not handle transitions yet, and when it does
   // it probably won't need to track reframed style contexts to start
   // transitions correctly.
   if (mozilla::GeckoRestyleManager* geckoRM = RestyleManager()->GetAsGecko()) {
     GeckoRestyleManager::ReframingStyleContexts* rsc =
       geckoRM->GetReframingStyleContexts();
     if (rsc) {
-      nsStyleContext* oldStyleContext =
+      GeckoStyleContext* oldStyleContext =
         rsc->Get(aContent, CSSPseudoElementType::NotPseudo);
       nsPresContext* presContext = mPresShell->GetPresContext();
       if (oldStyleContext) {
+        RefPtr<GeckoStyleContext> newContext =
+          GeckoStyleContext::TakeRef(result.forget());
         GeckoRestyleManager::TryInitiatingTransition(presContext, aContent,
-                                                     oldStyleContext, &result);
+                                                     oldStyleContext, &newContext);
+        result = newContext.forget();
       } else if (aContent->IsElement()) {
         presContext->TransitionManager()->
           PruneCompletedTransitions(aContent->AsElement(),
-            CSSPseudoElementType::NotPseudo, result);
+            CSSPseudoElementType::NotPseudo, result->AsGecko());
       }
     }
   }
 
   return result.forget();
 }
 
 // MathML Mod - RBS
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -751,17 +751,17 @@ nsFrame::DestroyFrom(nsIFrame* aDestruct
     // specifies CSS transitions.
     if (presContext->RestyleManager()->IsGecko()) {
       // stylo: ServoRestyleManager does not handle transitions yet, and when
       // it does it probably won't need to track reframed style contexts to
       // initiate transitions correctly.
       GeckoRestyleManager::ReframingStyleContexts* rsc =
         presContext->RestyleManager()->AsGecko()->GetReframingStyleContexts();
       if (rsc) {
-        rsc->Put(mContent, mStyleContext);
+        rsc->Put(mContent, mStyleContext->AsGecko());
       }
     }
   }
 
   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
--- a/layout/style/GeckoStyleContext.cpp
+++ b/layout/style/GeckoStyleContext.cpp
@@ -26,17 +26,17 @@ static bool sExpensiveStyleStructAsserti
 GeckoStyleContext::Initialize()
 {
   Preferences::AddBoolVarCache(
       &sExpensiveStyleStructAssertionsEnabled,
       "layout.css.expensive-style-struct-assertions.enabled");
 }
 #endif
 
-GeckoStyleContext::GeckoStyleContext(nsStyleContext* aParent,
+GeckoStyleContext::GeckoStyleContext(GeckoStyleContext* aParent,
                                      nsIAtom* aPseudoTag,
                                      CSSPseudoElementType aPseudoType,
                                      already_AddRefed<nsRuleNode> aRuleNode,
                                      bool aSkipParentDisplayBasedStyleFixup)
   : nsStyleContext(aParent, aPseudoTag, aPseudoType)
   , mCachedResetData(nullptr)
   , mChild(nullptr)
   , mEmptyChild(nullptr)
@@ -145,16 +145,63 @@ GeckoStyleContext::AddChild(GeckoStyleCo
     aChild->mPrevSibling = list->mPrevSibling;
     list->mPrevSibling->mNextSibling = aChild;
     list->mPrevSibling = aChild;
   }
   (*listPtr) = aChild;
 }
 
 void
+GeckoStyleContext::MoveTo(GeckoStyleContext* aNewParent)
+{
+  MOZ_ASSERT(aNewParent != mParent);
+
+  // This function shouldn't be getting called if the parents have different
+  // values for some flags in mBits (unless the flag is also set on this style
+  // context) because if that were the case we would need to recompute those
+  // bits for |this|.
+
+#define CHECK_FLAG(bit_) \
+  MOZ_ASSERT((mParent->AsGecko()->mBits & (bit_)) ==                          \
+               (aNewParent->mBits & (bit_)) || (mBits & (bit_)),              \
+             "MoveTo cannot be called if " #bit_ " value on old and new "     \
+             "style context parents do not match, unless the flag is set "    \
+             "on this style context");
+
+  CHECK_FLAG(NS_STYLE_HAS_PSEUDO_ELEMENT_DATA)
+  CHECK_FLAG(NS_STYLE_IN_DISPLAY_NONE_SUBTREE)
+  CHECK_FLAG(NS_STYLE_HAS_TEXT_DECORATION_LINES)
+  CHECK_FLAG(NS_STYLE_RELEVANT_LINK_VISITED)
+
+#undef CHECK_FLAG
+
+  // Assertions checking for visited style are just to avoid some tricky
+  // cases we can't be bothered handling at the moment.
+  MOZ_ASSERT(!IsStyleIfVisited());
+  MOZ_ASSERT(!mParent->IsStyleIfVisited());
+  MOZ_ASSERT(!aNewParent->IsStyleIfVisited());
+  auto* styleIfVisited = GetStyleIfVisited();
+  MOZ_ASSERT(!styleIfVisited || styleIfVisited->mParent == mParent);
+
+  if (mParent->HasChildThatUsesResetStyle()) {
+    aNewParent->AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE);
+  }
+
+  mParent->RemoveChild(this);
+  mParent = aNewParent;
+  mParent->AddChild(this);
+
+  if (styleIfVisited) {
+    styleIfVisited->mParent->RemoveChild(styleIfVisited);
+    styleIfVisited->mParent = aNewParent;
+    styleIfVisited->mParent->AddChild(styleIfVisited);
+  }
+}
+
+void
 GeckoStyleContext::RemoveChild(GeckoStyleContext* aChild)
 {
   NS_PRECONDITION(nullptr != aChild && this == aChild->mParent, "bad argument");
 
   MOZ_ASSERT(aChild->mRuleNode, "child context should have rule node");
   GeckoStyleContext **list = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
 
   if (aChild->mPrevSibling != aChild) { // has siblings
@@ -1062,17 +1109,17 @@ GeckoStyleContext::SwapStyleData(GeckoSt
     } else if (!(aNewContext->mBits & bit) && thisData && otherData) {
       std::swap(thisData, otherData);
     }
   }
 }
 
 
 void
-GeckoStyleContext::SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
+GeckoStyleContext::SetStyleIfVisited(already_AddRefed<GeckoStyleContext> aStyleIfVisited)
 {
   MOZ_ASSERT(!IsStyleIfVisited(), "this context is not visited data");
   NS_ASSERTION(!mStyleIfVisited, "should only be set once");
 
   mStyleIfVisited = aStyleIfVisited;
 
   MOZ_ASSERT(mStyleIfVisited->IsStyleIfVisited(),
              "other context is visited data");
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -8,37 +8,55 @@
 #define mozilla_GeckoStyleContext_h
 
 #include "nsStyleContext.h"
 
 namespace mozilla {
 
 class GeckoStyleContext final : public nsStyleContext {
 public:
-  GeckoStyleContext(nsStyleContext* aParent,
+  static already_AddRefed<GeckoStyleContext>
+  TakeRef(already_AddRefed<nsStyleContext> aStyleContext)
+  {
+    auto* context = aStyleContext.take();
+    MOZ_ASSERT(context);
+
+    return already_AddRefed<GeckoStyleContext>(context->AsGecko());
+  }
+
+  GeckoStyleContext(GeckoStyleContext* aParent,
                     nsIAtom* aPseudoTag,
                     CSSPseudoElementType aPseudoType,
                     already_AddRefed<nsRuleNode> aRuleNode,
                     bool aSkipParentDisplayBasedStyleFixup);
 
   void* operator new(size_t sz, nsPresContext* aPresContext);
 
   nsPresContext* PresContext() const {
     return RuleNode()->PresContext();
   }
 
   void AddChild(GeckoStyleContext* aChild);
   void RemoveChild(GeckoStyleContext* aChild);
 
+  /**
+   * Moves this style context to a new parent.
+   *
+   * This function violates style context tree immutability, and
+   * is a very low-level function and should only be used after verifying
+   * many conditions that make it safe to call.
+   */
+  void MoveTo(GeckoStyleContext* aNewParent);
+
   void* GetUniqueStyleData(const nsStyleStructID& aSID);
   void* CreateEmptyStyleData(const nsStyleStructID& aSID);
 
   // To be called only from nsStyleSet / ServoStyleSet.
-  void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited);
-  nsStyleContext* GetStyleIfVisited() const { return mStyleIfVisited; };
+  void SetStyleIfVisited(already_AddRefed<GeckoStyleContext> aStyleIfVisited);
+  GeckoStyleContext* GetStyleIfVisited() const { return mStyleIfVisited; };
 #ifdef DEBUG
   /**
    * Initializes a cached pref, which is only used in DEBUG code.
    */
   static void Initialize();
 #endif
 
   /**
@@ -221,17 +239,17 @@ private:
   GeckoStyleContext* mEmptyChild;
   GeckoStyleContext* mPrevSibling;
   GeckoStyleContext* mNextSibling;
   RefPtr<nsRuleNode> mRuleNode;
 
   // Style to be used instead for the R, G, and B components of color,
   // background-color, and border-*-color if the nearest ancestor link
   // element is visited (see RelevantLinkVisited()).
-  RefPtr<nsStyleContext> mStyleIfVisited;
+  RefPtr<GeckoStyleContext> mStyleIfVisited;
 
 #ifdef DEBUG
 public:
   struct AutoCheckDependency {
 
     GeckoStyleContext* mStyleContext;
     nsStyleStructID mOuterSID;
 
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -1440,17 +1440,17 @@ ComputeTransformListDistance(const nsCSS
                "aList1 and aList2 should have the same length.");
   } while (aList1);
   return sqrt(distance);
 }
 
 static double
 ComputeMismatchedTransfromListDistance(const nsCSSValueList* aList1,
                                        const nsCSSValueList* aList2,
-                                       nsStyleContext* aStyleContext)
+                                       GeckoStyleContext* aStyleContext)
 {
   // We need nsStyleContext and nsPresContext to compute calc() values while
   // processing the translate part of transforms.
   if (!aStyleContext) {
     return 0.0;
   }
 
   RuleNodeCacheConditions dontCare;
@@ -1475,17 +1475,17 @@ ComputeMismatchedTransfromListDistance(c
                    &dontCareBool);
   return sqrt(ComputeTransform3DMatrixDistance(m1, m2));
 }
 
 bool
 StyleAnimationValue::ComputeDistance(nsCSSPropertyID aProperty,
                                      const StyleAnimationValue& aStartValue,
                                      const StyleAnimationValue& aEndValue,
-                                     nsStyleContext* aStyleContext,
+                                     GeckoStyleContext* aStyleContext,
                                      double& aDistance)
 {
   Unit commonUnit =
     GetCommonUnit(aProperty, aStartValue.GetUnit(), aEndValue.GetUnit());
 
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_Auto:
@@ -3470,17 +3470,17 @@ BuildStyleRule(nsCSSPropertyID aProperty
   RefPtr<css::StyleRule> rule = new css::StyleRule(nullptr, declaration, 0, 0);
   return rule.forget();
 }
 
 static bool
 ComputeValuesFromStyleContext(
   nsCSSPropertyID aProperty,
   CSSEnabledState aEnabledState,
-  nsStyleContext* aStyleContext,
+  GeckoStyleContext* aStyleContext,
   nsTArray<PropertyStyleAnimationValuePair>& aValues)
 {
   // Extract computed value of our property (or all longhand components, if
   // aProperty is a shorthand) from the temporary style context
   if (nsCSSProps::IsShorthand(aProperty)) {
     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty, aEnabledState) {
       if (nsCSSProps::kAnimTypeTable[*p] == eStyleAnimType_None) {
         // Skip non-animatable component longhands.
@@ -3500,31 +3500,31 @@ ComputeValuesFromStyleContext(
   pair->mProperty = aProperty;
   return StyleAnimationValue::ExtractComputedValue(aProperty, aStyleContext,
                                                    pair->mValue.mGecko);
 }
 
 static bool
 ComputeValuesFromStyleRule(nsCSSPropertyID aProperty,
                            CSSEnabledState aEnabledState,
-                           nsStyleContext* aStyleContext,
+                           GeckoStyleContext* aStyleContext,
                            css::StyleRule* aStyleRule,
                            nsTArray<PropertyStyleAnimationValuePair>& aValues,
                            bool* aIsContextSensitive)
 {
   MOZ_ASSERT(aStyleContext);
   if (!nsCSSProps::IsEnabled(aProperty, aEnabledState)) {
     return false;
   }
 
   MOZ_ASSERT(aStyleContext->PresContext()->StyleSet()->IsGecko(),
              "ServoStyleSet should not use StyleAnimationValue for animations");
   nsStyleSet* styleSet = aStyleContext->PresContext()->StyleSet()->AsGecko();
 
-  RefPtr<nsStyleContext> tmpStyleContext;
+  RefPtr<GeckoStyleContext> tmpStyleContext;
   if (aIsContextSensitive) {
     MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty),
                "to correctly set aIsContextSensitive for shorthand properties, "
                "this code must be adjusted");
 
     nsCOMArray<nsIStyleRule> ruleArray;
     ruleArray.AppendObject(styleSet->InitialStyleRule());
     css::Declaration* declaration = aStyleRule->GetDeclaration();
@@ -3533,17 +3533,17 @@ ComputeValuesFromStyleRule(nsCSSProperty
     tmpStyleContext =
       styleSet->ResolveStyleByAddingRules(aStyleContext, ruleArray);
     if (!tmpStyleContext) {
       return false;
     }
 
     // Force walk of rule tree
     nsStyleStructID sid = nsCSSProps::kSIDTable[aProperty];
-    tmpStyleContext->AsGecko()->StyleData(sid);
+    tmpStyleContext->StyleData(sid);
 
     // The rule node will have unconditional cached style data if the value is
     // not context-sensitive.  So if there's nothing cached, it's not context
     // sensitive.
     *aIsContextSensitive =
       !tmpStyleContext->RuleNode()->NodeHasCachedUnconditionalData(sid);
   }
 
@@ -3567,17 +3567,17 @@ ComputeValuesFromStyleRule(nsCSSProperty
 
   return ComputeValuesFromStyleContext(aProperty, aEnabledState,
                                        tmpStyleContext, aValues);
 }
 
 /* static */ bool
 StyleAnimationValue::ComputeValue(nsCSSPropertyID aProperty,
                                   dom::Element* aTargetElement,
-                                  nsStyleContext* aStyleContext,
+                                  GeckoStyleContext* aStyleContext,
                                   const nsAString& aSpecifiedValue,
                                   bool aUseSVGMode,
                                   StyleAnimationValue& aComputedValue,
                                   bool* aIsContextSensitive)
 {
   MOZ_ASSERT(aTargetElement, "null target element");
 
   // Parse specified value into a temporary css::StyleRule
@@ -3619,17 +3619,17 @@ StyleAnimationValue::ComputeValue(nsCSSP
 }
 
 template <class T>
 bool
 ComputeValuesFromSpecifiedValue(
     nsCSSPropertyID aProperty,
     CSSEnabledState aEnabledState,
     dom::Element* aTargetElement,
-    nsStyleContext* aStyleContext,
+    GeckoStyleContext* aStyleContext,
     T& aSpecifiedValue,
     bool aUseSVGMode,
     nsTArray<PropertyStyleAnimationValuePair>& aResult)
 {
   MOZ_ASSERT(aTargetElement, "null target element");
 
   // Parse specified value into a temporary css::StyleRule
   // Note: BuildStyleRule needs an element's OwnerDoc, BaseURI, and Principal.
@@ -3647,33 +3647,33 @@ ComputeValuesFromSpecifiedValue(
                                     /* aIsContextSensitive */ nullptr);
 }
 
 /* static */ bool
 StyleAnimationValue::ComputeValues(
     nsCSSPropertyID aProperty,
     CSSEnabledState aEnabledState,
     dom::Element* aTargetElement,
-    nsStyleContext* aStyleContext,
+    GeckoStyleContext* aStyleContext,
     const nsAString& aSpecifiedValue,
     bool aUseSVGMode,
     nsTArray<PropertyStyleAnimationValuePair>& aResult)
 {
   return ComputeValuesFromSpecifiedValue(aProperty, aEnabledState,
                                          aTargetElement, aStyleContext,
                                          aSpecifiedValue, aUseSVGMode,
                                          aResult);
 }
 
 /* static */ bool
 StyleAnimationValue::ComputeValues(
     nsCSSPropertyID aProperty,
     CSSEnabledState aEnabledState,
     dom::Element* aTargetElement,
-    nsStyleContext* aStyleContext,
+    GeckoStyleContext* aStyleContext,
     const nsCSSValue& aSpecifiedValue,
     bool aUseSVGMode,
     nsTArray<PropertyStyleAnimationValuePair>& aResult)
 {
   return ComputeValuesFromSpecifiedValue(aProperty, aEnabledState,
                                          aTargetElement, aStyleContext,
                                          aSpecifiedValue, aUseSVGMode,
                                          aResult);
@@ -3978,23 +3978,23 @@ SetPositionCoordValue(const Position::Co
 }
 
 /*
  * Assign |aOutput = aInput|, except with any non-pixel lengths
  * replaced with the equivalent in pixels, and any non-canonical calc()
  * expressions replaced with canonical ones.
  */
 static void
-SubstitutePixelValues(nsStyleContext* aStyleContext,
+SubstitutePixelValues(GeckoStyleContext* aStyleContext,
                       const nsCSSValue& aInput, nsCSSValue& aOutput)
 {
   if (aInput.IsCalcUnit()) {
     RuleNodeCacheConditions conditions;
     nsRuleNode::ComputedCalc c =
-      nsRuleNode::SpecifiedCalcToComputedCalc(aInput, aStyleContext->AsGecko(),
+      nsRuleNode::SpecifiedCalcToComputedCalc(aInput, aStyleContext,
                                               aStyleContext->PresContext(),
                                               conditions);
     nsStyleCoord::CalcValue c2;
     c2.mLength = c.mLength;
     c2.mPercent = c.mPercent;
     c2.mHasPercent = true; // doesn't matter for transform translate
     CalcValueToCSSValue(&c2, aOutput);
   } else if (aInput.UnitHasArrayValue()) {
@@ -4004,17 +4004,17 @@ SubstitutePixelValues(nsStyleContext* aS
     for (size_t i = 0, i_end = inputArray->Count(); i < i_end; ++i) {
       SubstitutePixelValues(aStyleContext,
                             inputArray->Item(i), outputArray->Item(i));
     }
     aOutput.SetArrayValue(outputArray, aInput.GetUnit());
   } else if (aInput.IsLengthUnit() &&
              aInput.GetUnit() != eCSSUnit_Pixel) {
     RuleNodeCacheConditions conditions;
-    nscoord len = nsRuleNode::CalcLength(aInput, aStyleContext->AsGecko(),
+    nscoord len = nsRuleNode::CalcLength(aInput, aStyleContext,
                                          aStyleContext->PresContext(),
                                          conditions);
     aOutput.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(len),
                           eCSSUnit_Pixel);
   } else {
     aOutput = aInput;
   }
 }
@@ -4228,23 +4228,23 @@ SetFallbackValue(nsCSSValuePair* aPair, 
     aPair->mYValue.SetColorValue(aPaint.GetFallbackColor());
   } else {
     aPair->mYValue.SetNoneValue();
   }
 }
 
 bool
 StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
-                                          nsStyleContext* aStyleContext,
+                                          GeckoStyleContext* aStyleContext,
                                           StyleAnimationValue& aComputedValue)
 {
   MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
              "bad property");
   const void* styleStruct =
-    aStyleContext->AsGecko()->StyleData(nsCSSProps::kSIDTable[aProperty]);
+    aStyleContext->StyleData(nsCSSProps::kSIDTable[aProperty]);
   ptrdiff_t ssOffset = nsCSSProps::kStyleStructOffsetTable[aProperty];
   nsStyleAnimType animType = nsCSSProps::kAnimTypeTable[aProperty];
   MOZ_ASSERT(0 <= ssOffset ||
              animType == eStyleAnimType_Custom ||
              animType == eStyleAnimType_Discrete,
              "all animation types other than Custom and Discrete must " \
              "specify a style struct offset to extract values from");
   switch (animType) {
@@ -5384,17 +5384,17 @@ AnimationValue::ComputeDistance(nsCSSPro
   if (mServo) {
     return Servo_AnimationValues_ComputeDistance(mServo, aOther.mServo);
   }
 
   double distance = 0.0;
   return StyleAnimationValue::ComputeDistance(aProperty,
                                               mGecko,
                                               aOther.mGecko,
-                                              aStyleContext,
+                                              aStyleContext->AsGecko(),
                                               distance)
          ? distance
          : 0.0;
 }
 
 /* static */ AnimationValue
 AnimationValue::FromString(nsCSSPropertyID aProperty,
                            const nsAString& aValue,
@@ -5435,15 +5435,16 @@ AnimationValue::FromString(nsCSSProperty
     result.mServo = presContext->StyleSet()
                                ->AsServo()
                                ->ComputeAnimationValue(aElement,
                                                        declarations,
                                                        servoContext);
     return result;
   }
 
-  if (!StyleAnimationValue::ComputeValue(aProperty, aElement, styleContext,
+  if (!StyleAnimationValue::ComputeValue(aProperty, aElement,
+                                         styleContext->AsGecko(),
                                          aValue, false /* |aUseSVGMode| */,
                                          result.mGecko)) {
     MOZ_ASSERT(result.IsNull());
   }
   return result;
 }
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -22,16 +22,18 @@
 #include "nsStyleTransformMatrix.h"
 
 class nsIFrame;
 class nsStyleContext;
 class gfx3DMatrix;
 
 namespace mozilla {
 
+class GeckoStyleContext;
+
 namespace css {
 class StyleRule;
 } // namespace css
 
 namespace dom {
 class Element;
 } // namespace dom
 
@@ -103,17 +105,17 @@ public:
    *                      translate part of transforms.
    * @param aDistance   The result of the calculation.
    * @return true on success, false on failure.
    */
   static MOZ_MUST_USE bool
   ComputeDistance(nsCSSPropertyID aProperty,
                   const StyleAnimationValue& aStartValue,
                   const StyleAnimationValue& aEndValue,
-                  nsStyleContext* aStyleContext,
+                  GeckoStyleContext* aStyleContext,
                   double& aDistance);
 
   /**
    * Calculates an interpolated value that is the specified |aPortion| between
    * the two given values.
    *
    * This really just does the following calculation:
    *   aResultValue = (1.0 - aPortion) * aStartValue + aPortion * aEndValue
@@ -199,17 +201,17 @@ public:
    *                        Note that the operation of this method is
    *                        significantly faster when |aIsContextSensitive| is
    *                        nullptr.
    * @return true on success, false on failure.
    */
   static MOZ_MUST_USE bool
   ComputeValue(nsCSSPropertyID aProperty,
                mozilla::dom::Element* aTargetElement,
-               nsStyleContext* aStyleContext,
+               mozilla::GeckoStyleContext* aStyleContext,
                const nsAString& aSpecifiedValue,
                bool aUseSVGMode,
                StyleAnimationValue& aComputedValue,
                bool* aIsContextSensitive = nullptr);
 
   /**
    * Like ComputeValue, but returns an array of StyleAnimationValues.
    *
@@ -219,30 +221,30 @@ public:
    * is used to filter the longhand components that will be appended
    * to aResult.  On failure, aResult might still have partial results
    * in it.
    */
   static MOZ_MUST_USE bool
   ComputeValues(nsCSSPropertyID aProperty,
                 mozilla::CSSEnabledState aEnabledState,
                 mozilla::dom::Element* aTargetElement,
-                nsStyleContext* aStyleContext,
+                mozilla::GeckoStyleContext* aStyleContext,
                 const nsAString& aSpecifiedValue,
                 bool aUseSVGMode,
                 nsTArray<PropertyStyleAnimationValuePair>& aResult);
 
   /**
    * A variant on ComputeValues that takes an nsCSSValue as the specified
    * value. Only longhand properties are supported.
    */
   static MOZ_MUST_USE bool
   ComputeValues(nsCSSPropertyID aProperty,
                 mozilla::CSSEnabledState aEnabledState,
                 mozilla::dom::Element* aTargetElement,
-                nsStyleContext* aStyleContext,
+                mozilla::GeckoStyleContext* aStyleContext,
                 const nsCSSValue& aSpecifiedValue,
                 bool aUseSVGMode,
                 nsTArray<PropertyStyleAnimationValuePair>& aResult);
 
   /**
    * Creates a specified value for the given computed value.
    *
    * The first two overloads fill in an nsCSSValue object; the third
@@ -283,17 +285,17 @@ public:
    *
    * @param aProperty     The property whose value we're looking up.
    * @param aStyleContext The style context to check for the computed value.
    * @param [out] aComputedValue The resulting computed value.
    * @return true on success, false on failure.
    */
   static MOZ_MUST_USE bool ExtractComputedValue(
     nsCSSPropertyID aProperty,
-    nsStyleContext* aStyleContext,
+    mozilla::GeckoStyleContext* aStyleContext,
     StyleAnimationValue& aComputedValue);
 
   static already_AddRefed<nsCSSValue::Array>
     AppendTransformFunction(nsCSSKeyword aTransformFunction,
                             nsCSSValueList**& aListTail);
 
   /**
    * The types and values for the values that we extract and animate.
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -15,20 +15,20 @@
   if (IsGecko()) { \
     return AsGecko()->method_ geckoargs_; \
   } else { \
     return AsServo()->method_ servoargs_; \
   }
 
 #define FORWARD_WITH_PARENT(method_, parent_, args_) \
   if (IsGecko()) { \
-    nsStyleContext* parent = parent_; \
+    auto* parent = parent_ ? parent_->AsGecko() : nullptr; \
     return AsGecko()->method_ args_; \
   } else { \
-    ServoStyleContext* parent = parent_ ? parent_->AsServo() : nullptr; \
+    auto* parent = parent_ ? parent_->AsServo() : nullptr; \
     return AsServo()->method_ args_; \
   }
 
 #define FORWARD(method_, args_) FORWARD_CONCRETE(method_, args_, args_)
 
 namespace mozilla {
 
 void
@@ -98,19 +98,20 @@ StyleSetHandle::Ptr::ResolveStyleFor(dom
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement,
                                      nsStyleContext* aParentContext,
                                      LazyComputeBehavior aMayCompute,
                                      TreeMatchContext* aTreeMatchContext)
 {
   if (IsGecko()) {
     MOZ_ASSERT(aTreeMatchContext);
-    return AsGecko()->ResolveStyleFor(aElement, aParentContext, aMayCompute, *aTreeMatchContext);
+    auto* parent = aParentContext ? aParentContext->AsGecko() : nullptr;
+    return AsGecko()->ResolveStyleFor(aElement, parent, aMayCompute, *aTreeMatchContext);
   } else {
-    ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+    auto* parent = aParentContext ? aParentContext->AsServo() : nullptr;
     return AsServo()->ResolveStyleFor(aElement, parent, aMayCompute);
   }
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleForText(nsIContent* aTextNode,
                                          nsStyleContext* aParentContext)
 {
@@ -278,20 +279,21 @@ StyleSetHandle::Ptr::ProbePseudoElementS
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
                                              CSSPseudoElementType aType,
                                              nsStyleContext* aParentContext,
                                              TreeMatchContext* aTreeMatchContext)
 {
   if (IsGecko()) {
     MOZ_ASSERT(aTreeMatchContext);
-    return AsGecko()->ProbePseudoElementStyle(aParentElement, aType, aParentContext,
+    auto* parent = aParentContext ? aParentContext->AsGecko() : nullptr;
+    return AsGecko()->ProbePseudoElementStyle(aParentElement, aType, parent,
                                               *aTreeMatchContext);
   }
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+  auto* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   return AsServo()->ProbePseudoElementStyle(aParentElement, aType, parent);
 }
 
 nsRestyleHint
 StyleSetHandle::Ptr::HasStateDependentStyle(dom::Element* aElement,
                                             EventStates aStateMask)
 {
   FORWARD(HasStateDependentStyle, (aElement, aStateMask));
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -356,51 +356,52 @@ PopExistingAnimation(const nsAString& aN
   }
 
   return nullptr;
 }
 
 class ResolvedStyleCache {
 public:
   ResolvedStyleCache() : mCache() {}
-  nsStyleContext* Get(nsPresContext *aPresContext,
-                      nsStyleContext *aParentStyleContext,
-                      Declaration* aKeyframeDeclaration);
+  GeckoStyleContext* Get(nsPresContext* aPresContext,
+                         GeckoStyleContext* aParentStyleContext,
+                         Declaration* aKeyframeDeclaration);
 
 private:
-  nsRefPtrHashtable<nsPtrHashKey<Declaration>, nsStyleContext> mCache;
+  nsRefPtrHashtable<nsPtrHashKey<Declaration>, GeckoStyleContext> mCache;
 };
 
-nsStyleContext*
-ResolvedStyleCache::Get(nsPresContext *aPresContext,
-                        nsStyleContext *aParentStyleContext,
+GeckoStyleContext*
+ResolvedStyleCache::Get(nsPresContext* aPresContext,
+                        GeckoStyleContext* aParentStyleContext,
                         Declaration* aKeyframeDeclaration)
 {
   // FIXME (spec):  The css3-animations spec isn't very clear about how
   // properties are resolved when they have values that depend on other
   // properties (e.g., values in 'em').  I presume that they're resolved
   // relative to the other styles of the element.  The question is
   // whether they are resolved relative to other animations:  I assume
   // that they're not, since that would prevent us from caching a lot of
   // data that we'd really like to cache (in particular, the
   // StyleAnimationValue values in AnimationPropertySegment).
-  nsStyleContext *result = mCache.GetWeak(aKeyframeDeclaration);
+  GeckoStyleContext* result = mCache.GetWeak(aKeyframeDeclaration);
   if (!result) {
     aKeyframeDeclaration->SetImmutable();
     // The spec says that !important declarations should just be ignored
     MOZ_ASSERT(!aKeyframeDeclaration->HasImportantData(),
                "Keyframe rule has !important data");
 
     nsCOMArray<nsIStyleRule> rules;
     rules.AppendObject(aKeyframeDeclaration);
     MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
                "ServoStyleSet should not use nsAnimationManager for "
                "animations");
-    RefPtr<nsStyleContext> resultStrong = aPresContext->StyleSet()->AsGecko()->
-      ResolveStyleByAddingRules(aParentStyleContext, rules);
+    RefPtr<GeckoStyleContext> resultStrong =
+      aPresContext->StyleSet()->AsGecko()->
+        ResolveStyleByAddingRules(aParentStyleContext, rules);
     mCache.Put(aKeyframeDeclaration, resultStrong);
     result = resultStrong;
   }
   return result;
 }
 
 class MOZ_STACK_CLASS ServoCSSAnimationBuilder final {
 public:
@@ -428,32 +429,32 @@ public:
   }
 
 private:
   const ServoStyleContext* mStyleContext;
 };
 
 class MOZ_STACK_CLASS GeckoCSSAnimationBuilder final {
 public:
-  GeckoCSSAnimationBuilder(nsStyleContext* aStyleContext,
+  GeckoCSSAnimationBuilder(GeckoStyleContext* aStyleContext,
                            const NonOwningAnimationTarget& aTarget)
     : mStyleContext(aStyleContext)
     , mTarget(aTarget)
   {
     MOZ_ASSERT(aStyleContext);
     MOZ_ASSERT(aTarget.mElement);
   }
 
   bool BuildKeyframes(nsPresContext* aPresContext,
                       const StyleAnimation& aSrc,
                       nsTArray<Keyframe>& aKeyframs);
   void SetKeyframes(KeyframeEffectReadOnly& aEffect,
                     nsTArray<Keyframe>&& aKeyframes)
   {
-    aEffect.SetKeyframes(Move(aKeyframes), mStyleContext->AsGecko());
+    aEffect.SetKeyframes(Move(aKeyframes), mStyleContext);
   }
 
 private:
   nsTArray<Keyframe> BuildAnimationFrames(nsPresContext* aPresContext,
                                           const StyleAnimation& aSrc,
                                           const nsCSSKeyframesRule* aRule);
   Maybe<ComputedTimingFunction> GetKeyframeTimingFunction(
     nsPresContext* aPresContext,
@@ -465,17 +466,17 @@ private:
     nsCSSPropertyIDSet& aAnimatedProperties);
   void FillInMissingKeyframeValues(
     nsCSSPropertyIDSet aAnimatedProperties,
     nsCSSPropertyIDSet aPropertiesSetAtStart,
     nsCSSPropertyIDSet aPropertiesSetAtEnd,
     const Maybe<ComputedTimingFunction>& aInheritedTimingFunction,
     nsTArray<Keyframe>& aKeyframes);
 
-  RefPtr<nsStyleContext> mStyleContext;
+  RefPtr<GeckoStyleContext> mStyleContext;
   NonOwningAnimationTarget mTarget;
 
   ResolvedStyleCache mResolvedStyles;
 };
 
 static Maybe<ComputedTimingFunction>
 ConvertTimingFunction(const nsTimingFunction& aTimingFunction);
 
@@ -838,17 +839,17 @@ ConvertTimingFunction(const nsTimingFunc
 
 nsTArray<PropertyValuePair>
 GeckoCSSAnimationBuilder::GetKeyframePropertyValues(
     nsPresContext* aPresContext,
     nsCSSKeyframeRule* aKeyframeRule,
     nsCSSPropertyIDSet& aAnimatedProperties)
 {
   nsTArray<PropertyValuePair> result;
-  RefPtr<nsStyleContext> styleContext =
+  RefPtr<GeckoStyleContext> styleContext =
     mResolvedStyles.Get(aPresContext, mStyleContext,
                         aKeyframeRule->Declaration());
 
   for (nsCSSPropertyID prop = nsCSSPropertyID(0);
        prop < eCSSProperty_COUNT_no_shorthands;
        prop = nsCSSPropertyID(prop + 1)) {
     if (nsCSSProps::kAnimTypeTable[prop] == eStyleAnimType_None ||
         !aKeyframeRule->Declaration()->HasNonImportantValueFor(prop)) {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -450,28 +450,28 @@ public:
 
       mOldSkipAnimationRules = mRestyleManager->SkipAnimationRules();
       mRestyleManager->SetSkipAnimationRules(true);
     } else {
       NS_WARNING("stylo: can't skip animaition rules yet");
     }
   }
 
-  already_AddRefed<nsStyleContext>
-  ResolveWithAnimation(StyleSetHandle aStyleSet,
+  already_AddRefed<GeckoStyleContext>
+  ResolveWithAnimation(nsStyleSet* aStyleSet,
                        Element* aElement,
                        CSSPseudoElementType aType,
-                       nsStyleContext* aParentContext,
+                       GeckoStyleContext* aParentContext,
                        nsComputedDOMStyle::StyleType aStyleType,
                        bool aInDocWithShell)
   {
     MOZ_ASSERT(mAnimationFlag == nsComputedDOMStyle::eWithAnimation,
       "AnimationFlag should be eWithAnimation");
 
-    RefPtr<nsStyleContext> result;
+    RefPtr<GeckoStyleContext> result;
 
     if (aType != CSSPseudoElementType::NotPseudo) {
       nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
       Element* pseudoElement =
         frame && aInDocWithShell ? frame->GetPseudoElement(aType) : nullptr;
       result = aStyleSet->ResolvePseudoElementStyle(aElement, aType,
                                                     aParentContext,
                                                     pseudoElement);
@@ -495,49 +495,45 @@ public:
       // most important, so we have to reverse the list.
       // Integer division to get "stop" is purposeful here: if length is odd, we
       // don't have to do anything with the middle element of the array.
       for (uint32_t i = 0, length = rules.Length(), stop = length / 2;
            i < stop; ++i) {
         rules[i].swap(rules[length - i - 1]);
       }
 
-      result = aStyleSet->AsGecko()->ResolveStyleForRules(aParentContext,
-                                                          rules);
+      result = aStyleSet->ResolveStyleForRules(aParentContext, rules);
     }
     return result.forget();
   }
 
-  already_AddRefed<nsStyleContext>
-  ResolveWithoutAnimation(StyleSetHandle aStyleSet,
+  already_AddRefed<GeckoStyleContext>
+  ResolveWithoutAnimation(nsStyleSet* aStyleSet,
                           Element* aElement,
                           CSSPseudoElementType aType,
-                          nsStyleContext* aParentContext,
+                          GeckoStyleContext* aParentContext,
                           bool aInDocWithShell)
   {
-    MOZ_ASSERT(!aStyleSet->IsServo(),
-      "Servo backend should not use this function");
     MOZ_ASSERT(mAnimationFlag == nsComputedDOMStyle::eWithoutAnimation,
       "AnimationFlag should be eWithoutAnimation");
 
-    RefPtr<nsStyleContext> result;
+    RefPtr<GeckoStyleContext> result;
 
     if (aType != CSSPseudoElementType::NotPseudo) {
       nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
       Element* pseudoElement =
         frame && aInDocWithShell ? frame->GetPseudoElement(aType) : nullptr;
       result =
-        aStyleSet->AsGecko()->ResolvePseudoElementStyleWithoutAnimation(
+        aStyleSet->ResolvePseudoElementStyleWithoutAnimation(
           aElement, aType,
           aParentContext,
           pseudoElement);
     } else {
       result =
-        aStyleSet->AsGecko()->ResolveStyleWithoutAnimation(aElement,
-                                                           aParentContext);
+        aStyleSet->ResolveStyleWithoutAnimation(aElement, aParentContext);
     }
     return result.forget();
   }
 
   ~StyleResolver()
   {
     if (mRestyleManager) {
       mRestyleManager->SetSkipAnimationRules(mOldSkipAnimationRules);
@@ -633,17 +629,18 @@ nsComputedDOMStyle::DoGetStyleContextNoF
         // The existing style context may have animation styles so check if we
         // need to remove them.
         if (aAnimationFlag == eWithoutAnimation) {
           nsPresContext* presContext = presShell->GetPresContext();
           MOZ_ASSERT(presContext, "Should have a prescontext if we have a frame");
           if (presContext && presContext->StyleSet()->IsGecko()) {
             nsStyleSet* styleSet = presContext->StyleSet()->AsGecko();
             return styleSet->ResolveStyleByRemovingAnimation(
-                     aElement, result, eRestyle_AllHintsWithAnimations);
+                     aElement, result->AsGecko(),
+                     eRestyle_AllHintsWithAnimations);
           } else {
               return presContext->StyleSet()->AsServo()->
                 GetBaseContextForElement(aElement, nullptr, presContext,
                                          aPseudo, pseudoType, result->AsServo());
           }
         }
 
         // this function returns an addrefed style context
@@ -663,45 +660,48 @@ nsComputedDOMStyle::DoGetStyleContextNoF
   StyleSetHandle styleSet = presShell->StyleSet();
 
   // For Servo, compute the result directly without recursively building up
   // a throwaway style context chain.
   if (ServoStyleSet* servoSet = styleSet->GetAsServo()) {
     StyleRuleInclusion rules = aStyleType == eDefaultOnly
                                ? StyleRuleInclusion::DefaultOnly
                                : StyleRuleInclusion::All;
-    RefPtr<nsStyleContext> result =
+    RefPtr<ServoStyleContext> result =
        servoSet->ResolveTransientStyle(aElement, pseudoType, aPseudo, rules);
     if (aAnimationFlag == eWithAnimation) {
       return result.forget();
     }
 
     return servoSet->GetBaseContextForElement(aElement, nullptr, presContext,
-                                              aPseudo, pseudoType, result->AsServo());
-  }
-
-  RefPtr<nsStyleContext> parentContext;
+                                              aPseudo, pseudoType, result);
+  }
+
+  RefPtr<GeckoStyleContext> parentContext;
   nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
   // Don't resolve parent context for document fragments.
   if (parent && parent->IsElement()) {
-    parentContext = GetStyleContextNoFlush(parent->AsElement(), nullptr,
-                                           aPresShell, aStyleType);
+    RefPtr<nsStyleContext> p =
+      GetStyleContextNoFlush(parent->AsElement(), nullptr,
+                             aPresShell, aStyleType);
+    MOZ_ASSERT(p && p->IsGecko());
+    parentContext = GeckoStyleContext::TakeRef(p.forget());
   }
 
   StyleResolver styleResolver(presContext, aAnimationFlag);
 
   if (aAnimationFlag == eWithAnimation) {
-    return styleResolver.ResolveWithAnimation(styleSet,
+    return styleResolver.ResolveWithAnimation(styleSet->AsGecko(),
                                               aElement, pseudoType,
                                               parentContext,
                                               aStyleType,
                                               inDocWithShell);
   }
 
-  return styleResolver.ResolveWithoutAnimation(styleSet,
+  return styleResolver.ResolveWithoutAnimation(styleSet->AsGecko(),
                                                aElement, pseudoType,
                                                parentContext,
                                                inDocWithShell);
 }
 
 nsMargin
 nsComputedDOMStyle::GetAdjustedValuesForBoxSizing()
 {
@@ -935,17 +935,18 @@ nsComputedDOMStyle::UpdateCurrentStyleSo
 
   if (mAnimationFlag == eWithoutAnimation) {
     // We will support Servo in bug 1311257.
     MOZ_ASSERT(mPresShell->StyleSet()->IsGecko(),
                "eWithoutAnimationRules support Gecko only");
     nsStyleSet* styleSet = mPresShell->StyleSet()->AsGecko();
     RefPtr<nsStyleContext> unanimatedStyleContext =
       styleSet->ResolveStyleByRemovingAnimation(
-        mContent->AsElement(), mStyleContext, eRestyle_AllHintsWithAnimations);
+        mContent->AsElement(), mStyleContext->AsGecko(),
+        eRestyle_AllHintsWithAnimations);
     SetResolvedStyleContext(Move(unanimatedStyleContext), currentGeneration);
   }
 
   // mExposeVisitedStyle is set to true only by testing APIs that
   // require chrome privilege.
   MOZ_ASSERT(!mExposeVisitedStyle || nsContentUtils::IsCallerChrome(),
              "mExposeVisitedStyle set incorrectly");
   if (mExposeVisitedStyle && mStyleContext->RelevantLinkVisited()) {
@@ -5440,17 +5441,17 @@ nsComputedDOMStyle::GetLineHeightCoord(n
     } else {
       GetCBContentHeight(blockHeight);
     }
   }
 
   // lie about font size inflation since we lie about font size (since
   // the inflation only applies to text)
   aCoord = ReflowInput::CalcLineHeight(mContent, mStyleContext,
-                                             blockHeight, 1.0f);
+                                       blockHeight, 1.0f);
 
   // CalcLineHeight uses font->mFont.size, but we want to use
   // font->mSize as the font size.  Adjust for that.  Also adjust for
   // the text zoom, if any.
   const nsStyleFont* font = StyleFont();
   float fCoord = float(aCoord);
   if (font->mAllowZoom) {
     fCoord /= mPresShell->GetPresContext()->EffectiveTextZoom();
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -133,63 +133,16 @@ nsStyleContext::FinishConstruction()
   SetStyleBits();
 
   #define eStyleStruct_LastItem (nsStyleStructID_Length - 1)
   static_assert(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
                 "NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
   #undef eStyleStruct_LastItem
 }
 
-void
-nsStyleContext::MoveTo(nsStyleContext* aNewParent)
-{
-  MOZ_ASSERT(aNewParent != mParent);
-
-  // This function shouldn't be getting called if the parents have different
-  // values for some flags in mBits (unless the flag is also set on this style
-  // context) because if that were the case we would need to recompute those
-  // bits for |this|.
-
-#define CHECK_FLAG(bit_) \
-  MOZ_ASSERT((mParent->mBits & (bit_)) == (aNewParent->mBits & (bit_)) ||     \
-             (mBits & (bit_)),                                                \
-             "MoveTo cannot be called if " #bit_ " value on old and new "     \
-             "style context parents do not match, unless the flag is set "    \
-             "on this style context");
-
-  CHECK_FLAG(NS_STYLE_HAS_PSEUDO_ELEMENT_DATA)
-  CHECK_FLAG(NS_STYLE_IN_DISPLAY_NONE_SUBTREE)
-  CHECK_FLAG(NS_STYLE_HAS_TEXT_DECORATION_LINES)
-  CHECK_FLAG(NS_STYLE_RELEVANT_LINK_VISITED)
-
-#undef CHECK_FLAG
-
-  // Assertions checking for visited style are just to avoid some tricky
-  // cases we can't be bothered handling at the moment.
-  MOZ_ASSERT(!IsStyleIfVisited());
-  MOZ_ASSERT(!mParent->IsStyleIfVisited());
-  MOZ_ASSERT(!aNewParent->IsStyleIfVisited());
-  auto styleIfVisited = GetStyleIfVisited();
-  MOZ_ASSERT(!styleIfVisited || styleIfVisited->mParent == mParent);
-
-  if (mParent->HasChildThatUsesResetStyle()) {
-    aNewParent->AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE);
-  }
-
-  mParent->RemoveChild(this);
-  mParent = aNewParent;
-  mParent->AddChild(this);
-
-  if (styleIfVisited) {
-    styleIfVisited->mParent->RemoveChild(styleIfVisited);
-    styleIfVisited->mParent = aNewParent;
-    styleIfVisited->mParent->AddChild(styleIfVisited);
-  }
-}
-
 nsChangeHint
 nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext,
                                     uint32_t* aEqualStructs,
                                     uint32_t* aSamePointerStructs,
                                     uint32_t aRelevantStructs)
 {
   AUTO_PROFILER_LABEL("nsStyleContext::CalcStyleDifference", CSS);
 
@@ -530,17 +483,17 @@ nsStyleContext::Destroy()
     presContext->PresShell()->
       FreeByObjectID(eArenaObjectID_GeckoStyleContext, this);
   } else {
     delete static_cast<ServoStyleContext*>(this);
   }
 }
 
 already_AddRefed<GeckoStyleContext>
-NS_NewStyleContext(nsStyleContext* aParentContext,
+NS_NewStyleContext(GeckoStyleContext* aParentContext,
                    nsIAtom* aPseudoTag,
                    CSSPseudoElementType aPseudoType,
                    nsRuleNode* aRuleNode,
                    bool aSkipParentDisplayBasedStyleFixup)
 {
   RefPtr<nsRuleNode> node = aRuleNode;
   RefPtr<GeckoStyleContext> context =
     new (aRuleNode->PresContext())
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -309,25 +309,16 @@ public:
   static nscolor CombineVisitedColors(nscolor *aColors,
                                       bool aLinkIsVisited);
 
   /**
    * Start the background image loads for this style context.
    */
   inline void StartBackgroundImageLoads();
 
-  /**
-   * Moves this style context to a new parent.
-   *
-   * This function violates style context tree immutability, and
-   * is a very low-level function and should only be used after verifying
-   * many conditions that make it safe to call.
-   */
-  void MoveTo(nsStyleContext* aNewParent);
-
 #ifdef DEBUG
   void List(FILE* out, int32_t aIndent, bool aListDescendants = true);
   static const char* StructName(nsStyleStructID aSID);
   static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
 #endif
 
 protected:
   // protected destructor to discourage deletion outside of Release()
@@ -382,15 +373,15 @@ protected:
               nsCachedStyleData::GetBitForSID(aInnerSID));
   }
 
   static const uint32_t sDependencyTable[];
 #endif
 };
 
 already_AddRefed<mozilla::GeckoStyleContext>
-NS_NewStyleContext(nsStyleContext* aParentContext,
+NS_NewStyleContext(mozilla::GeckoStyleContext* aParentContext,
                    nsIAtom* aPseudoTag,
                    mozilla::CSSPseudoElementType aPseudoType,
                    nsRuleNode* aRuleNode,
                    bool aSkipParentDisplayBasedStyleFixup);
 
 #endif
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -858,18 +858,18 @@ ReplaceAnimationRule(nsRuleNode *aOldRul
 }
 
 /**
  * |GetContext| implements sharing of style contexts (not just the data
  * on the rule nodes) between siblings and cousins of the same
  * generation.  (It works for cousins of the same generation since
  * |aParentContext| could itself be a shared context.)
  */
-already_AddRefed<nsStyleContext>
-nsStyleSet::GetContext(nsStyleContext* aParentContext,
+already_AddRefed<GeckoStyleContext>
+nsStyleSet::GetContext(GeckoStyleContext* aParentContext,
                        nsRuleNode* aRuleNode,
                        // aVisitedRuleNode may be null; if it is null
                        // it means that we don't need to force creation
                        // of a StyleIfVisited.  (But if we make one
                        // because aParentContext has one, then aRuleNode
                        // should be used.)
                        nsRuleNode* aVisitedRuleNode,
                        nsIAtom* aPseudoTag,
@@ -889,17 +889,17 @@ nsStyleSet::GetContext(nsStyleContext* a
   if (aVisitedRuleNode == aRuleNode) {
     // No need to force creation of a visited style in this case.
     aVisitedRuleNode = nullptr;
   }
 
   // Ensure |aVisitedRuleNode != nullptr| corresponds to the need to
   // create an if-visited style context, and that in that case, we have
   // parentIfVisited set correctly.
-  nsStyleContext *parentIfVisited =
+  GeckoStyleContext *parentIfVisited =
     aParentContext ? aParentContext->GetStyleIfVisited() : nullptr;
   if (parentIfVisited) {
     if (!aVisitedRuleNode) {
       aVisitedRuleNode = aRuleNode;
     }
   } else {
     if (aVisitedRuleNode) {
       parentIfVisited = aParentContext;
@@ -912,17 +912,17 @@ nsStyleSet::GetContext(nsStyleContext* a
     // only the visitedness of the relevant link should influence style.
     parentIfVisited = aParentContext;
   }
 
   bool relevantLinkVisited = (aFlags & eIsLink) ?
     (aFlags & eIsVisitedLink) :
     (aParentContext && aParentContext->RelevantLinkVisited());
 
-  RefPtr<nsStyleContext> result;
+  RefPtr<GeckoStyleContext> result;
   if (aParentContext)
     result = aParentContext->AsGecko()->FindChildWithRules(aPseudoTag, aRuleNode,
                                                 aVisitedRuleNode,
                                                 relevantLinkVisited);
 
   if (!result) {
     // |aVisitedRuleNode| may have a ref-count of zero since we are yet
     // to create the style context that will hold an owning reference to it.
@@ -930,17 +930,17 @@ nsStyleSet::GetContext(nsStyleContext* a
     // in case something in the first call to NS_NewStyleContext triggers a
     // GC sweep of rule nodes.
     RefPtr<nsRuleNode> kungFuDeathGrip{aVisitedRuleNode};
 
     result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType,
                                 aRuleNode,
                                 aFlags & eSkipParentDisplayBasedStyleFixup);
     if (aVisitedRuleNode) {
-      RefPtr<nsStyleContext> resultIfVisited =
+      RefPtr<GeckoStyleContext> resultIfVisited =
         NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType,
                            aVisitedRuleNode,
                            aFlags & eSkipParentDisplayBasedStyleFixup);
       resultIfVisited->SetIsStyleIfVisited();
       result->AsGecko()->SetStyleIfVisited(resultIfVisited.forget());
 
       if (relevantLinkVisited) {
         result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
@@ -1321,29 +1321,29 @@ nsStyleSet::WalkRuleProcessors(nsIStyleR
 static void
 InitStyleScopes(TreeMatchContext& aTreeContext, Element* aElement)
 {
   if (aElement->IsElementInStyleScope()) {
     aTreeContext.InitStyleScopes(aElement->GetParentElementCrossingShadowRoot());
   }
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleFor(Element* aElement,
-                            nsStyleContext* aParentContext)
+                            GeckoStyleContext* aParentContext)
 {
   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
                                aElement->OwnerDoc());
   InitStyleScopes(treeContext, aElement);
   return ResolveStyleFor(aElement, aParentContext, treeContext);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleForInternal(Element* aElement,
-                                    nsStyleContext* aParentContext,
+                                    GeckoStyleContext* aParentContext,
                                     TreeMatchContext& aTreeMatchContext,
                                     AnimationFlag aAnimationFlag)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
   NS_ASSERTION(aElement, "aElement must not be null");
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   aTreeMatchContext.ResetForUnvisitedMatching();
@@ -1376,29 +1376,29 @@ nsStyleSet::ResolveStyleForInternal(Elem
     flags |= eSkipParentDisplayBasedStyleFixup;
   }
 
   return GetContext(aParentContext, ruleNode, visitedRuleNode,
                     nullptr, CSSPseudoElementType::NotPseudo,
                     aElement, flags);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleFor(Element* aElement,
-                            nsStyleContext* aParentContext,
+                            GeckoStyleContext* aParentContext,
                             TreeMatchContext& aTreeMatchContext)
 {
   return ResolveStyleForInternal(aElement,
                                  aParentContext,
                                  aTreeMatchContext,
                                  eWithAnimation);
 }
 
-already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
+already_AddRefed<GeckoStyleContext>
+nsStyleSet::ResolveStyleForRules(GeckoStyleContext* aParentContext,
                                  const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   // FIXME: Perhaps this should be passed in, but it probably doesn't
   // matter.
   ruleWalker.SetLevel(SheetType::Doc, false, false);
@@ -1406,18 +1406,18 @@ nsStyleSet::ResolveStyleForRules(nsStyle
     ruleWalker.ForwardOnPossiblyCSSRule(aRules.ElementAt(i));
   }
 
   return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
                     nullptr, CSSPseudoElementType::NotPseudo,
                     nullptr, eNoFlags);
 }
 
-already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
+already_AddRefed<GeckoStyleContext>
+nsStyleSet::ResolveStyleByAddingRules(GeckoStyleContext* aBaseContext,
                                       const nsCOMArray<nsIStyleRule> &aRules)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   ruleWalker.SetCurrentNode(aBaseContext->RuleNode());
   // This needs to be the transition sheet because that is the highest
   // level of the cascade, and thus the only thing that makes sense if
@@ -1695,45 +1695,45 @@ nsStyleSet::RuleNodeWithReplacement(Elem
   NS_ASSERTION(rulesIndex == 0,
                "rules are in incorrect cascading order, "
                "which means we replaced them incorrectly");
 
   return ruleWalker.CurrentNode();
 }
 
 static bool
-SkipsParentDisplayBasedStyleFixup(nsStyleContext* aStyleContext)
+SkipsParentDisplayBasedStyleFixup(GeckoStyleContext* aStyleContext)
 {
   CSSPseudoElementType type = aStyleContext->GetPseudoType();
   switch (type) {
     case CSSPseudoElementType::InheritingAnonBox:
     case CSSPseudoElementType::NonInheritingAnonBox:
        return true;
     case CSSPseudoElementType::NotPseudo:
        return false;
     default:
        return !nsCSSPseudoElements::PseudoElementIsFlexOrGridItem(type);
   }
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleWithReplacement(Element* aElement,
                                         Element* aPseudoElement,
-                                        nsStyleContext* aNewParentContext,
-                                        nsStyleContext* aOldStyleContext,
+                                        GeckoStyleContext* aNewParentContext,
+                                        GeckoStyleContext* aOldStyleContext,
                                         nsRestyleHint aReplacements,
                                         uint32_t aFlags)
 {
   nsRuleNode* ruleNode =
     RuleNodeWithReplacement(aElement, aPseudoElement,
                             aOldStyleContext->RuleNode(),
                             aOldStyleContext->GetPseudoType(), aReplacements);
 
   nsRuleNode* visitedRuleNode = nullptr;
-  nsStyleContext* oldStyleIfVisited = aOldStyleContext->GetStyleIfVisited();
+  GeckoStyleContext* oldStyleIfVisited = aOldStyleContext->GetStyleIfVisited();
   if (oldStyleIfVisited) {
     if (oldStyleIfVisited->RuleNode() == aOldStyleContext->RuleNode()) {
       visitedRuleNode = ruleNode;
     } else {
       visitedRuleNode =
         RuleNodeWithReplacement(aElement, aPseudoElement,
                                 oldStyleIfVisited->RuleNode(),
                                 oldStyleIfVisited->GetPseudoType(),
@@ -1794,19 +1794,19 @@ nsStyleSet::ResolveStyleWithReplacement(
     flags |= eSkipParentDisplayBasedStyleFixup;
   }
 
   return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
                     aOldStyleContext->GetPseudo(), pseudoType,
                     elementForAnimation, flags);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleByRemovingAnimation(dom::Element* aTarget,
-                                            nsStyleContext* aStyleContext,
+                                            GeckoStyleContext* aStyleContext,
                                             nsRestyleHint aWhichToRemove)
 {
 #ifdef DEBUG
   CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
 #endif
   MOZ_ASSERT(pseudoType == CSSPseudoElementType::NotPseudo ||
              pseudoType == CSSPseudoElementType::before ||
              pseudoType == CSSPseudoElementType::after,
@@ -1815,84 +1815,85 @@ nsStyleSet::ResolveStyleByRemovingAnimat
              "stylo: the style set and restyle manager must have the same "
              "StyleBackendType");
   GeckoRestyleManager* restyleManager =
     PresContext()->RestyleManager()->AsGecko();
 
   bool oldSkipAnimationRules = restyleManager->SkipAnimationRules();
   restyleManager->SetSkipAnimationRules(true);
 
-  RefPtr<nsStyleContext> result =
+  RefPtr<GeckoStyleContext> result =
     ResolveStyleWithReplacement(aTarget, nullptr, aStyleContext->GetParent(),
                                 aStyleContext, aWhichToRemove,
                                 eSkipStartingAnimations);
 
   restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
 
   return result.forget();
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleWithoutAnimation(Element* aTarget,
-                                         nsStyleContext* aParentContext)
+                                         GeckoStyleContext* aParentContext)
 {
   GeckoRestyleManager* restyleManager =
     PresContext()->RestyleManager()->AsGecko();
 
   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
                                aTarget->OwnerDoc());
   InitStyleScopes(treeContext, aTarget);
 
   bool oldSkipAnimationRules = restyleManager->SkipAnimationRules();
   restyleManager->SetSkipAnimationRules(true);
 
   // Here we can call ResolveStyleForInternal() instead of
   // ResolveStyleWithReplacement() since we don't need any animation rules
   // (CSS Animations, Transitions and script animations). That's because
   // EffectCompositor::GetAnimationRule() skips all of animations rules if
   // SkipAnimationRules flag is true.
-  RefPtr<nsStyleContext> result = ResolveStyleForInternal(aTarget,
-                                                          aParentContext,
-                                                          treeContext,
-                                                          eWithoutAnimation);
+  RefPtr<GeckoStyleContext> result =
+    ResolveStyleForInternal(aTarget,
+                            aParentContext,
+                            treeContext,
+                            eWithoutAnimation);
 
   restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
 
   return result.forget();
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleForText(nsIContent* aTextNode,
-                                nsStyleContext* aParentContext)
+                                GeckoStyleContext* aParentContext)
 {
   MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
   return GetContext(aParentContext, mRuleTree, nullptr,
                     nsCSSAnonBoxes::mozText,
                     CSSPseudoElementType::InheritingAnonBox, nullptr, eNoFlags);
 }
 
-already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
+already_AddRefed<GeckoStyleContext>
+nsStyleSet::ResolveStyleForFirstLetterContinuation(GeckoStyleContext* aParentContext)
 {
   return GetContext(aParentContext, mRuleTree, nullptr,
                     nsCSSAnonBoxes::firstLetterContinuation,
                     CSSPseudoElementType::InheritingAnonBox, nullptr, eNoFlags);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveStyleForPlaceholder()
 {
-  RefPtr<nsStyleContext>& cache =
+  RefPtr<GeckoStyleContext>& cache =
     mNonInheritingStyleContexts[nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
   if (cache) {
-    RefPtr<nsStyleContext> retval = cache;
+    RefPtr<GeckoStyleContext> retval = cache;
     return retval.forget();
   }
 
-  RefPtr<nsStyleContext> retval =
+  RefPtr<GeckoStyleContext> retval =
     GetContext(nullptr, mRuleTree, nullptr,
                nsCSSAnonBoxes::oofPlaceholder,
                CSSPseudoElementType::NonInheritingAnonBox, nullptr, eNoFlags);
   cache = retval;
   return retval.forget();
 }
 
 void
@@ -1912,21 +1913,21 @@ nsStyleSet::WalkRestrictionRule(CSSPseud
 void
 nsStyleSet::WalkDisableTextZoomRule(Element* aElement, nsRuleWalker* aRuleWalker)
 {
   aRuleWalker->SetLevel(SheetType::Agent, false, false);
   if (aElement->IsSVGElement(nsGkAtoms::text))
     aRuleWalker->Forward(mDisableTextZoomStyleRule);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolvePseudoElementStyleInternal(
   Element* aParentElement,
   CSSPseudoElementType aType,
-  nsStyleContext* aParentContext,
+  GeckoStyleContext* aParentContext,
   Element* aPseudoElement,
   AnimationFlag aAnimationFlag)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   NS_ASSERTION(aType < CSSPseudoElementType::Count,
                "must have pseudo element type");
   NS_ASSERTION(aParentElement, "Must have parent element");
@@ -1970,59 +1971,59 @@ nsStyleSet::ResolvePseudoElementStyleInt
     flags |= eSkipParentDisplayBasedStyleFixup;
   }
 
   return GetContext(aParentContext, ruleNode, visitedRuleNode,
                     nsCSSPseudoElements::GetPseudoAtom(aType), aType,
                     aParentElement, flags);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
                                       CSSPseudoElementType aType,
-                                      nsStyleContext* aParentContext,
+                                      GeckoStyleContext* aParentContext,
                                       Element* aPseudoElement)
 {
   return ResolvePseudoElementStyleInternal(aParentElement,
                                            aType,
                                            aParentContext,
                                            aPseudoElement,
                                            eWithAnimation);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolvePseudoElementStyleWithoutAnimation(
   Element* aParentElement,
   CSSPseudoElementType aType,
-  nsStyleContext* aParentContext,
+  GeckoStyleContext* aParentContext,
   Element* aPseudoElement)
 {
   return ResolvePseudoElementStyleInternal(aParentElement,
                                            aType,
                                            aParentContext,
                                            aPseudoElement,
                                            eWithoutAnimation);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
                                     CSSPseudoElementType aType,
-                                    nsStyleContext* aParentContext)
+                                    GeckoStyleContext* aParentContext)
 {
   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
                                aParentElement->OwnerDoc());
   InitStyleScopes(treeContext, aParentElement);
   return ProbePseudoElementStyle(aParentElement, aType, aParentContext,
                                  treeContext);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
                                     CSSPseudoElementType aType,
-                                    nsStyleContext* aParentContext,
+                                    GeckoStyleContext* aParentContext,
                                     TreeMatchContext& aTreeMatchContext)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   NS_ASSERTION(aType < CSSPseudoElementType::Count,
                "must have pseudo element type");
   NS_ASSERTION(aParentElement, "aParentElement must not be null");
 
@@ -2063,17 +2064,17 @@ nsStyleSet::ProbePseudoElementStyle(Elem
   }
 
   if (!nsCSSPseudoElements::PseudoElementIsFlexOrGridItem(aType)) {
     // Only pseudo-elements that act as items in flex and grid containers
     // have parent display-based style fixup.
     flags |= eSkipParentDisplayBasedStyleFixup;
   }
 
-  RefPtr<nsStyleContext> result =
+  RefPtr<GeckoStyleContext> result =
     GetContext(aParentContext, ruleNode, visitedRuleNode,
                pseudoTag, aType,
                aParentElement, flags);
 
   // For :before and :after pseudo-elements, having display: none or no
   // 'content' property is equivalent to not having the pseudo-element
   // at all.
   if (result &&
@@ -2086,19 +2087,19 @@ nsStyleSet::ProbePseudoElementStyle(Elem
         content->ContentCount() == 0) {
       result = nullptr;
     }
   }
 
   return result.forget();
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
-                                               nsStyleContext* aParentContext)
+                                               GeckoStyleContext* aParentContext)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
 #ifdef DEBUG
     bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
                      !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag)
 #ifdef MOZ_XUL
                  && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
@@ -2132,62 +2133,62 @@ nsStyleSet::ResolveInheritingAnonymousBo
     }
   }
 
   return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
                     aPseudoTag, CSSPseudoElementType::InheritingAnonBox,
                     nullptr, eSkipParentDisplayBasedStyleFixup);
 }
 
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
 #ifdef DEBUG
     bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
                      nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag)
 #ifdef MOZ_XUL
                  && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
 #endif
       ;
     NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
 #endif
 
   nsCSSAnonBoxes::NonInheriting type =
     nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(aPseudoTag);
-  RefPtr<nsStyleContext>& cache = mNonInheritingStyleContexts[type];
+  RefPtr<GeckoStyleContext>& cache = mNonInheritingStyleContexts[type];
   if (cache) {
-    RefPtr<nsStyleContext> retval = cache;
+    RefPtr<GeckoStyleContext> retval = cache;
     return retval.forget();
   }
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker);
   FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nullptr,
             &ruleWalker);
 
   MOZ_ASSERT(aPseudoTag != nsCSSAnonBoxes::pageContent,
              "If nsCSSAnonBoxes::pageContent ends up non-inheriting, move the "
              "@page handling from ResolveInheritingAnonymousBoxStyle to "
              "ResolveNonInheritingAnonymousBoxStyle");
 
-  RefPtr<nsStyleContext> retval =
+  RefPtr<GeckoStyleContext> retval =
     GetContext(nullptr, ruleWalker.CurrentNode(), nullptr,
                aPseudoTag, CSSPseudoElementType::NonInheritingAnonBox,
                nullptr, eNoFlags);
   cache = retval;
   return retval.forget();
 }
 
 #ifdef MOZ_XUL
-already_AddRefed<nsStyleContext>
+already_AddRefed<GeckoStyleContext>
 nsStyleSet::ResolveXULTreePseudoStyle(Element* aParentElement,
                                       nsICSSAnonBoxPseudo* aPseudoTag,
-                                      nsStyleContext* aParentContext,
+                                      GeckoStyleContext* aParentContext,
                                       nsICSSPseudoComparator* aComparator)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   NS_ASSERTION(aPseudoTag, "must have pseudo tag");
   NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
                "Unexpected pseudo");
 
@@ -2456,42 +2457,42 @@ nsStyleSet::GCRuleTrees()
 #ifdef DEBUG
   NS_ASSERTION(!mOldRootNode, "Should have GCed old root node");
   mOldRootNode = nullptr;
 #endif
   mUnusedRuleNodeCount = 0;
   mInGC = false;
 }
 
-already_AddRefed<nsStyleContext>
-nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
-                                 nsStyleContext* aNewParentContext,
+already_AddRefed<GeckoStyleContext>
+nsStyleSet::ReparentStyleContext(GeckoStyleContext* aStyleContext,
+                                 GeckoStyleContext* aNewParentContext,
                                  Element* aElement)
 {
   MOZ_ASSERT(aStyleContext, "aStyleContext must not be null");
 
   // This short-circuit is OK because we don't call TryInitatingTransition
   // during style reresolution if the style context pointer hasn't changed.
   if (aStyleContext->GetParent() == aNewParentContext) {
-    RefPtr<nsStyleContext> ret = aStyleContext;
+    RefPtr<GeckoStyleContext> ret = aStyleContext;
     return ret.forget();
   }
 
   nsIAtom* pseudoTag = aStyleContext->GetPseudo();
   CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
   nsRuleNode* ruleNode = aStyleContext->RuleNode();
 
   MOZ_ASSERT(PresContext()->RestyleManager()->IsGecko(),
              "stylo: the style set and restyle manager must have the same "
              "StyleBackendType");
   NS_ASSERTION(!PresContext()->RestyleManager()->AsGecko()->SkipAnimationRules(),
                "we no longer handle SkipAnimationRules()");
 
   nsRuleNode* visitedRuleNode = nullptr;
-  nsStyleContext* visitedContext = aStyleContext->GetStyleIfVisited();
+  GeckoStyleContext* visitedContext = aStyleContext->GetStyleIfVisited();
   // Reparenting a style context just changes where we inherit from,
   // not what rules we match or what our DOM looks like.  In
   // particular, it doesn't change whether this is a style context for
   // a link.
   if (visitedContext) {
     visitedRuleNode = visitedContext->RuleNode();
   }
 
@@ -2773,12 +2774,12 @@ nsStyleSet::ClearSelectors()
              "stylo: the style set and restyle manager must have the same "
              "StyleBackendType");
   PresContext()->RestyleManager()->AsGecko()->ClearSelectors();
 }
 
 void
 nsStyleSet::ClearNonInheritingStyleContexts()
 {
-  for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
+  for (RefPtr<GeckoStyleContext>& ptr : mNonInheritingStyleContexts) {
     ptr = nullptr;
   }
 }
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -108,162 +108,162 @@ class nsStyleSet final
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
 
   nsRuleNode* GetRuleTree() { return mRuleTree; }
 
   // get a style context for a non-pseudo frame.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleFor(mozilla::dom::Element* aElement,
-                  nsStyleContext* aParentContext);
+                  mozilla::GeckoStyleContext* aParentContext);
 
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleFor(mozilla::dom::Element* aElement,
-                  nsStyleContext* aParentContext,
+                  mozilla::GeckoStyleContext* aParentContext,
                   mozilla::LazyComputeBehavior)
   {
     return ResolveStyleFor(aElement, aParentContext);
   }
 
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleFor(mozilla::dom::Element* aElement,
-                  nsStyleContext* aParentContext,
+                  mozilla::GeckoStyleContext* aParentContext,
                   TreeMatchContext& aTreeMatchContext);
 
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleFor(mozilla::dom::Element* aElement,
-                  nsStyleContext* aParentContext,
+                  mozilla::GeckoStyleContext* aParentContext,
                   mozilla::LazyComputeBehavior aMayCompute,
                   TreeMatchContext& aTreeMatchContext)
   {
     return ResolveStyleFor(aElement, aParentContext, aTreeMatchContext);
   }
 
   // Get a style context (with the given parent) for the
   // sequence of style rules in the |aRules| array.
-  already_AddRefed<nsStyleContext>
-  ResolveStyleForRules(nsStyleContext* aParentContext,
+  already_AddRefed<mozilla::GeckoStyleContext>
+  ResolveStyleForRules(mozilla::GeckoStyleContext* aParentContext,
                        const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules);
 
   // Get a style context that represents aBaseContext, but as though
   // it additionally matched the rules in the aRules array (in that
   // order, as more specific than any other rules).
   //
   // One of the following must hold:
   // 1. The resulting style context must be used only on a temporary
   //    basis, and it must never be put into the style context tree
   //    (and, in particular, we must never call
   //    ResolveStyleWithReplacement with it as the old context, which
   //    might happen if it is put in the style context tree), or
   // 2. The additional rules must be appropriate for the transitions
   //    level of the cascade, which is the highest level of the cascade.
   //    (This is the case for one current caller, the cover rule used
   //    for CSS transitions.)
-  already_AddRefed<nsStyleContext>
-  ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
+  already_AddRefed<mozilla::GeckoStyleContext>
+  ResolveStyleByAddingRules(mozilla::GeckoStyleContext* aBaseContext,
                             const nsCOMArray<nsIStyleRule> &aRules);
 
   // Resolve style by making replacements in the list of style rules as
   // described by aReplacements, but otherwise maintaining the status
   // quo.
   // aPseudoElement must follow the same rules as for
   // ResolvePseudoElementStyle, and be null for non-pseudo-element cases
   enum { // flags for aFlags
     // Skip starting CSS animations that result from the style.
     eSkipStartingAnimations = (1<<0),
   };
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleWithReplacement(mozilla::dom::Element* aElement,
                               mozilla::dom::Element* aPseudoElement,
-                              nsStyleContext* aNewParentContext,
-                              nsStyleContext* aOldStyleContext,
+                              mozilla::GeckoStyleContext* aNewParentContext,
+                              mozilla::GeckoStyleContext* aOldStyleContext,
                               nsRestyleHint aReplacements,
                               uint32_t aFlags = 0);
 
   // Resolve style by returning a style context with the specified
   // animation data removed.  It is allowable to remove all animation
   // data with eRestyle_AllHintsWithAnimations, or by using any other
   // hints that are allowed by ResolveStyleWithReplacement.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
     ResolveStyleByRemovingAnimation(mozilla::dom::Element* aElement,
-                                    nsStyleContext* aStyleContext,
+                                    mozilla::GeckoStyleContext* aStyleContext,
                                     nsRestyleHint aWhichToRemove);
 
   // Similar to the above, but resolving style without all animation data in
   // the first place.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
     ResolveStyleWithoutAnimation(mozilla::dom::Element* aTarget,
-                                 nsStyleContext* aParentContext);
+                                 mozilla::GeckoStyleContext* aParentContext);
 
   // Pseudo-element version of the above, ResolveStyleWithoutAnimation.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolvePseudoElementStyleWithoutAnimation(
     mozilla::dom::Element* aParentElement,
     mozilla::CSSPseudoElementType aType,
-    nsStyleContext* aParentContext,
+    mozilla::GeckoStyleContext* aParentContext,
     mozilla::dom::Element* aPseudoElement);
 
   // Get a style context for a text node (which no rules will match).
   //
   // The returned style context will have nsCSSAnonBoxes::mozText as its pseudo.
   //
   // (Perhaps mozText should go away and we shouldn't even create style
   // contexts for such content nodes, when text-combine-upright is not
   // present.  However, not doing any rule matching for them is a first step.)
-  already_AddRefed<nsStyleContext>
-  ResolveStyleForText(nsIContent* aTextNode, nsStyleContext* aParentContext);
+  already_AddRefed<mozilla::GeckoStyleContext>
+  ResolveStyleForText(nsIContent* aTextNode, mozilla::GeckoStyleContext* aParentContext);
 
   // Get a style context for a first-letter continuation (which no rules will
   // match).
   //
   // The returned style context will have
   // nsCSSAnonBoxes::firstLetterContinuation as its pseudo.
   //
   // (Perhaps nsCSSAnonBoxes::firstLetterContinuation should go away and we
   // shouldn't even create style contexts for such frames.  However, not doing
   // any rule matching for them is a first step.  And right now we do use this
   // style context for some things)
-  already_AddRefed<nsStyleContext>
-  ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
+  already_AddRefed<mozilla::GeckoStyleContext>
+  ResolveStyleForFirstLetterContinuation(mozilla::GeckoStyleContext* aParentContext);
 
   // Get a style context for a placeholder frame (which no rules will match).
   //
   // The returned style context will have nsCSSAnonBoxes::oofPlaceholder as
   // its pseudo.
   //
   // (Perhaps nsCSSAnonBoxes::oofPlaceholder should go away and we shouldn't
   // even create style contexts for placeholders.  However, not doing any rule
   // matching for them is a first step.)
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleForPlaceholder();
 
   // Get a style context for a pseudo-element.  aParentElement must be
   // non-null.  aPseudoID is the CSSPseudoElementType for the
   // pseudo-element.  aPseudoElement must be non-null if the pseudo-element
   // type is one that allows user action pseudo-classes after it or allows
   // style attributes; otherwise, it is ignored.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType,
-                            nsStyleContext* aParentContext,
+                            mozilla::GeckoStyleContext* aParentContext,
                             mozilla::dom::Element* aPseudoElement);
 
   // This functions just like ResolvePseudoElementStyle except that it will
   // return nullptr if there are no explicit style rules for that
   // pseudo element.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
                           mozilla::CSSPseudoElementType aType,
-                          nsStyleContext* aParentContext);
-  already_AddRefed<nsStyleContext>
+                          mozilla::GeckoStyleContext* aParentContext);
+  already_AddRefed<mozilla::GeckoStyleContext>
   ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
                           mozilla::CSSPseudoElementType aType,
-                          nsStyleContext* aParentContext,
+                          mozilla::GeckoStyleContext* aParentContext,
                           TreeMatchContext& aTreeMatchContext);
 
   /**
    * Bit-flags that can be passed to GetContext in its parameter 'aFlags'.
    */
   enum {
     eNoFlags =          0,
     eIsLink =           1 << 0,
@@ -276,34 +276,34 @@ class nsStyleSet final
     // it's the outer frame of a button widget, and we're the inline frame for
     // the button's label).
     eSkipParentDisplayBasedStyleFixup = 1 << 3
   };
 
   // Get a style context for an anonymous box.  aPseudoTag is the pseudo-tag to
   // use and must be non-null.  It must be an anon box, and must be one that
   // inherits style from the given aParentContext.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
-                                     nsStyleContext* aParentContext);
+                                     mozilla::GeckoStyleContext* aParentContext);
 
   // Get a style context for an anonymous box that does not inherit style from
   // anything.  aPseudoTag is the pseudo-tag to use and must be non-null.  It
   // must be an anon box, and must be a non-inheriting one.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag);
 
 #ifdef MOZ_XUL
   // Get a style context for a XUL tree pseudo.  aPseudoTag is the
   // pseudo-tag to use and must be non-null.  aParentContent must be
   // non-null.  aComparator must be non-null.
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveXULTreePseudoStyle(mozilla::dom::Element* aParentElement,
                             nsICSSAnonBoxPseudo* aPseudoTag,
-                            nsStyleContext* aParentContext,
+                            mozilla::GeckoStyleContext* aParentContext,
                             nsICSSPseudoComparator* aComparator);
 #endif
 
   // Append all the currently-active font face rules to aArray.  Return
   // true for success and false for failure.
   bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
 
   // Return the winning (in the cascade) @keyframes rule for the given name.
@@ -346,19 +346,19 @@ class nsStyleSet final
   void InvalidateStyleForCSSRuleChanges();
 
   // Get a new style context that lives in a different parent
   // The new context will be the same as the old if the new parent is the
   // same as the old parent.
   // aElement should be non-null if this is a style context for an
   // element or pseudo-element; in the latter case it should be the
   // real element the pseudo-element is for.
-  already_AddRefed<nsStyleContext>
-  ReparentStyleContext(nsStyleContext* aStyleContext,
-                       nsStyleContext* aNewParentContext,
+  already_AddRefed<mozilla::GeckoStyleContext>
+  ReparentStyleContext(mozilla::GeckoStyleContext* aStyleContext,
+                       mozilla::GeckoStyleContext* aNewParentContext,
                        mozilla::dom::Element* aElement);
 
   // Test if style is dependent on a document state.
   bool HasDocumentStateDependentStyle(nsIContent*    aContent,
                                       mozilla::EventStates aStateMask);
 
   // Test if style is dependent on content state
   nsRestyleHint HasStateDependentStyle(mozilla::dom::Element* aElement,
@@ -552,39 +552,39 @@ private:
   // aPseudoElement must follow the same rules as for
   // ResolvePseudoElementStyle, and be null for non-pseudo-element cases
   nsRuleNode* RuleNodeWithReplacement(mozilla::dom::Element* aElement,
                                       mozilla::dom::Element* aPseudoElement,
                                       nsRuleNode* aOldRuleNode,
                                       mozilla::CSSPseudoElementType aPseudoType,
                                       nsRestyleHint aReplacements);
 
-  already_AddRefed<nsStyleContext>
-  GetContext(nsStyleContext* aParentContext,
+  already_AddRefed<mozilla::GeckoStyleContext>
+  GetContext(mozilla::GeckoStyleContext* aParentContext,
              nsRuleNode* aRuleNode,
              nsRuleNode* aVisitedRuleNode,
              nsIAtom* aPseudoTag,
              mozilla::CSSPseudoElementType aPseudoType,
              mozilla::dom::Element* aElementForAnimation,
              uint32_t aFlags);
 
   enum AnimationFlag {
     eWithAnimation,
     eWithoutAnimation,
   };
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleForInternal(mozilla::dom::Element* aElement,
-                          nsStyleContext* aParentContext,
+                          mozilla::GeckoStyleContext* aParentContext,
                           TreeMatchContext& aTreeMatchContext,
                           AnimationFlag aAnimationFlag);
 
-  already_AddRefed<nsStyleContext>
+  already_AddRefed<mozilla::GeckoStyleContext>
   ResolvePseudoElementStyleInternal(mozilla::dom::Element* aParentElement,
                                     mozilla::CSSPseudoElementType aType,
-                                    nsStyleContext* aParentContext,
+                                    mozilla::GeckoStyleContext* aParentContext,
                                     mozilla::dom::Element* aPseudoElement,
                                     AnimationFlag aAnimationFlag);
 
   nsPresContext* PresContext() { return mRuleTree->PresContext(); }
 
   // Clear our cached mNonInheritingStyleContexts.  We do this when we want to
   // make sure those style contexts won't live too long (e.g. at ruletree
   // reconstruct or shutdown time).
@@ -666,17 +666,17 @@ private:
 
   // whether font feature values lookup object needs initialization
   RefPtr<gfxFontFeatureValueSet> mFontFeatureValuesLookup;
 
   // Stores pointers to our cached style contexts for non-inheriting anonymous
   // boxes.
   mozilla::EnumeratedArray<nsCSSAnonBoxes::NonInheriting,
                            nsCSSAnonBoxes::NonInheriting::_Count,
-                           RefPtr<nsStyleContext>> mNonInheritingStyleContexts;
+                           RefPtr<mozilla::GeckoStyleContext>> mNonInheritingStyleContexts;
 };
 
 #ifdef MOZILLA_INTERNAL_API
 inline
 void nsRuleNode::AddRef()
 {
   if (mRefCnt++ == 0) {
     MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -429,17 +429,17 @@ CSSTransition::SetEffectFromStyle(dom::A
 
 NS_IMPL_CYCLE_COLLECTION(nsTransitionManager, mEventDispatcher)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransitionManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransitionManager, Release)
 
 static inline bool
 ExtractNonDiscreteComputedValue(nsCSSPropertyID aProperty,
-                                nsStyleContext* aStyleContext,
+                                GeckoStyleContext* aStyleContext,
                                 AnimationValue& aAnimationValue)
 {
   return (nsCSSProps::kAnimTypeTable[aProperty] != eStyleAnimType_Discrete ||
           aProperty == eCSSProperty_visibility) &&
          StyleAnimationValue::ExtractComputedValue(aProperty, aStyleContext,
                                                    aAnimationValue.mGecko);
 }
 
@@ -456,20 +456,20 @@ ExtractNonDiscreteComputedValue(nsCSSPro
   aAnimationValue.mServo =
     Servo_ComputedValues_ExtractAnimationValue(aComputedStyle,
                                                aProperty).Consume();
   return !!aAnimationValue.mServo;
 }
 
 void
 nsTransitionManager::StyleContextChanged(dom::Element *aElement,
-                                         nsStyleContext *aOldStyleContext,
-                                         RefPtr<nsStyleContext>* aNewStyleContext /* inout */)
+                                         GeckoStyleContext* aOldStyleContext,
+                                         RefPtr<GeckoStyleContext>* aNewStyleContext /* inout */)
 {
-  nsStyleContext* newStyleContext = *aNewStyleContext;
+  GeckoStyleContext* newStyleContext = *aNewStyleContext;
 
   NS_PRECONDITION(aOldStyleContext->GetPseudo() == newStyleContext->GetPseudo(),
                   "pseudo type mismatch");
 
   if (mInAnimationOnlyStyleUpdate) {
     // If we're doing an animation-only style update, return, since the
     // purpose of an animation-only style update is to update only the
     // animation styles so that we don't consider style changes
@@ -561,17 +561,17 @@ nsTransitionManager::StyleContextChanged
   NS_WARNING_ASSERTION(
     !mPresContext->EffectCompositor()->HasThrottledStyleUpdates(),
     "throttled animations not up to date");
 
   // Compute what the css-transitions spec calls the "after-change
   // style", which is the new style without any data from transitions,
   // but still inheriting from data that contains transitions that are
   // not stopping or starting right now.
-  RefPtr<nsStyleContext> afterChangeStyle;
+  RefPtr<GeckoStyleContext> afterChangeStyle;
   if (collection) {
     MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
                "ServoStyleSets should not use nsTransitionManager "
                "for transitions");
     nsStyleSet* styleSet = mPresContext->StyleSet()->AsGecko();
     afterChangeStyle =
       styleSet->ResolveStyleByRemovingAnimation(aElement, newStyleContext,
                                                 eRestyle_CSSTransitions);
@@ -1107,17 +1107,17 @@ nsTransitionManager::ConsiderInitiatingT
 
   *aStartedAny = true;
   aWhichStarted->AddProperty(aProperty);
 }
 
 void
 nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement,
                                                CSSPseudoElementType aPseudoType,
-                                               nsStyleContext* aNewStyleContext)
+                                               GeckoStyleContext* aNewStyleContext)
 {
   MOZ_ASSERT(!aElement->IsGeneratedContentContainerForBefore() &&
              !aElement->IsGeneratedContentContainerForAfter());
 
   CSSTransitionCollection* collection =
     CSSTransitionCollection::GetAnimationCollection(aElement, aPseudoType);
   if (!collection) {
     return;
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -19,16 +19,17 @@
 
 class nsIGlobalObject;
 class nsStyleContext;
 class nsPresContext;
 class nsCSSPropertyIDSet;
 
 namespace mozilla {
 enum class CSSPseudoElementType : uint8_t;
+class GeckoStyleContext;
 struct Keyframe;
 struct StyleTransition;
 class ServoStyleContext;
 } // namespace mozilla
 
 /*****************************************************************************
  * Per-Element data                                                          *
  *****************************************************************************/
@@ -364,18 +365,18 @@ public:
    * element.
    *
    * It may modify the new style context (by replacing
    * *aNewStyleContext) to cover up some of the changes for the duration
    * of the restyling of descendants.  If it does, this function will
    * take care of causing the necessary restyle afterwards.
    */
   void StyleContextChanged(mozilla::dom::Element *aElement,
-                           nsStyleContext *aOldStyleContext,
-                           RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
+                           mozilla::GeckoStyleContext* aOldStyleContext,
+                           RefPtr<mozilla::GeckoStyleContext>* aNewStyleContext /* inout */);
 
   /**
    * Update transitions for stylo.
    */
   bool UpdateTransitions(
     mozilla::dom::Element *aElement,
     mozilla::CSSPseudoElementType aPseudoType,
     const mozilla::ServoStyleContext* aOldStyle,
@@ -386,17 +387,17 @@ public:
    * style, we might have some old finished transitions for it, if,
    * say, it was display:none for a while, but previously displayed.
    *
    * This method removes any finished transitions that don't match the
    * new style.
    */
   void PruneCompletedTransitions(mozilla::dom::Element* aElement,
                                  mozilla::CSSPseudoElementType aPseudoType,
-                                 nsStyleContext* aNewStyleContext);
+                                 mozilla::GeckoStyleContext* aNewStyleContext);
 
   void SetInAnimationOnlyStyleUpdate(bool aInAnimationOnlyUpdate) {
     mInAnimationOnlyStyleUpdate = aInAnimationOnlyUpdate;
   }
 
   bool InAnimationOnlyStyleUpdate() const {
     return mInAnimationOnlyStyleUpdate;
   }
--- a/layout/xul/tree/nsTreeStyleCache.cpp
+++ b/layout/xul/tree/nsTreeStyleCache.cpp
@@ -84,17 +84,17 @@ nsTreeStyleCache::GetStyleContext(nsICSS
     RefPtr<nsStyleContext> newResult;
     if (aPresContext->StyleSet()->IsServo()) {
       NS_ERROR("stylo: ServoStyleSets should not support XUL tree styles yet");
       newResult = aPresContext->StyleSet()->
         ResolveStyleForPlaceholder();
     } else {
       newResult = aPresContext->StyleSet()->AsGecko()->
         ResolveXULTreePseudoStyle(aContent->AsElement(), aPseudoElement,
-                                  aContext, aComparator);
+                                  aContext->AsGecko(), aComparator);
     }
 
     // Put the style context in our table, transferring the owning reference to the table.
     if (!mCache) {
       mCache = new StyleContextCache();
     }
     result = newResult.get();
     mCache->Put(currState, newResult.forget());