Bug 1301245 - Clean out mSourceURI if given URI does not contain a fragment. draft
authorcku <cku@mozilla.com>
Tue, 07 Mar 2017 17:31:48 +0800
changeset 495055 4d2a4db490392a725635eb5dc710435697fef133
parent 494263 b7e42143bbbc9dc3e5c05bd1e93b6485ce1d0ad4
child 548266 665bb042fc27fb5e00edbed9d1c6f58b6e606352
push id48211
push userbmo:cku@mozilla.com
push dateWed, 08 Mar 2017 06:25:40 +0000
bugs1301245
milestone55.0a1
Bug 1301245 - Clean out mSourceURI if given URI does not contain a fragment. heycam filed this bug to fix two things: 1. If the given url contains fragment, do not use Layer::mImage On bug 1301245 comment 2, I explained why we can not do this. 2. If the given url does not contain fragment, do not use Layer::mSourceURI At least we can fix #2, and this is what this patch focus on. MozReview-Commit-ID: HDJ7TeyqCpN
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsRuleNode.cpp
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2843,16 +2843,33 @@ css::URLValueData::GetURI() const
               nullptr, const_cast<nsIURI*>(mBaseURI.get()));
     mURI = new PtrHolder<nsIURI>(newURI.forget());
     mURIResolved = true;
   }
 
   return mURI;
 }
 
+bool
+css::URLValueData::HasRef() const
+{
+  nsIURI* uri = GetURI();
+  if (!uri) {
+    return false;
+  }
+
+  nsAutoCString ref;
+  nsresult rv = uri->GetRef(ref);
+  if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
+    return true;
+  }
+
+  return false;
+}
+
 already_AddRefed<nsIURI>
 css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
 {
   nsCOMPtr<nsIURI> result = GetURI();
 
   if (result && mIsLocalRef) {
     nsCString ref;
     mURI->GetRef(ref);
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -133,16 +133,18 @@ public:
   // Smae as DefinitelyEqualURIs but additionally compares the nsIPrincipal
   // pointers of the two URLValueData objects.
   bool DefinitelyEqualURIsAndPrincipal(const URLValueData& aOther) const;
 
   nsIURI* GetURI() const;
 
   bool IsLocalRef() const { return mIsLocalRef; }
 
+  bool HasRef() const;
+
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLValueData)
 
   // When matching a url with mIsLocalRef set, resolve it against aURI;
   // Otherwise, ignore aURL and return mURL directly.
   already_AddRefed<nsIURI> ResolveLocalRef(nsIURI* aURI) const;
   already_AddRefed<nsIURI> ResolveLocalRef(nsIContent* aContent) const;
 
   // Serializes mURI as a computed URI value, taking into account mIsLocalRef
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -7129,17 +7129,18 @@ SetImageLayerList(nsStyleContext* aStyle
                   nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
                   const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
                   ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
                   ComputedValueItem aInitialValue,
                   uint32_t aParentItemCount,
                   uint32_t& aItemCount,
                   uint32_t& aMaxItemCount,
                   bool& aRebuild,
-                  RuleNodeCacheConditions& aConditions)
+                  RuleNodeCacheConditions& aConditions,
+                  std::function<void(ComputedValueItem&)> aCallback = std::function<void(ComputedValueItem&)>())
 {
   switch (aValue.GetUnit()) {
   case eCSSUnit_Null:
     break;
 
   case eCSSUnit_Inherit:
     aRebuild = true;
     aConditions.SetUncacheable();
@@ -7169,16 +7170,19 @@ SetImageLayerList(nsStyleContext* aStyle
                    item->mValue.GetUnit() != eCSSUnit_Unset,
                    "unexpected unit");
       ++aItemCount;
       aLayers.EnsureLengthAtLeast(aItemCount);
       BackgroundItemComputer<nsCSSValueList, ComputedValueItem>
         ::ComputeValue(aStyleContext, item,
                        aLayers[aItemCount-1].*aResultLocation,
                        aConditions);
+      if (aCallback) {
+        aCallback(aLayers[aItemCount-1].*aResultLocation);
+      }
       item = item->mNext;
     } while (item);
     break;
   }
 
   default:
     MOZ_ASSERT(false, "unexpected unit");
   }
@@ -7265,17 +7269,18 @@ SetImageLayerPairList(nsStyleContext* aS
                       const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
                       ComputedValueItem nsStyleImageLayers::Layer::*
                                                                 aResultLocation,
                       ComputedValueItem aInitialValue,
                       uint32_t aParentItemCount,
                       uint32_t& aItemCount,
                       uint32_t& aMaxItemCount,
                       bool& aRebuild,
-                      RuleNodeCacheConditions& aConditions)
+                      RuleNodeCacheConditions& aConditions,
+                      std::function<void(ComputedValueItem&)> aCallback = std::function<void(ComputedValueItem&)>())
 {
   switch (aValue.GetUnit()) {
   case eCSSUnit_Null:
     break;
 
   case eCSSUnit_Inherit:
     aRebuild = true;
     aConditions.SetUncacheable();
@@ -7307,16 +7312,19 @@ SetImageLayerPairList(nsStyleContext* aS
                    item->mYValue.GetUnit() != eCSSUnit_Unset,
                    "unexpected unit");
       ++aItemCount;
       aLayers.EnsureLengthAtLeast(aItemCount);
       BackgroundItemComputer<nsCSSValuePairList, ComputedValueItem>
         ::ComputeValue(aStyleContext, item,
                        aLayers[aItemCount-1].*aResultLocation,
                        aConditions);
+      if (aCallback) {
+        aCallback(aLayers[aItemCount-1].*aResultLocation);
+      }
       item = item->mNext;
     } while (item);
     break;
   }
 
   default:
     MOZ_ASSERT(false, "unexpected unit");
   }
@@ -10064,17 +10072,30 @@ nsRuleNode::ComputeSVGResetData(void* aS
                     maxItemCount, rebuild, conditions);
   SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
                     svgReset->mMask.mLayers,
                     parentSVGReset->mMask.mLayers,
                     &nsStyleImageLayers::Layer::mSourceURI,
                     RefPtr<css::URLValueData>(),
                     parentSVGReset->mMask.mImageCount,
                     svgReset->mMask.mImageCount,
-                    maxItemCount, rebuild, conditions);
+                    maxItemCount, rebuild, conditions,
+                    std::function<void(RefPtr<css::URLValueData>&)>(
+                      [](RefPtr<css::URLValueData>& aComputedValue) {
+                        // mSourceURI can be used to address an SVG mask only
+                        // if it contains a fragment, not vice versa. If not,
+                        // we can just clean it out now, to prevent resouce
+                        // lookup in rendering process.
+                        if (aComputedValue) {
+                          if (!aComputedValue->HasRef()) {
+                            aComputedValue = nullptr;
+                          }
+                        }
+                      })
+                    );
 
   // mask-repeat: enum, inherit, initial [pair list]
   nsStyleImageLayers::Repeat initialRepeat;
   initialRepeat.SetInitialValues();
   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
                         svgReset->mMask.mLayers,
                         parentSVGReset->mMask.mLayers,
                         &nsStyleImageLayers::Layer::mRepeat,