Bug 1439285: Make the old image request arrive to FinishStyle if we come from ResolveSameStructsAs. r?bholley draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 22 Feb 2018 19:44:44 +0100
changeset 758615 843ef71ea874133769920e197cfbe64908987ed6
parent 758500 ea6022712fab1fce76a2721c8d1e9ed2df0a09bf
child 758616 e454fe8087db57f8fa86961ecec187526898652f
child 758620 ee9af099990ba396613b9116139483e8fd22513b
push id100128
push userbmo:emilio@crisal.io
push dateThu, 22 Feb 2018 19:35:39 +0000
reviewersbholley
bugs1439285
milestone60.0a1
Bug 1439285: Make the old image request arrive to FinishStyle if we come from ResolveSameStructsAs. r?bholley MozReview-Commit-ID: H1N9jNql9tl
layout/style/ServoStyleContextInlines.h
layout/style/nsStyleContextInlines.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/SVGObserverUtils.cpp
--- a/layout/style/ServoStyleContextInlines.h
+++ b/layout/style/ServoStyleContextInlines.h
@@ -17,20 +17,22 @@ namespace mozilla {
 void
 ServoStyleContext::ResolveSameStructsAs(const ServoStyleContext* aOther)
 {
   // Only resolve structs that are not already resolved in this struct.
   uint64_t ourBits = mBits & NS_STYLE_INHERIT_MASK;
   uint64_t otherBits = aOther->mBits & NS_STYLE_INHERIT_MASK;
   uint64_t newBits = otherBits & ~ourBits & NS_STYLE_INHERIT_MASK;
 
-#define STYLE_STRUCT(name_, checkdata_cb)                                           \
-  if (nsStyle##name_::kHasFinishStyle && newBits & NS_STYLE_INHERIT_BIT(name_)) {   \
-    const nsStyle##name_* data = ComputedData()->GetStyle##name_();               \
-    const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext);                   \
+#define STYLE_STRUCT(name_, checkdata_cb)                                      \
+  if (nsStyle##name_::kHasFinishStyle &&                                       \
+      (newBits & NS_STYLE_INHERIT_BIT(name_))) {                               \
+    const nsStyle##name_* data = ComputedData()->GetStyle##name_();            \
+    const nsStyle##name_* oldData = aOther->ComputedData()->GetStyle##name_(); \
+    const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, oldData);     \
   }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
   mBits |= newBits;
 }
 
 } // namespace mozilla
--- a/layout/style/nsStyleContextInlines.h
+++ b/layout/style/nsStyleContextInlines.h
@@ -100,38 +100,38 @@ const nsStyle##name_ * nsStyleContext::P
     return newData;                                                 \
   }
 #else
 #define DO_GET_STYLE_INHERITED_GECKO(name_, checkdata_cb_)          \
   MOZ_CRASH("old style system disabled");
 #endif
 
 // Helper functions for GetStyle* and PeekStyle*
-#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                \
-template<bool aComputeData>                                         \
-const nsStyle##name_ * nsStyleContext::DoGetStyle##name_() {        \
-  if (IsGecko()) {                                                  \
-    DO_GET_STYLE_INHERITED_GECKO(name_, checkdata_cb_)              \
-  }                                                                 \
-  const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\
-  if (!aComputeData && needToCompute) {                             \
-    return nullptr;                                                 \
-  }                                                                 \
-                                                                    \
-  const nsStyle##name_* data = ComputedData()->GetStyle##name_();   \
-                                                                    \
-  /* perform any remaining main thread work on the struct */        \
-  if (needToCompute) {                                              \
-    MOZ_ASSERT(NS_IsMainThread());                                  \
-    MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal());      \
-    const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext());  \
-    /* the ServoStyleContext owns the struct */                     \
-    AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                       \
-  }                                                                 \
-  return data;                                                      \
+#define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                         \
+template<bool aComputeData>                                                  \
+const nsStyle##name_ * nsStyleContext::DoGetStyle##name_() {                 \
+  if (IsGecko()) {                                                           \
+    DO_GET_STYLE_INHERITED_GECKO(name_, checkdata_cb_)                       \
+  }                                                                          \
+  const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));         \
+  if (!aComputeData && needToCompute) {                                      \
+    return nullptr;                                                          \
+  }                                                                          \
+                                                                             \
+  const nsStyle##name_* data = ComputedData()->GetStyle##name_();            \
+                                                                             \
+  /* perform any remaining main thread work on the struct */                 \
+  if (needToCompute) {                                                       \
+    MOZ_ASSERT(NS_IsMainThread());                                           \
+    MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal());               \
+    const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext(), nullptr);  \
+    /* the ServoStyleContext owns the struct */                              \
+    AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                                \
+  }                                                                          \
+  return data;                                                               \
 }
 
 #ifdef MOZ_OLD_STYLE
 #define DO_GET_STYLE_RESET_GECKO(name_, checkdata_cb_)                        \
   {                                                                           \
     auto gecko = AsGecko();                                                   \
     if (gecko->mCachedResetData) {                                            \
       const nsStyle##name_ * cachedData =                                     \
@@ -157,17 +157,17 @@ const nsStyle##name_ * nsStyleContext::D
   }                                                                           \
   const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));          \
   if (!aComputeData && needToCompute) {                                       \
     return nullptr;                                                           \
   }                                                                           \
   const nsStyle##name_* data = ComputedData()->GetStyle##name_();             \
   /* perform any remaining main thread work on the struct */                  \
   if (needToCompute) {                                                        \
-    const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext());            \
+    const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext(), nullptr);   \
     /* the ServoStyleContext owns the struct */                               \
     AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                                 \
   }                                                                           \
   return data;                                                                \
 }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT_RESET
 #undef STYLE_STRUCT_INHERITED
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -388,22 +388,23 @@ nsStyleBorder::nsStyleBorder(const nsSty
 }
 
 nsStyleBorder::~nsStyleBorder()
 {
   MOZ_COUNT_DTOR(nsStyleBorder);
 }
 
 void
-nsStyleBorder::FinishStyle(nsPresContext* aPresContext)
+nsStyleBorder::FinishStyle(nsPresContext* aPresContext, const nsStyleBorder* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
-  mBorderImageSource.ResolveImage(aPresContext);
+  mBorderImageSource.ResolveImage(
+    aPresContext, aOldStyle ? &aOldStyle->mBorderImageSource : nullptr);
 }
 
 nsMargin
 nsStyleBorder::GetImageOutset() const
 {
   // We don't check whether there is a border-image (which is OK since
   // the initial values yields 0 outset) so that we don't have to
   // reflow to update overflow areas when an image loads.
@@ -608,23 +609,24 @@ nsStyleList::nsStyleList(const nsStyleLi
   , mCounterStyle(aSource.mCounterStyle)
   , mQuotes(aSource.mQuotes)
   , mImageRegion(aSource.mImageRegion)
 {
   MOZ_COUNT_CTOR(nsStyleList);
 }
 
 void
-nsStyleList::FinishStyle(nsPresContext* aPresContext)
+nsStyleList::FinishStyle(nsPresContext* aPresContext, const nsStyleList* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   if (mListStyleImage && !mListStyleImage->IsResolved()) {
-    mListStyleImage->Resolve(aPresContext);
+    mListStyleImage->Resolve(
+      aPresContext, aOldStyle ? aOldStyle->mListStyleImage.get() : nullptr);
   }
   mCounterStyle.Resolve(aPresContext->CounterStyleManager());
 }
 
 void
 nsStyleList::SetQuotesInherit(const nsStyleList* aOther)
 {
   mQuotes = aOther->mQuotes;
@@ -1295,30 +1297,35 @@ void
 nsStyleSVGReset::Destroy(nsPresContext* aContext)
 {
   this->~nsStyleSVGReset();
   aContext->PresShell()->
     FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
 }
 
 void
-nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
+nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext, const nsStyleSVGReset* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
     nsStyleImage& image = mMask.mLayers[i].mImage;
     if (image.GetType() == eStyleImageType_Image) {
       // If the url of mask resource contains a reference('#'), it should be a
       // <mask-source>, mostly. For a <mask-source>, there is no need to
       // resolve this style image, since we do not depend on it to get the
       // SVG mask resource.
       if (!image.GetURLValue()->HasRef()) {
-        image.ResolveImage(aPresContext);
+        const nsStyleImage* oldImage =
+          (aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
+          ? &aOldStyle->mMask.mLayers[i].mImage
+          : nullptr;
+
+        image.ResolveImage(aPresContext, oldImage);
       }
     }
   }
 }
 
 nsChangeHint
 nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
 {
@@ -2186,17 +2193,18 @@ nsStyleImageRequest::~nsStyleImageReques
   }
 
   MOZ_ASSERT(!mRequestProxy);
   MOZ_ASSERT(!mImageValue);
   MOZ_ASSERT(!mImageTracker);
 }
 
 bool
-nsStyleImageRequest::Resolve(nsPresContext* aPresContext)
+nsStyleImageRequest::Resolve(
+  nsPresContext* aPresContext, const nsStyleImageRequest* aOldImageRequest)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!IsResolved(), "already resolved");
   MOZ_ASSERT(aPresContext);
 
   mResolved = true;
 
   nsIDocument* doc = aPresContext->Document();
@@ -3340,22 +3348,23 @@ void
 nsStyleBackground::Destroy(nsPresContext* aContext)
 {
   this->~nsStyleBackground();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
 }
 
 void
-nsStyleBackground::FinishStyle(nsPresContext* aPresContext)
+nsStyleBackground::FinishStyle(
+  nsPresContext* aPresContext, const nsStyleBackground* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
-  mImage.ResolveImages(aPresContext);
+  mImage.ResolveImages(aPresContext, aOldStyle ? &aOldStyle->mImage : nullptr);
 }
 
 nsChangeHint
 nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
   if (mBackgroundColor != aNewData.mBackgroundColor) {
     hint |= nsChangeHint_RepaintFrame;
@@ -3719,32 +3728,37 @@ nsStyleDisplay::~nsStyleDisplay()
                                 mSpecifiedScale);
   ReleaseSharedListOnMainThread("nsStyleDisplay::mCombinedTransform",
                                 mCombinedTransform);
 
   MOZ_COUNT_DTOR(nsStyleDisplay);
 }
 
 void
-nsStyleDisplay::FinishStyle(nsPresContext* aPresContext)
+nsStyleDisplay::FinishStyle(
+    nsPresContext* aPresContext, const nsStyleDisplay* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
   if (mShapeOutside.GetType() == StyleShapeSourceType::Image) {
     const UniquePtr<nsStyleImage>& shapeImage = mShapeOutside.GetShapeImage();
     if (shapeImage) {
       // Bug 1434963: The CORS mode should instead be set when the
       // ImageValue is created, in both Gecko and Stylo. That will
       // avoid doing a mutation here.
       if (shapeImage->GetType() == eStyleImageType_Image) {
         shapeImage->GetImageRequest()->GetImageValue()->SetCORSMode(
           CORSMode::CORS_ANONYMOUS);
       }
-      shapeImage->ResolveImage(aPresContext);
+      const nsStyleImage* oldShapeImage =
+        (aOldStyle &&
+         aOldStyle->mShapeOutside.GetType() == StyleShapeSourceType::Image)
+          ?  &*aOldStyle->mShapeOutside.GetShapeImage() : nullptr;
+      shapeImage->ResolveImage(aPresContext, oldShapeImage);
     }
   }
 
   GenerateCombinedTransform();
 }
 
 static inline nsChangeHint
 CompareTransformValues(const RefPtr<nsCSSValueSharedList>& aList,
@@ -4011,16 +4025,20 @@ nsStyleDisplay::CalcDifference(const nsS
   }
 
   return hint;
 }
 
 void
 nsStyleDisplay::GenerateCombinedTransform()
 {
+  // FIXME(emilio): This should probably be called from somewhere like what we
+  // do for image layers, instead of FinishStyle.
+  //
+  // This does and undoes the work a ton of times in Stylo.
   mCombinedTransform = nullptr;
 
   // Follow the order defined in the spec to append transform functions.
   // https://drafts.csswg.org/css-transforms-2/#ctm
   AutoTArray<nsCSSValueSharedList*, 4> shareLists;
   if (mSpecifiedTranslate) {
     shareLists.AppendElement(mSpecifiedTranslate.get());
   }
@@ -4203,22 +4221,26 @@ nsStyleContentData::operator==(const nsS
   if (mType == eStyleContentType_Counter ||
       mType == eStyleContentType_Counters) {
     return *mContent.mCounters == *aOther.mContent.mCounters;
   }
   return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
 }
 
 void
-nsStyleContentData::Resolve(nsPresContext* aPresContext)
+nsStyleContentData::Resolve(
+  nsPresContext* aPresContext, const nsStyleContentData* aOldStyle)
 {
   switch (mType) {
     case eStyleContentType_Image:
       if (!mContent.mImage->IsResolved()) {
-        mContent.mImage->Resolve(aPresContext);
+        const nsStyleImageRequest* oldRequest =
+          (aOldStyle && aOldStyle->mType == eStyleContentType_Image)
+          ? aOldStyle->mContent.mImage : nullptr;
+        mContent.mImage->Resolve(aPresContext, oldRequest);
       }
       break;
     case eStyleContentType_Counter:
     case eStyleContentType_Counters: {
       mContent.mCounters->
         mCounterStyle.Resolve(aPresContext->CounterStyleManager());
       break;
     }
@@ -4245,20 +4267,24 @@ nsStyleContent::~nsStyleContent()
 void
 nsStyleContent::Destroy(nsPresContext* aContext)
 {
   this->~nsStyleContent();
   aContext->PresShell()->FreeByObjectID(eArenaObjectID_nsStyleContent, this);
 }
 
 void
-nsStyleContent::FinishStyle(nsPresContext* aPresContext)
-{
-  for (nsStyleContentData& data : mContents) {
-    data.Resolve(aPresContext);
+nsStyleContent::FinishStyle(nsPresContext* aPresContext, const nsStyleContent* aOldStyle)
+{
+  for (size_t i = 0; i < mContents.Length(); ++i) {
+    const nsStyleContentData* oldData =
+      (aOldStyle && aOldStyle->mContents.Length() > i)
+      ? &aOldStyle->mContents[i]
+      : nullptr;
+    mContents[i].Resolve(aPresContext, oldData);
   }
 }
 
 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
   : mContents(aSource.mContents)
   , mIncrements(aSource.mIncrements)
   , mResets(aSource.mResets)
 {
@@ -4626,24 +4652,32 @@ nsStyleUserInterface::nsStyleUserInterfa
 }
 
 nsStyleUserInterface::~nsStyleUserInterface()
 {
   MOZ_COUNT_DTOR(nsStyleUserInterface);
 }
 
 void
-nsStyleUserInterface::FinishStyle(nsPresContext* aPresContext)
+nsStyleUserInterface::FinishStyle(
+  nsPresContext* aPresContext, const nsStyleUserInterface* aOldStyle)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
 
-  for (nsCursorImage& cursor : mCursorImages) {
+  for (size_t i = 0; i < mCursorImages.Length(); ++i) {
+    nsCursorImage& cursor = mCursorImages[i];
+
     if (cursor.mImage && !cursor.mImage->IsResolved()) {
-      cursor.mImage->Resolve(aPresContext);
+      const nsCursorImage* oldCursor =
+        (aOldStyle && aOldStyle->mCursorImages.Length() > i)
+        ? &aOldStyle->mCursorImages[i]
+        : nullptr;
+      cursor.mImage->Resolve(
+        aPresContext, oldCursor ? oldCursor->mImage.get() : nullptr);
     }
   }
 }
 
 nsChangeHint
 nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -160,17 +160,17 @@ struct Position {
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
 {
   nsStyleFont(const nsFont& aFont, const nsPresContext* aContext);
   nsStyleFont(const nsStyleFont& aStyleFont);
   explicit nsStyleFont(const nsPresContext* aContext);
   ~nsStyleFont() {
     MOZ_COUNT_DTOR(nsStyleFont);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleFont*) {}
   const static bool kHasFinishStyle = false;
 
   nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
 
   /**
    * Return aSize multiplied by the current text zoom factor (in aPresContext).
    * aSize is allowed to be negative, but the caller is expected to deal with
    * negative results.  The result is clamped to nscoord_MIN .. nscoord_MAX.
@@ -353,17 +353,17 @@ public:
                       mozilla::dom::ImageTracker* aImageTracker);
 
   // Can be called from any thread, but Resolve() must be called later
   // on the main thread before get() can be used.
   nsStyleImageRequest(
       Mode aModeFlags,
       mozilla::css::ImageValue* aImageValue);
 
-  bool Resolve(nsPresContext* aPresContext);
+  bool Resolve(nsPresContext*, const nsStyleImageRequest* aOldImageRequest);
   bool IsResolved() const { return mResolved; }
 
   imgRequestProxy* get() {
     MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
     MOZ_ASSERT(NS_IsMainThread());
     return mRequestProxy.get();
   }
   const imgRequestProxy* get() const {
@@ -450,20 +450,23 @@ struct nsStyleImage
 
   void SetNull();
   void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
   void SetGradientData(nsStyleGradient* aGradient);
   void SetElementId(already_AddRefed<nsAtom> aElementId);
   void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
   void SetURLValue(already_AddRefed<URLValue> aData);
 
-  void ResolveImage(nsPresContext* aContext) {
+  void ResolveImage(nsPresContext* aContext, const nsStyleImage* aOldImage) {
     MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
     if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
-      mImage->Resolve(aContext);
+      const nsStyleImageRequest* oldRequest =
+        (aOldImage && aOldImage->GetType() == eStyleImageType_Image)
+        ? aOldImage->GetImageRequest() : nullptr;
+      mImage->Resolve(aContext, oldRequest);
     }
   }
 
   nsStyleImageType GetType() const {
     return mType;
   }
   nsStyleImageRequest* GetImageRequest() const {
     MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
@@ -589,17 +592,17 @@ private:
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
 {
   explicit nsStyleColor(const nsPresContext* aContext);
   nsStyleColor(const nsStyleColor& aOther);
   ~nsStyleColor() {
     MOZ_COUNT_DTOR(nsStyleColor);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleColor*) {}
   const static bool kHasFinishStyle = false;
 
   nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
     return mozilla::LinearBlendColors(aColor.mColor, mColor,
                                       aColor.mForegroundRatio);
   }
 
   nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
@@ -780,20 +783,18 @@ struct nsStyleImageLayers {
     // This constructor does not initialize mRepeat or mOrigin and Initialize()
     // must be called to do that.
     Layer();
     ~Layer();
 
     // Initialize mRepeat and mOrigin by specified layer type
     void Initialize(LayerType aType);
 
-    void ResolveImage(nsPresContext* aContext) {
-      if (mImage.GetType() == eStyleImageType_Image) {
-        mImage.ResolveImage(aContext);
-      }
+    void ResolveImage(nsPresContext* aContext, const Layer* aOldLayer) {
+      mImage.ResolveImage(aContext, aOldLayer ? &aOldLayer->mImage : nullptr);
     }
 
     // True if the rendering of this layer might change when the size
     // of the background positioning area changes.  This is true for any
     // non-solid-color background whose position or size depends on
     // the size of the positioning area.  It's also true for SVG images
     // whose root <svg> node has a viewBox.
     bool RenderingMightDependOnPositioningAreaSizeChange() const;
@@ -832,19 +833,23 @@ struct nsStyleImageLayers {
   // background-clip applies to the background-color) may not be last
   // layer.  In layers below the bottom layer, properties will be
   // uninitialized unless their count, above, indicates that they are
   // present.
   nsStyleAutoArray<Layer> mLayers;
 
   const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
 
-  void ResolveImages(nsPresContext* aContext) {
+  void ResolveImages(nsPresContext* aContext, const nsStyleImageLayers* aOldLayers) {
     for (uint32_t i = 0; i < mImageCount; ++i) {
-      mLayers[i].ResolveImage(aContext);
+      const Layer* oldLayer =
+        (aOldLayers && aOldLayers->mLayers.Length() > i)
+        ? &aOldLayers->mLayers[i]
+        : nullptr;
+      mLayers[i].ResolveImage(aContext, oldLayer);
     }
   }
 
   // Fill unspecified layers by cycling through their values
   // till they all are of length aMaxItemCount
   void FillAllLayers(uint32_t aMaxItemCount);
 
   nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
@@ -868,17 +873,17 @@ struct nsStyleImageLayers {
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
   explicit nsStyleBackground(const nsPresContext* aContext);
   nsStyleBackground(const nsStyleBackground& aOther);
   ~nsStyleBackground();
 
   // Resolves and tracks the images in mImage.  Only called with a Servo-backed
   // style system, where those images must be resolved later than the OMT
   // nsStyleBackground constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleBackground*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -911,17 +916,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
 {
   explicit nsStyleMargin(const nsPresContext* aContext);
   nsStyleMargin(const nsStyleMargin& aMargin);
   ~nsStyleMargin() {
     MOZ_COUNT_DTOR(nsStyleMargin);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleMargin*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleMargin* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -950,17 +955,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
 {
   explicit nsStylePadding(const nsPresContext* aContext);
   nsStylePadding(const nsStylePadding& aPadding);
   ~nsStylePadding() {
     MOZ_COUNT_DTOR(nsStylePadding);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStylePadding*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStylePadding* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -1117,17 +1122,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 {
   explicit nsStyleBorder(const nsPresContext* aContext);
   nsStyleBorder(const nsStyleBorder& aBorder);
   ~nsStyleBorder();
 
   // Resolves and tracks mBorderImageSource.  Only called with a Servo-backed
   // style system, where those images must be resolved later than the OMT
   // nsStyleBorder constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleBorder*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -1191,23 +1196,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
   }
 
   inline bool IsBorderImageLoaded() const
   {
     return mBorderImageSource.IsLoaded();
   }
 
-  void ResolveImage(nsPresContext* aContext)
-  {
-    if (mBorderImageSource.GetType() == eStyleImageType_Image) {
-      mBorderImageSource.ResolveImage(aContext);
-    }
-  }
-
   nsMargin GetImageOutset() const;
 
   imgIRequest* GetBorderImageRequest() const
   {
     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
       return mBorderImageSource.GetImageData();
     }
     return nullptr;
@@ -1302,17 +1300,17 @@ ASSERT_BORDER_COLOR_FIELD(Left);
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
 {
   explicit nsStyleOutline(const nsPresContext* aContext);
   nsStyleOutline(const nsStyleOutline& aOutline);
   ~nsStyleOutline() {
     MOZ_COUNT_DTOR(nsStyleOutline);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleOutline*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleOutline* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -1374,17 +1372,17 @@ private:
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
 {
   explicit nsStyleList(const nsPresContext* aContext);
   nsStyleList(const nsStyleList& aStyleList);
   ~nsStyleList();
 
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleList*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleList* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -1576,17 +1574,17 @@ struct nsStyleGridTemplate
   }
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
 {
   explicit nsStylePosition(const nsPresContext* aContext);
   nsStylePosition(const nsStylePosition& aOther);
   ~nsStylePosition();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStylePosition*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStylePosition* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -1801,17 +1799,17 @@ struct nsStyleTextOverflow
   bool mLogicalDirections;  // true when only one value was specified
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
 {
   explicit nsStyleTextReset(const nsPresContext* aContext);
   nsStyleTextReset(const nsStyleTextReset& aOther);
   ~nsStyleTextReset();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleTextReset*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleTextReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -1839,17 +1837,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   mozilla::StyleComplexColor mTextDecorationColor; // [reset]
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
 {
   explicit nsStyleText(const nsPresContext* aContext);
   nsStyleText(const nsStyleText& aOther);
   ~nsStyleText();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleText*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleText* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -2059,17 +2057,17 @@ protected:
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
 {
   explicit nsStyleVisibility(const nsPresContext* aContext);
   nsStyleVisibility(const nsStyleVisibility& aVisibility);
   ~nsStyleVisibility() {
     MOZ_COUNT_DTOR(nsStyleVisibility);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleVisibility*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleVisibility* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -2480,17 +2478,17 @@ private:
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
 {
   typedef mozilla::StyleGeometryBox StyleGeometryBox;
 
   explicit nsStyleDisplay(const nsPresContext* aContext);
   nsStyleDisplay(const nsStyleDisplay& aOther);
   ~nsStyleDisplay();
 
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleDisplay*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleDisplay* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -2869,17 +2867,17 @@ public:
   inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
 {
   explicit nsStyleTable(const nsPresContext* aContext);
   nsStyleTable(const nsStyleTable& aOther);
   ~nsStyleTable();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleTable*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleTable* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -2894,17 +2892,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   int32_t       mSpan;          // [reset] the number of columns spanned by a colgroup or col
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
 {
   explicit nsStyleTableBorder(const nsPresContext* aContext);
   nsStyleTableBorder(const nsStyleTableBorder& aOther);
   ~nsStyleTableBorder();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleTableBorder*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleTableBorder* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3040,17 +3038,17 @@ public:
   {
     MOZ_ASSERT(mType == eStyleContentType_Uninitialized,
                "should only initialize nsStyleContentData once");
     mType = eStyleContentType_Image;
     mContent.mImage = aRequest.take();
     MOZ_ASSERT(mContent.mImage);
   }
 
-  void Resolve(nsPresContext* aPresContext);
+  void Resolve(nsPresContext*, const nsStyleContentData*);
 
 private:
   nsStyleContentType mType;
   union {
     char16_t *mString;
     nsStyleImageRequest* mImage;
     CounterFunction* mCounters;
   } mContent;
@@ -3070,17 +3068,17 @@ struct nsStyleCounterData
   }
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
 {
   explicit nsStyleContent(const nsPresContext* aContext);
   nsStyleContent(const nsStyleContent& aContent);
   ~nsStyleContent();
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleContent*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleContent* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -3141,17 +3139,17 @@ protected:
   nsTArray<nsStyleCounterData> mResets;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
 {
   explicit nsStyleUIReset(const nsPresContext* aContext);
   nsStyleUIReset(const nsStyleUIReset& aOther);
   ~nsStyleUIReset();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleUIReset*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleUIReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3195,17 +3193,17 @@ struct nsCursorImage
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
 {
   explicit nsStyleUserInterface(const nsPresContext* aContext);
   nsStyleUserInterface(const nsStyleUserInterface& aOther);
   ~nsStyleUserInterface();
 
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleUserInterface*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleUserInterface* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3228,17 +3226,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
 {
   explicit nsStyleXUL(const nsPresContext* aContext);
   nsStyleXUL(const nsStyleXUL& aSource);
   ~nsStyleXUL();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleXUL*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleXUL* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3258,17 +3256,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   mozilla::StyleStackSizing mStackSizing;   // [reset] see nsStyleConsts.h
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
 {
   explicit nsStyleColumn(const nsPresContext* aContext);
   nsStyleColumn(const nsStyleColumn& aSource);
   ~nsStyleColumn();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleColumn*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleColumn* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3393,17 +3391,17 @@ private:
   nscolor mFallbackColor;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
 {
   explicit nsStyleSVG(const nsPresContext* aContext);
   nsStyleSVG(const nsStyleSVG& aSource);
   ~nsStyleSVG();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleSVG*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleSVG* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3530,17 +3528,17 @@ private:
   uint8_t          mContextFlags;     // [inherited]
 };
 
 struct nsStyleFilter
 {
   nsStyleFilter();
   nsStyleFilter(const nsStyleFilter& aSource);
   ~nsStyleFilter();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleFilter*) {}
   const static bool kHasFinishStyle = false;
 
   nsStyleFilter& operator=(const nsStyleFilter& aOther);
 
   bool operator==(const nsStyleFilter& aOther) const;
   bool operator!=(const nsStyleFilter& aOther) const {
     return !(*this == aOther);
   }
@@ -3592,17 +3590,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 {
   explicit nsStyleSVGReset(const nsPresContext* aContext);
   nsStyleSVGReset(const nsStyleSVGReset& aSource);
   ~nsStyleSVGReset();
 
   // Resolves and tracks the images in mMask.  Only called with a Servo-backed
   // style system, where those images must be resolved later than the OMT
   // nsStyleSVGReset constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
+  void FinishStyle(nsPresContext*, const nsStyleSVGReset*);
   const static bool kHasFinishStyle = true;
 
   void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
   }
   void Destroy(nsPresContext* aContext);
@@ -3635,17 +3633,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
 // XXX This can be removed once the old style system is gone.
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
 {
   nsStyleVariables();
   explicit nsStyleVariables(const nsPresContext* aContext);
   nsStyleVariables(const nsStyleVariables& aSource);
   ~nsStyleVariables();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleVariables*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleVariables* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
   }
   void Destroy(nsPresContext* aContext) {
@@ -3661,17 +3659,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 #endif
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
 {
   explicit nsStyleEffects(const nsPresContext* aContext);
   nsStyleEffects(const nsStyleEffects& aSource);
   ~nsStyleEffects();
-  void FinishStyle(nsPresContext* aPresContext) {}
+  void FinishStyle(nsPresContext*, const nsStyleEffects*) {}
   const static bool kHasFinishStyle = false;
 
   void* operator new(size_t sz, nsStyleEffects* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
   }
   void Destroy(nsPresContext* aContext) {
--- a/layout/svg/SVGObserverUtils.cpp
+++ b/layout/svg/SVGObserverUtils.cpp
@@ -420,17 +420,17 @@ nsSVGMaskProperty::ResolveImage(uint32_t
   const nsStyleSVGReset* svgReset = mFrame->StyleSVGReset();
   MOZ_ASSERT(aIndex < svgReset->mMask.mImageCount);
 
   nsStyleImage& image =
     const_cast<nsStyleImage&>(svgReset->mMask.mLayers[aIndex].mImage);
 
   if (!image.IsResolved()) {
     MOZ_ASSERT(image.GetType() == nsStyleImageType::eStyleImageType_Image);
-    image.ResolveImage(mFrame->PresContext());
+    image.ResolveImage(mFrame->PresContext(), nullptr);
 
     mozilla::css::ImageLoader* imageLoader =
       mFrame->PresContext()->Document()->StyleImageLoader();
     if (imgRequestProxy* req = image.GetImageData()) {
       imageLoader->AssociateRequestToFrame(req, mFrame);
     }
   }
 }