Bug 1354772 - Part 1. Compute URLValueData::mIsLocalRef when need. draft
authorcku <cku@mozilla.com>
Mon, 10 Apr 2017 17:25:48 +0800
changeset 560485 f4560cf43290bbb598f48a02efd970a9f8ba31cc
parent 560424 f914d40a48009c5acd1093e9939cc0ec035696dd
child 560486 6bb071f15a708d3063438e4426a7f2badc6d4165
push id53430
push userbmo:cku@mozilla.com
push dateTue, 11 Apr 2017 13:47:32 +0000
bugs1354772
milestone55.0a1
Bug 1354772 - Part 1. Compute URLValueData::mIsLocalRef when need. MozReview-Commit-ID: 77pcTcaScF0
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -2783,29 +2783,27 @@ nsCSSValue::Array::SizeOfIncludingThis(m
 
 css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
                                 nsStringBuffer* aString,
                                 already_AddRefed<URLExtraData> aExtraData)
   : mURI(Move(aURI))
   , mString(aString)
   , mExtraData(Move(aExtraData))
   , mURIResolved(true)
-  , mIsLocalRef(IsLocalRefURL(aString))
 {
   MOZ_ASSERT(mString);
   MOZ_ASSERT(mExtraData);
   MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 css::URLValueData::URLValueData(nsStringBuffer* aString,
                                 already_AddRefed<URLExtraData> aExtraData)
   : mString(aString)
   , mExtraData(Move(aExtraData))
   , mURIResolved(false)
-  , mIsLocalRef(IsLocalRefURL(aString))
 {
   MOZ_ASSERT(aString);
   MOZ_ASSERT(mExtraData);
   MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 bool
 css::URLValueData::Equals(const URLValueData& aOther) const
@@ -2822,17 +2820,17 @@ css::URLValueData::Equals(const URLValue
            (mURI && aOther.mURI &&
             NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
             eq)) &&
           (self->BaseURI() == other->BaseURI() ||
            (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
             eq)) &&
           (self->GetPrincipal() == other->GetPrincipal() ||
            self->GetPrincipal()->Equals(other->GetPrincipal())) &&
-          mIsLocalRef == aOther.mIsLocalRef;
+          IsLocalRef() == aOther.IsLocalRef();
 }
 
 bool
 css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
 {
   return mExtraData->BaseURI() == aOther.mExtraData->BaseURI() &&
          (mString == aOther.mString ||
           NS_strcmp(nsCSSValue::GetBufferValue(mString),
@@ -2861,16 +2859,27 @@ css::URLValueData::GetURI() const
     mURI = new PtrHolder<nsIURI>(newURI.forget());
     mURIResolved = true;
   }
 
   return mURI;
 }
 
 bool
+css::URLValueData::IsLocalRef() const
+{
+  if (mIsLocalRef.isNothing()) {
+    // IsLocalRefURL is O(N), use it only when IsLocalRef is called.
+    mIsLocalRef.emplace(IsLocalRefURL(mString));
+  }
+
+  return mIsLocalRef.value();
+}
+
+bool
 css::URLValueData::HasRef() const
 {
   if (IsLocalRef()) {
     return true;
   }
 
   nsIURI* uri = GetURI();
   if (!uri) {
@@ -2886,17 +2895,17 @@ css::URLValueData::HasRef() const
   return false;
 }
 
 already_AddRefed<nsIURI>
 css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
 {
   nsCOMPtr<nsIURI> result = GetURI();
 
-  if (result && mIsLocalRef) {
+  if (result && IsLocalRef()) {
     nsCString ref;
     mURI->GetRef(ref);
 
     aURI->Clone(getter_AddRefs(result));
     result->SetRef(ref);
   }
 
   return result.forget();
@@ -2914,17 +2923,17 @@ css::URLValueData::GetSourceString(nsStr
 {
   nsIURI* uri = GetURI();
   if (!uri) {
     aRef.Truncate();
     return;
   }
 
   nsCString cref;
-  if (mIsLocalRef) {
+  if (IsLocalRef()) {
     // XXXheycam It's possible we can just return mString in this case, since
     // it should be the "#fragment" string the URLValueData was created with.
     uri->GetRef(cref);
     cref.Insert('#', 0);
   } else {
     // It's not entirely clear how to best handle failure here. Ensuring the
     // string is empty seems safest.
     nsresult rv = uri->GetSpec(cref);
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -126,17 +126,17 @@ public:
   bool DefinitelyEqualURIs(const URLValueData& aOther) const;
 
   // 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 IsLocalRef() const;
 
   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;
@@ -153,17 +153,17 @@ private:
   // invalid, even once resolved.
   mutable PtrHandle<nsIURI> mURI;
 public:
   RefPtr<nsStringBuffer> mString;
   RefPtr<URLExtraData> mExtraData;
 private:
   mutable bool mURIResolved;
   // mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
-  bool mIsLocalRef;
+  mutable Maybe<bool> mIsLocalRef;
 
 protected:
   virtual ~URLValueData() = default;
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   URLValueData(const URLValueData& aOther) = delete;