Bug 1404181 - Part 12: Make FrameProperties support reentry during DeleteAll.
MozReview-Commit-ID: 1UgKpRRaZwL
--- 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_ */