mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 730587: Stash a pointer to the subtree root on DOM nodes. r=smaug, sr=jst
This commit is contained in:
parent
71ca779083
commit
fd1ce47377
@ -93,8 +93,7 @@ public:
|
||||
// nsIContent is that it exists with an IID
|
||||
|
||||
nsIContent(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsINode(aNodeInfo),
|
||||
mPrimaryFrame(nsnull)
|
||||
: nsINode(aNodeInfo)
|
||||
{
|
||||
NS_ASSERTION(mNodeInfo,
|
||||
"No nsINodeInfo passed to nsIContent, PREPARE TO CRASH!!!");
|
||||
@ -859,8 +858,12 @@ public:
|
||||
* In the case of absolutely positioned elements and floated elements, this
|
||||
* frame is the out of flow frame, not the placeholder.
|
||||
*/
|
||||
nsIFrame* GetPrimaryFrame() const { return mPrimaryFrame; }
|
||||
nsIFrame* GetPrimaryFrame() const
|
||||
{
|
||||
return IsInDoc() ? mPrimaryFrame : nsnull;
|
||||
}
|
||||
void SetPrimaryFrame(nsIFrame* aFrame) {
|
||||
NS_ASSERTION(IsInDoc(), "This will end badly!");
|
||||
NS_PRECONDITION(!aFrame || !mPrimaryFrame || aFrame == mPrimaryFrame,
|
||||
"Losing track of existing primary frame");
|
||||
mPrimaryFrame = aFrame;
|
||||
@ -962,11 +965,6 @@ private:
|
||||
*/
|
||||
virtual const nsAttrValue* DoGetClasses() const = 0;
|
||||
|
||||
/**
|
||||
* Pointer to our primary frame. Might be null.
|
||||
*/
|
||||
nsIFrame* mPrimaryFrame;
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
|
@ -1994,4 +1994,10 @@ nsINode::GetOwnerDocument() const
|
||||
return ownerDoc != this ? ownerDoc : nsnull;
|
||||
}
|
||||
|
||||
inline nsINode*
|
||||
nsINode::OwnerDocAsNode() const
|
||||
{
|
||||
return OwnerDoc();
|
||||
}
|
||||
|
||||
#endif /* nsIDocument_h___ */
|
||||
|
@ -345,6 +345,11 @@ public:
|
||||
friend class nsAttrAndChildArray;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
// Disable annoying warning about 'this' in initializers.
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: mNodeInfo(aNodeInfo),
|
||||
mParent(nsnull),
|
||||
@ -353,10 +358,14 @@ public:
|
||||
mNextSibling(nsnull),
|
||||
mPreviousSibling(nsnull),
|
||||
mFirstChild(nsnull),
|
||||
mSubtreeRoot(this),
|
||||
mSlots(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
virtual ~nsINode();
|
||||
@ -463,6 +472,12 @@ public:
|
||||
return mNodeInfo->GetDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the "owner document" of this node as an nsINode*. Implemented
|
||||
* in nsIDocument.h.
|
||||
*/
|
||||
inline nsINode *OwnerDocAsNode() const;
|
||||
|
||||
/**
|
||||
* Returns true if the content has an ancestor that is a document.
|
||||
*
|
||||
@ -761,6 +776,35 @@ public:
|
||||
return mParent && mParent->IsElement() ? mParent : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root of the subtree this node belongs to. This never returns
|
||||
* null. It may return 'this' (e.g. for document nodes, and nodes that
|
||||
* are the roots of disconnected subtrees).
|
||||
*/
|
||||
nsINode* SubtreeRoot() const
|
||||
{
|
||||
// There are three cases of interest here. nsINodes that are really:
|
||||
// 1. nsIDocument nodes - Are always in the document.
|
||||
// 2. nsIContent nodes - Are either in the document, or mSubtreeRoot
|
||||
// is updated in BindToTree/UnbindFromTree.
|
||||
// 3. nsIAttribute nodes - Are never in the document, and mSubtreeRoot
|
||||
// is always 'this' (as set in nsINode's ctor).
|
||||
nsINode* node = IsInDoc() ? OwnerDocAsNode() : mSubtreeRoot;
|
||||
NS_ASSERTION(node, "Should always have a node here!");
|
||||
#ifdef DEBUG
|
||||
{
|
||||
const nsINode* slowNode = this;
|
||||
const nsINode* iter = slowNode;
|
||||
while ((iter = iter->GetNodeParent())) {
|
||||
slowNode = iter;
|
||||
}
|
||||
|
||||
NS_ASSERTION(slowNode == node, "These should always be in sync!");
|
||||
}
|
||||
#endif
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
*/
|
||||
@ -1363,6 +1407,18 @@ protected:
|
||||
bool HasLockedStyleStates() const
|
||||
{ return GetBoolFlag(ElementHasLockedStyleStates); }
|
||||
|
||||
void SetSubtreeRootPointer(nsINode* aSubtreeRoot)
|
||||
{
|
||||
NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!");
|
||||
NS_ASSERTION(!(IsNodeOfType(eCONTENT) && IsInDoc()), "Shouldn't be here!");
|
||||
mSubtreeRoot = aSubtreeRoot;
|
||||
}
|
||||
|
||||
void ClearSubtreeRootPointer()
|
||||
{
|
||||
mSubtreeRoot = nsnull;
|
||||
}
|
||||
|
||||
public:
|
||||
// Optimized way to get classinfo.
|
||||
virtual nsXPCClassInfo* GetClassInfo() = 0;
|
||||
@ -1506,6 +1562,14 @@ protected:
|
||||
nsIContent* mPreviousSibling;
|
||||
nsIContent* mFirstChild;
|
||||
|
||||
union {
|
||||
// Pointer to our primary frame. Might be null.
|
||||
nsIFrame* mPrimaryFrame;
|
||||
|
||||
// Pointer to the root of our subtree. Might be null.
|
||||
nsINode* mSubtreeRoot;
|
||||
};
|
||||
|
||||
// Storage for more members that are usually not needed; allocated lazily.
|
||||
nsSlots* mSlots;
|
||||
};
|
||||
|
@ -524,6 +524,10 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
||||
// Set document
|
||||
if (aDocument) {
|
||||
// We no longer need to track the subtree pointer (and in fact we'll assert
|
||||
// if we do this any later).
|
||||
ClearSubtreeRootPointer();
|
||||
|
||||
// XXX See the comment in nsGenericElement::BindToTree
|
||||
SetInDocument();
|
||||
if (mText.IsBidi()) {
|
||||
@ -531,6 +535,9 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
}
|
||||
// Clear the lazy frame construction bits.
|
||||
UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
|
||||
} else {
|
||||
// If we're not in the doc, update our subtree pointer.
|
||||
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
||||
}
|
||||
|
||||
nsNodeUtils::ParentChainChanged(this);
|
||||
@ -570,6 +577,9 @@ nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
}
|
||||
ClearInDocument();
|
||||
|
||||
// Begin keeping track of our subtree root.
|
||||
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
|
||||
|
||||
nsDataSlots *slots = GetExistingDataSlots();
|
||||
if (slots) {
|
||||
slots->mBindingParent = nsnull;
|
||||
|
@ -219,6 +219,7 @@ nsINode::nsSlots::Unlink()
|
||||
nsINode::~nsINode()
|
||||
{
|
||||
NS_ASSERTION(!HasSlots(), "nsNodeUtils::LastRelease was not called?");
|
||||
NS_ASSERTION(mSubtreeRoot == this, "Didn't restore state properly?");
|
||||
}
|
||||
|
||||
void*
|
||||
@ -3164,6 +3165,10 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
// aDocument->BindingManager()->ChangeDocumentFor(this, nsnull,
|
||||
// aDocument);
|
||||
|
||||
// We no longer need to track the subtree pointer (and in fact we'll assert
|
||||
// if we do this any later).
|
||||
ClearSubtreeRootPointer();
|
||||
|
||||
// Being added to a document.
|
||||
SetInDocument();
|
||||
|
||||
@ -3173,6 +3178,9 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
|
||||
// And the restyle bits
|
||||
ELEMENT_ALL_RESTYLE_FLAGS);
|
||||
} else {
|
||||
// If we're not in the doc, update our subtree pointer.
|
||||
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
||||
}
|
||||
|
||||
// If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
|
||||
@ -3264,6 +3272,9 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
}
|
||||
ClearInDocument();
|
||||
|
||||
// Begin keeping track of our subtree root.
|
||||
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
|
||||
|
||||
if (document) {
|
||||
// Notify XBL- & nsIAnonymousContentCreator-generated
|
||||
// anonymous content that the document is changing.
|
||||
|
@ -184,7 +184,7 @@ nsTextNode::CloneDataNode(nsINodeInfo *aNodeInfo, bool aCloneText) const
|
||||
return it;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsTextNode::BindToAttribute(nsIAttribute* aAttr)
|
||||
{
|
||||
NS_ASSERTION(!IsInDoc(), "Unbind before binding!");
|
||||
@ -194,18 +194,17 @@ nsTextNode::BindToAttribute(nsIAttribute* aAttr)
|
||||
mParent = aAttr;
|
||||
SetParentIsContent(false);
|
||||
ClearInDocument();
|
||||
return NS_OK;
|
||||
SetSubtreeRootPointer(aAttr->SubtreeRoot());
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsTextNode::UnbindFromAttribute()
|
||||
{
|
||||
NS_ASSERTION(GetNodeParent(), "Bind before unbinding!");
|
||||
NS_ASSERTION(GetNodeParent() &&
|
||||
GetNodeParent()->IsNodeOfType(nsINode::eATTRIBUTE),
|
||||
NS_ASSERTION(GetNodeParent()->IsNodeOfType(nsINode::eATTRIBUTE),
|
||||
"Use this method only to unbind from an attribute!");
|
||||
mParent = nsnull;
|
||||
return NS_OK;
|
||||
SetSubtreeRootPointer(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -74,8 +74,8 @@ public:
|
||||
virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
|
||||
bool aCloneText) const;
|
||||
|
||||
nsresult BindToAttribute(nsIAttribute* aAttr);
|
||||
nsresult UnbindFromAttribute();
|
||||
void BindToAttribute(nsIAttribute* aAttr);
|
||||
void UnbindFromAttribute();
|
||||
|
||||
virtual nsXPCClassInfo* GetClassInfo();
|
||||
|
||||
|
@ -727,9 +727,12 @@ nsImageMap::FreeAreas()
|
||||
PRUint32 i, n = mAreas.Length();
|
||||
for (i = 0; i < n; i++) {
|
||||
Area* area = mAreas.ElementAt(i);
|
||||
NS_ASSERTION(area->mArea->GetPrimaryFrame() == mImageFrame,
|
||||
"Unexpected primary frame");
|
||||
area->mArea->SetPrimaryFrame(nsnull);
|
||||
if (area->mArea->IsInDoc()) {
|
||||
NS_ASSERTION(area->mArea->GetPrimaryFrame() == mImageFrame,
|
||||
"Unexpected primary frame");
|
||||
|
||||
area->mArea->SetPrimaryFrame(nsnull);
|
||||
}
|
||||
|
||||
area->mArea->RemoveSystemEventListener(NS_LITERAL_STRING("focus"), this,
|
||||
false);
|
||||
|
Loading…
Reference in New Issue
Block a user