Bug 1404181 - Part 12: Make FrameProperties support reentry during DeleteAll. draft
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 28 Sep 2017 10:16:13 +1300
changeset 682094 ad2742a380c7ad048c911b117191277a69eb7092
parent 682093 05c2e4ef9b68685dfdf46e70fa69d1cc40b60ec7
child 682095 dfa906a5b872c7785003be37159c07379e7b909f
push id85000
push usermwoodrow@mozilla.com
push dateWed, 18 Oct 2017 03:52:13 +0000
bugs1404181
milestone58.0a1
Bug 1404181 - Part 12: Make FrameProperties support reentry during DeleteAll. MozReview-Commit-ID: 1UgKpRRaZwL
layout/base/FrameProperties.h
--- a/layout/base/FrameProperties.h
+++ b/layout/base/FrameProperties.h
@@ -147,16 +147,17 @@ public:
   template<typename T>
   using Descriptor = const FramePropertyDescriptor<T>*;
   using UntypedDescriptor = const FramePropertyDescriptorUntyped*;
 
   template<typename T>
   using PropertyType = typename detail::FramePropertyTypeHelper<T>::Type;
 
   explicit FrameProperties()
+    : mInDeleteAll(false)
   {
   }
 
   ~FrameProperties()
   {
     MOZ_ASSERT(mProperties.Length() == 0, "forgot to delete properties");
   }
 
@@ -284,20 +285,22 @@ public:
     }
   }
 
   /**
    * Remove and destroy all property values for the frame.
    */
   void DeleteAll(const nsIFrame* aFrame) {
     mozilla::DebugOnly<size_t> len = mProperties.Length();
+    mInDeleteAll = true;
     for (auto& prop : mProperties) {
       prop.DestroyValueFor(aFrame);
       MOZ_ASSERT(mProperties.Length() == len);
     }
+    mInDeleteAll = false;
     mProperties.Clear();
   }
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
     // We currently report only the shallow size of the mProperties array.
     // As for the PropertyValue entries: we don't need to measure the mProperty
     // field of because it always points to static memory, and we can't measure
     // mValue because the type is opaque.
@@ -366,16 +369,19 @@ private:
    * Stores a property descriptor/value pair.
    */
   struct PropertyValue {
     PropertyValue() : mProperty(nullptr), mValue(nullptr) {}
     PropertyValue(UntypedDescriptor aProperty, void* aValue)
       : mProperty(aProperty), mValue(aValue) {}
 
     void DestroyValueFor(const nsIFrame* aFrame) {
+      if (!mProperty) {
+        return;
+      }
       if (mProperty->mDestructor) {
         mProperty->mDestructor(mValue);
       } else if (mProperty->mDestructorWithFrame) {
         mProperty->mDestructorWithFrame(aFrame, mValue);
       }
     }
 
     UntypedDescriptor mProperty;
@@ -395,16 +401,17 @@ private:
       return a == b.mProperty;
     }
     bool Equals(const PropertyValue& a, UntypedDescriptor b) const {
       return a.mProperty == b;
     }
   };
 
   nsTArray<PropertyValue> mProperties;
+  bool mInDeleteAll;
 };
 
 
 inline void*
 FrameProperties::GetInternal(UntypedDescriptor aProperty,
                              bool* aFoundResult) const
 {
   MOZ_ASSERT(aProperty, "Null property?");
@@ -464,30 +471,42 @@ FrameProperties::RemoveInternal(UntypedD
     return nullptr;
   }
 
   if (aFoundResult) {
     *aFoundResult = true;
   }
 
   void* result = mProperties.ElementAt(index).mValue;
-  mProperties.RemoveElementAt(index);
+
+  if (mInDeleteAll) {
+    mProperties.ElementAt(index).mProperty = nullptr;
+    mProperties.ElementAt(index).mValue = nullptr;
+  } else {
+    mProperties.RemoveElementAt(index);
+  }
 
   return result;
 }
 
 inline void
 FrameProperties::DeleteInternal(UntypedDescriptor aProperty,
                                 const nsIFrame* aFrame)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aProperty, "Null property?");
 
   auto index = mProperties.IndexOf(aProperty, 0, PropertyComparator());
   if (index != nsTArray<PropertyValue>::NoIndex) {
-    mProperties.ElementAt(index).DestroyValueFor(aFrame);
-    mProperties.RemoveElementAt(index);
+    PropertyValue pv = mProperties.ElementAt(index);
+    if (mInDeleteAll) {
+      mProperties.ElementAt(index).mProperty = nullptr;
+      mProperties.ElementAt(index).mValue = nullptr;
+    } else {
+      mProperties.RemoveElementAt(index);
+    }
+    pv.DestroyValueFor(aFrame);
   }
 }
 
 } // namespace mozilla
 
 #endif /* FRAMEPROPERTIES_H_ */