Bug 1381844: Be more explicit about the kind of style context we handle all the time. draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 21 Jul 2017 03:22:00 +0200
changeset 613075 85148b2c081e89e3f52ef77cdb79dddb1252f100
parent 613074 0aae3b1db1387dd2d3d69ff80a5a909cb656360c
child 638605 f1a0b1b9844e99295793b065c0d0688da6538ba7
push id69719
push userbmo:emilio+bugs@crisal.io
push dateFri, 21 Jul 2017 14:38:22 +0000
bugs1381844
milestone56.0a1
Bug 1381844: Be more explicit about the kind of style context we handle all the time. 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
@@ -2902,17 +2902,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
@@ -2689,45 +2689,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();
 }
@@ -2739,17 +2739,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(),
@@ -2765,17 +2765,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,
@@ -2787,17 +2787,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);
 
@@ -2924,20 +2924,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) {
@@ -2952,17 +2952,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)
@@ -3013,24 +3013,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;
   }
@@ -3960,41 +3960,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->ComputedValues()->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,
@@ -840,21 +917,21 @@ GetPrevContinuationWithPossiblySameStyle
 static nsIFrame*
 GetPrevContinuationWithSameStyle(nsIFrame* aFrame)
 {
   nsIFrame* prevContinuation = GetPrevContinuationWithPossiblySameStyle(aFrame);
   if (!prevContinuation) {
     return nullptr;
   }
 
-  nsStyleContext* prevStyle = prevContinuation->StyleContext();
-  nsStyleContext* selfStyle = aFrame->StyleContext();
+  auto* prevStyle = prevContinuation->StyleContext();
+  auto* selfStyle = aFrame->StyleContext();
   if (prevStyle != selfStyle) {
-    NS_ASSERTION(prevStyle->GetPseudo() != selfStyle->GetPseudo() ||
-                 prevStyle->GetParent() != selfStyle->GetParent(),
+    NS_ASSERTION(prevStyle->AsGecko()->GetPseudo() != selfStyle->AsGecko()->GetPseudo() ||
+                 prevStyle->AsGecko()->GetParent() != selfStyle->AsGecko()->GetParent(),
                  "continuations should have the same style context");
     prevContinuation = nullptr;
   }
   return prevContinuation;
 }
 
 nsresult
 GeckoRestyleManager::ReparentStyleContext(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);
+  auto* 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->ComputedValues());
     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 =
+        already_AddRefed<GeckoStyleContext>(pseudoStyleContext.forget().take()->AsGecko());
+      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 =
+          already_AddRefed<GeckoStyleContext>(result.forget().take()->AsGecko());
         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,46 @@
 #define mozilla_GeckoStyleContext_h
 
 #include "nsStyleContext.h"
 
 namespace mozilla {
 
 class GeckoStyleContext final : public nsStyleContext {
 public:
-  GeckoStyleContext(nsStyleContext* aParent,
+  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 +230,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,49 @@ 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 =
+      already_AddRefed<GeckoStyleContext>(p.forget().take()->AsGecko());
   }
 
   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 +936,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()) {
@@ -5441,17 +5443,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()
@@ -384,15 +375,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,84 @@ 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,
+  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 +1912,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 +1970,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 +2063,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 +2086,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 +2132,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 +2456,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 +2773,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());