Bug 1377993 - Make node slots less memory hungry in common cases.

Tag UXP Issue #1344
This commit is contained in:
Gaming4JC 2020-01-04 19:48:30 -05:00 • committed by Roy Tam
commit dd7fa403a8
9 changed files with 203 additions and 178 deletions

View file

@ -1595,7 +1595,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
#endif #endif
{ {
if (aBindingParent) { if (aBindingParent) {
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mBindingParent = aBindingParent; // Weak, so no addref happens. slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
} }
@ -1618,7 +1618,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
} }
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow(); ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
if (parentContainingShadow) { if (parentContainingShadow) {
DOMSlots()->mContainingShadow = parentContainingShadow; ExtendedDOMSlots()->mContainingShadow = parentContainingShadow;
} }
} }
@ -2007,7 +2007,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
} }
#endif #endif
nsDOMSlots* slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
if (clearBindingParent) { if (clearBindingParent) {
slots->mBindingParent = nullptr; slots->mBindingParent = nullptr;
@ -2055,7 +2055,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
nsICSSDeclaration* nsICSSDeclaration*
Element::GetSMILOverrideStyle() Element::GetSMILOverrideStyle()
{ {
Element::nsDOMSlots *slots = DOMSlots(); Element::nsExtendedDOMSlots* slots = ExtendedDOMSlots();
if (!slots->mSMILOverrideStyle) { if (!slots->mSMILOverrideStyle) {
slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true); slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
@ -2067,7 +2067,7 @@ Element::GetSMILOverrideStyle()
DeclarationBlock* DeclarationBlock*
Element::GetSMILOverrideStyleDeclaration() Element::GetSMILOverrideStyleDeclaration()
{ {
Element::nsDOMSlots *slots = GetExistingDOMSlots(); Element::nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr; return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
} }
@ -2075,7 +2075,7 @@ nsresult
Element::SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration, Element::SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
bool aNotify) bool aNotify)
{ {
Element::nsDOMSlots *slots = DOMSlots(); Element::nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mSMILOverrideStyleDeclaration = aDeclaration; slots->mSMILOverrideStyleDeclaration = aDeclaration;
@ -3988,7 +3988,7 @@ Element::ClearDataset()
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers() Element::RegisteredIntersectionObservers()
{ {
nsDOMSlots* slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
return &slots->mRegisteredIntersectionObservers; return &slots->mRegisteredIntersectionObservers;
} }
@ -4041,7 +4041,7 @@ Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32
void void
Element::SetCustomElementData(CustomElementData* aData) Element::SetCustomElementData(CustomElementData* aData)
{ {
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots *slots = ExtendedDOMSlots();
MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set."); MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
slots->mCustomElementData = aData; slots->mCustomElementData = aData;
} }

View file

@ -398,7 +398,7 @@ public:
*/ */
inline CustomElementData* GetCustomElementData() const inline CustomElementData* GetCustomElementData() const
{ {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return slots->mCustomElementData; return slots->mCustomElementData;
} }
@ -837,7 +837,7 @@ public:
ShadowRoot *FastGetShadowRoot() const ShadowRoot *FastGetShadowRoot() const
{ {
nsDOMSlots* slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mShadowRoot.get() : nullptr; return slots ? slots->mShadowRoot.get() : nullptr;
} }

View file

@ -530,8 +530,7 @@ nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FragmentOrElement::nsDOMSlots::nsDOMSlots() FragmentOrElement::nsDOMSlots::nsDOMSlots()
: nsINode::nsSlots(), : nsINode::nsSlots(),
mDataset(nullptr), mDataset(nullptr)
mBindingParent(nullptr)
{ {
} }
@ -543,84 +542,104 @@ FragmentOrElement::nsDOMSlots::~nsDOMSlots()
} }
void void
FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL) FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{ {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
cb.NoteXPCOMChild(mStyle.get()); cb.NoteXPCOMChild(mStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
cb.NoteXPCOMChild(mSMILOverrideStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
cb.NoteXPCOMChild(mAttributeMap.get()); cb.NoteXPCOMChild(mAttributeMap.get());
if (aIsXUL) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
cb.NoteXPCOMChild(mControllers);
}
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLBinding");
cb.NoteNativeChild(mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
cb.NoteXPCOMChild(mXBLInsertionParent.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mShadowRoot");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList)); cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
cb.NoteXPCOMChild(mClassList.get()); cb.NoteXPCOMChild(mClassList.get());
if (mCustomElementData) { if (!mExtendedSlots) {
for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) { return;
mCustomElementData->mCallbackQueue[i]->Traverse(cb); }
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mSMILOverrideStyle");
cb.NoteXPCOMChild(mExtendedSlots->mSMILOverrideStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mControllers");
cb.NoteXPCOMChild(mExtendedSlots->mControllers);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mLabelsList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*,mExtendedSlots-> mLabelsList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mShadowRoot");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mShadowRoot));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mContainingShadow");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLBinding");
cb.NoteNativeChild(mExtendedSlots->mXBLBinding,
NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLInsertionParent");
cb.NoteXPCOMChild(mExtendedSlots->mXBLInsertionParent.get());
if (mExtendedSlots->mCustomElementData) {
for (uint32_t i = 0;
i < mExtendedSlots->mCustomElementData->mCallbackQueue.Length(); i++) {
mExtendedSlots->mCustomElementData->mCallbackQueue[i]->Traverse(cb);
} }
} }
for (auto iter = mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) { for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter();
!iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key(); DOMIntersectionObserver* observer = iter.Key();
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mRegisteredIntersectionObservers[i]"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mExtendedSlots->mRegisteredIntersectionObservers[i]");
cb.NoteXPCOMChild(observer); cb.NoteXPCOMChild(observer);
} }
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mFrameLoaderOrOpener");
cb.NoteXPCOMChild(mExtendedSlots->mFrameLoaderOrOpener);
} }
void void
FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL) FragmentOrElement::nsDOMSlots::Unlink()
{ {
mStyle = nullptr; mStyle = nullptr;
mSMILOverrideStyle = nullptr;
if (mAttributeMap) { if (mAttributeMap) {
mAttributeMap->DropReference(); mAttributeMap->DropReference();
mAttributeMap = nullptr; mAttributeMap = nullptr;
} }
if (aIsXUL)
NS_IF_RELEASE(mControllers);
MOZ_ASSERT(!mXBLBinding);
mXBLInsertionParent = nullptr;
mShadowRoot = nullptr;
mContainingShadow = nullptr;
mChildrenList = nullptr; mChildrenList = nullptr;
mLabelsList = nullptr;
mCustomElementData = nullptr;
mClassList = nullptr; mClassList = nullptr;
mRegisteredIntersectionObservers.Clear();
if (!mExtendedSlots) {
return;
}
mExtendedSlots->mSMILOverrideStyle = nullptr;
mExtendedSlots->mControllers = nullptr;
mExtendedSlots->mLabelsList = nullptr;
mExtendedSlots->mShadowRoot = nullptr;
mExtendedSlots->mContainingShadow = nullptr;
MOZ_ASSERT(!(mExtendedSlots->mXBLBinding));
mExtendedSlots->mXBLInsertionParent = nullptr;
mExtendedSlots->mCustomElementData = nullptr;
mExtendedSlots->mRegisteredIntersectionObservers.Clear();
nsCOMPtr<nsIFrameLoader> frameLoader =
do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
if (frameLoader) {
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
}
mExtendedSlots->mFrameLoaderOrOpener = nullptr;
} }
size_t size_t
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{ {
size_t n = aMallocSizeOf(this); size_t n = aMallocSizeOf(this);
if (mExtendedSlots) {
n += aMallocSizeOf(mExtendedSlots.get());
}
if (mAttributeMap) { if (mAttributeMap) {
n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf); n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf);
@ -641,6 +660,19 @@ FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) c
return n; return n;
} }
FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots()
: mBindingParent(nullptr)
{
}
FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
{
nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
if (frameLoader) {
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
}
}
FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsIContent(aNodeInfo) : nsIContent(aNodeInfo)
{ {
@ -962,7 +994,7 @@ FragmentOrElement::IsLink(nsIURI** aURI) const
nsIContent* nsIContent*
FragmentOrElement::GetBindingParent() const FragmentOrElement::GetBindingParent() const
{ {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return slots->mBindingParent; return slots->mBindingParent;
@ -974,7 +1006,7 @@ nsXBLBinding*
FragmentOrElement::GetXBLBinding() const FragmentOrElement::GetXBLBinding() const
{ {
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return slots->mXBLBinding; return slots->mXBLBinding;
} }
@ -1009,11 +1041,11 @@ FragmentOrElement::SetXBLBinding(nsXBLBinding* aBinding,
if (aBinding) { if (aBinding) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR); SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mXBLBinding = aBinding; slots->mXBLBinding = aBinding;
bindingManager->AddBoundContent(this); bindingManager->AddBoundContent(this);
} else { } else {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
slots->mXBLBinding = nullptr; slots->mXBLBinding = nullptr;
} }
@ -1028,7 +1060,7 @@ nsIContent*
FragmentOrElement::GetXBLInsertionParent() const FragmentOrElement::GetXBLInsertionParent() const
{ {
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return slots->mXBLInsertionParent; return slots->mXBLInsertionParent;
} }
@ -1040,7 +1072,7 @@ FragmentOrElement::GetXBLInsertionParent() const
ShadowRoot* ShadowRoot*
FragmentOrElement::GetContainingShadow() const FragmentOrElement::GetContainingShadow() const
{ {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return slots->mContainingShadow; return slots->mContainingShadow;
} }
@ -1050,21 +1082,21 @@ FragmentOrElement::GetContainingShadow() const
void void
FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot) FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot)
{ {
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mShadowRoot = aShadowRoot; slots->mShadowRoot = aShadowRoot;
} }
nsTArray<nsIContent*>& nsTArray<nsIContent*>&
FragmentOrElement::DestInsertionPoints() FragmentOrElement::DestInsertionPoints()
{ {
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
return slots->mDestInsertionPoints; return slots->mDestInsertionPoints;
} }
nsTArray<nsIContent*>* nsTArray<nsIContent*>*
FragmentOrElement::GetExistingDestInsertionPoints() const FragmentOrElement::GetExistingDestInsertionPoints() const
{ {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
return &slots->mDestInsertionPoints; return &slots->mDestInsertionPoints;
} }
@ -1075,11 +1107,11 @@ void
FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent) FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
{ {
if (aContent) { if (aContent) {
nsDOMSlots *slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR); SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
slots->mXBLInsertionParent = aContent; slots->mXBLInsertionParent = aContent;
} else { } else {
nsDOMSlots *slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
slots->mXBLInsertionParent = nullptr; slots->mXBLInsertionParent = nullptr;
} }
@ -1348,14 +1380,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
{ {
nsDOMSlots *slots = tmp->GetExistingDOMSlots(); nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) { if (slots) {
if (tmp->IsElement()) { if (slots->mExtendedSlots && tmp->IsElement()) {
Element* elem = tmp->AsElement(); Element* elem = tmp->AsElement();
for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) { for (auto iter = slots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
!iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key(); DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem); observer->UnlinkTarget(*elem);
} }
} }
slots->Unlink(tmp->IsXULElement()); slots->Unlink();
} }
} }
@ -1920,7 +1953,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
{ {
nsDOMSlots *slots = tmp->GetExistingDOMSlots(); nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) { if (slots) {
slots->Traverse(cb, tmp->IsXULElement()); slots->Traverse(cb);
} }
} }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

View file

@ -15,6 +15,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/UniquePtr.h"
#include "nsAttrAndChildArray.h" // member #include "nsAttrAndChildArray.h" // member
#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_* #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
#include "nsIContent.h" // base class #include "nsIContent.h" // base class
@ -239,8 +240,6 @@ protected:
nsresult CopyInnerTo(FragmentOrElement* aDest); nsresult CopyInnerTo(FragmentOrElement* aDest);
public: public:
// Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
// otherwise nsXULElement::nsXULSlots doesn't compile.
/** /**
* There are a set of DOM- and scripting-specific instance variables * There are a set of DOM- and scripting-specific instance variables
* that may only be instantiated when a content object is accessed * that may only be instantiated when a content object is accessed
@ -249,29 +248,13 @@ public:
* in a side structure that's only allocated when the content is * in a side structure that's only allocated when the content is
* accessed through the DOM. * accessed through the DOM.
*/ */
class nsDOMSlots : public nsINode::nsSlots
class nsExtendedDOMSlots
{ {
public: public:
nsDOMSlots(); nsExtendedDOMSlots();
virtual ~nsDOMSlots();
void Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL); ~nsExtendedDOMSlots();
void Unlink(bool aIsXUL);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
/**
* The .style attribute (an interface that forwards to the actual
* style rules)
* @see nsGenericHTMLElement::GetStyle
*/
nsCOMPtr<nsICSSDeclaration> mStyle;
/**
* The .dataset attribute.
* @see nsGenericHTMLElement::GetDataset
*/
nsDOMStringMap* mDataset; // [Weak]
/** /**
* SMIL Overridde style rules (for SMIL animation of CSS properties) * SMIL Overridde style rules (for SMIL animation of CSS properties)
@ -285,35 +268,17 @@ public:
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration; RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
/** /**
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes) * The nearest enclosing content node with a binding that created us.
* @see FragmentOrElement::GetAttributes * @see FragmentOrElement::GetBindingParent
*/ */
RefPtr<nsDOMAttributeMap> mAttributeMap; nsIContent* mBindingParent; // [Weak]
union {
/**
* The nearest enclosing content node with a binding that created us.
* @see FragmentOrElement::GetBindingParent
*/
nsIContent* mBindingParent; // [Weak]
/**
* The controllers of the XUL Element.
*/
nsIControllers* mControllers; // [OWNER]
};
/** /**
* An object implementing the .children property for this element. * The controllers of the XUL Element.
*/ */
RefPtr<nsContentList> mChildrenList; nsCOMPtr<nsIControllers> mControllers;
/** /**
* An object implementing the .classList property for this element.
*/
RefPtr<nsDOMTokenList> mClassList;
/*
* An object implementing the .labels property for this element. * An object implementing the .labels property for this element.
*/ */
RefPtr<nsLabelsNodeList> mLabelsList; RefPtr<nsLabelsNodeList> mLabelsList;
@ -354,6 +319,55 @@ public:
*/ */
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t> nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
mRegisteredIntersectionObservers; mRegisteredIntersectionObservers;
/**
* For XUL to hold either frameloader or opener.
*/
nsCOMPtr<nsISupports> mFrameLoaderOrOpener;
};
class nsDOMSlots : public nsINode::nsSlots
{
public:
nsDOMSlots();
virtual ~nsDOMSlots();
void Traverse(nsCycleCollectionTraversalCallback &cb);
void Unlink();
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
/**
* The .style attribute (an interface that forwards to the actual
* style rules)
* @see nsGenericHTMLElement::GetStyle
*/
nsCOMPtr<nsICSSDeclaration> mStyle;
/**
* The .dataset attribute.
* @see nsGenericHTMLElement::GetDataset
*/
nsDOMStringMap* mDataset; // [Weak]
/**
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
* @see FragmentOrElement::GetAttributes
*/
RefPtr<nsDOMAttributeMap> mAttributeMap;
/**
* An object implementing the .children property for this element.
*/
RefPtr<nsContentList> mChildrenList;
/**
* An object implementing the .classList property for this element.
*/
RefPtr<nsDOMTokenList> mClassList;
mozilla::UniquePtr<nsExtendedDOMSlots> mExtendedSlots;
}; };
protected: protected:
@ -373,6 +387,26 @@ protected:
return static_cast<nsDOMSlots*>(GetExistingSlots()); return static_cast<nsDOMSlots*>(GetExistingSlots());
} }
nsExtendedDOMSlots* ExtendedDOMSlots()
{
nsDOMSlots* slots = DOMSlots();
if (!slots->mExtendedSlots) {
slots->mExtendedSlots = MakeUnique<nsExtendedDOMSlots>();
}
return slots->mExtendedSlots.get();
}
nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
{
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots) {
return slots->mExtendedSlots.get();
}
return nullptr;
}
/** /**
* Calls SetIsElementInStyleScopeFlagOnSubtree for each shadow tree attached * Calls SetIsElementInStyleScopeFlagOnSubtree for each shadow tree attached
* to this node, which is assumed to be an Element. * to this node, which is assumed to be an Element.

View file

@ -75,8 +75,8 @@ ShadowRoot::ShadowRoot(nsIContent* aContent,
SetFlags(NODE_IS_IN_SHADOW_TREE); SetFlags(NODE_IS_IN_SHADOW_TREE);
DOMSlots()->mBindingParent = aContent; ExtendedDOMSlots()->mBindingParent = aContent;
DOMSlots()->mContainingShadow = this; ExtendedDOMSlots()->mContainingShadow = this;
// Add the ShadowRoot as a mutation observer on the host to watch // Add the ShadowRoot as a mutation observer on the host to watch
// for mutations because the insertion points in this ShadowRoot // for mutations because the insertion points in this ShadowRoot

View file

@ -301,9 +301,12 @@ nsNodeUtils::LastRelease(nsINode* aNode)
Element* elem = aNode->AsElement(); Element* elem = aNode->AsElement();
FragmentOrElement::nsDOMSlots* domSlots = FragmentOrElement::nsDOMSlots* domSlots =
static_cast<FragmentOrElement::nsDOMSlots*>(slots); static_cast<FragmentOrElement::nsDOMSlots*>(slots);
for (auto iter = domSlots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) { if (domSlots->mExtendedSlots) {
DOMIntersectionObserver* observer = iter.Key(); for (auto iter = domSlots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
observer->UnlinkTarget(*elem); !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem);
}
} }
} }

View file

@ -497,7 +497,7 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
// We need to consider a labels element is moved to another subtree // We need to consider a labels element is moved to another subtree
// with different root, it needs to update labels list and its root // with different root, it needs to update labels list and its root
// as well. // as well.
nsDOMSlots* slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots && slots->mLabelsList) { if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
} }
@ -524,7 +524,7 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
// We need to consider a labels element is removed from tree, // We need to consider a labels element is removed from tree,
// it needs to update labels list and its root as well. // it needs to update labels list and its root as well.
nsDOMSlots* slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots && slots->mLabelsList) { if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot()); slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
} }
@ -1730,7 +1730,7 @@ nsGenericHTMLElement::Labels()
{ {
MOZ_ASSERT(IsLabelable(), MOZ_ASSERT(IsLabelable(),
"Labels() only allow labelable elements to use it."); "Labels() only allow labelable elements to use it.");
nsDOMSlots* slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
if (!slots->mLabelsList) { if (!slots->mLabelsList) {
slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement, slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement,

View file

@ -174,33 +174,6 @@ nsXULElement::~nsXULElement()
{ {
} }
nsXULElement::nsXULSlots::nsXULSlots()
: nsXULElement::nsDOMSlots()
{
}
nsXULElement::nsXULSlots::~nsXULSlots()
{
NS_IF_RELEASE(mControllers); // Forces release
nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
if (frameLoader) {
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
}
}
void
nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoaderOrOpener");
cb.NoteXPCOMChild(mFrameLoaderOrOpener);
}
nsINode::nsSlots*
nsXULElement::CreateSlots()
{
return new nsXULSlots();
}
void void
nsXULElement::MaybeUpdatePrivateLifetime() nsXULElement::MaybeUpdatePrivateLifetime()
{ {
@ -326,12 +299,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULElement,
nsStyledElement) nsStyledElement)
{
nsXULSlots* slots = static_cast<nsXULSlots*>(tmp->GetExistingSlots());
if (slots) {
slots->Traverse(cb);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULElement, NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULElement,
@ -895,9 +863,9 @@ nsXULElement::UnbindFromTree(bool aDeep, bool aNullParent)
// mDocument in nsGlobalWindow::SetDocShell, but I'm not // mDocument in nsGlobalWindow::SetDocShell, but I'm not
// sure whether that would fix all possible cycles through // sure whether that would fix all possible cycles through
// mControllers.) // mControllers.)
nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots()); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
NS_IF_RELEASE(slots->mControllers); slots->mControllers = nullptr;
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader) { if (frameLoader) {
frameLoader->Destroy(); frameLoader->Destroy();
@ -1241,9 +1209,9 @@ nsXULElement::RemoveBroadcaster(const nsAString & broadcasterId)
void void
nsXULElement::DestroyContent() nsXULElement::DestroyContent()
{ {
nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots()); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) { if (slots) {
NS_IF_RELEASE(slots->mControllers); slots->mControllers = nullptr;
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (frameLoader) { if (frameLoader) {
frameLoader->Destroy(); frameLoader->Destroy();
@ -1473,7 +1441,7 @@ nsIControllers*
nsXULElement::GetControllers(ErrorResult& rv) nsXULElement::GetControllers(ErrorResult& rv)
{ {
if (! Controllers()) { if (! Controllers()) {
nsDOMSlots* slots = DOMSlots(); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers), rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers),
reinterpret_cast<void**>(&slots->mControllers)); reinterpret_cast<void**>(&slots->mControllers));
@ -1578,7 +1546,7 @@ nsXULElement::LoadSrc()
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
if (!frameLoader) { if (!frameLoader) {
// Check if we have an opener we need to be setting // Check if we have an opener we need to be setting
nsXULSlots* slots = static_cast<nsXULSlots*>(Slots()); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryInterface(slots->mFrameLoaderOrOpener); nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryInterface(slots->mFrameLoaderOrOpener);
if (!opener) { if (!opener) {
// If we are a content-primary xul-browser, we want to take the opener property! // If we are a content-primary xul-browser, we want to take the opener property!
@ -1624,7 +1592,7 @@ nsXULElement::GetFrameLoaderXPCOM(nsIFrameLoader **aFrameLoader)
already_AddRefed<nsFrameLoader> already_AddRefed<nsFrameLoader>
nsXULElement::GetFrameLoader() nsXULElement::GetFrameLoader()
{ {
nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingSlots()); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (!slots) if (!slots)
return nullptr; return nullptr;
@ -1646,7 +1614,7 @@ nsXULElement::GetParentApplication(mozIApplication** aApplication)
void void
nsXULElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv) nsXULElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
{ {
nsXULSlots* slots = static_cast<nsXULSlots*>(Slots()); nsExtendedDOMSlots* slots = ExtendedDOMSlots();
MOZ_ASSERT(!slots->mFrameLoaderOrOpener, "A frameLoader or opener is present when calling PresetOpenerWindow"); MOZ_ASSERT(!slots->mFrameLoaderOrOpener, "A frameLoader or opener is present when calling PresetOpenerWindow");
slots->mFrameLoaderOrOpener = aWindow; slots->mFrameLoaderOrOpener = aWindow;
@ -1662,7 +1630,7 @@ nsXULElement::SetIsPrerendered()
void void
nsXULElement::InternalSetFrameLoader(nsIFrameLoader* aNewFrameLoader) nsXULElement::InternalSetFrameLoader(nsIFrameLoader* aNewFrameLoader)
{ {
nsXULSlots* slots = static_cast<nsXULSlots*>(GetExistingDOMSlots()); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
MOZ_ASSERT(slots); MOZ_ASSERT(slots);
slots->mFrameLoaderOrOpener = aNewFrameLoader; slots->mFrameLoaderOrOpener = aNewFrameLoader;

View file

@ -609,19 +609,6 @@ protected:
nsresult AddPopupListener(nsIAtom* aName); nsresult AddPopupListener(nsIAtom* aName);
class nsXULSlots : public mozilla::dom::Element::nsDOMSlots
{
public:
nsXULSlots();
virtual ~nsXULSlots();
void Traverse(nsCycleCollectionTraversalCallback &cb);
nsCOMPtr<nsISupports> mFrameLoaderOrOpener;
};
virtual nsINode::nsSlots* CreateSlots() override;
nsresult LoadSrc(); nsresult LoadSrc();
/** /**
@ -677,8 +664,8 @@ protected:
// Internal accessor. This shadows the 'Slots', and returns // Internal accessor. This shadows the 'Slots', and returns
// appropriate value. // appropriate value.
nsIControllers *Controllers() { nsIControllers *Controllers() {
nsDOMSlots* slots = GetExistingDOMSlots(); nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mControllers : nullptr; return slots ? slots->mControllers.get() : nullptr;
} }
void UnregisterAccessKey(const nsAString& aOldValue); void UnregisterAccessKey(const nsAString& aOldValue);