mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 566416. Make attribute nodes set their mFirstChild correctly. r=sicking
This commit is contained in:
parent
aadbb25e72
commit
07c9425ef6
@ -73,6 +73,13 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
|
||||
|
||||
// We don't add a reference to our content. It will tell us
|
||||
// to drop our reference when it goes away.
|
||||
|
||||
EnsureChildState();
|
||||
|
||||
nsIContent* content = GetContentInternal();
|
||||
if (content) {
|
||||
content->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsDOMAttribute::~nsDOMAttribute()
|
||||
@ -80,6 +87,12 @@ nsDOMAttribute::~nsDOMAttribute()
|
||||
if (mChild) {
|
||||
static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
|
||||
NS_RELEASE(mChild);
|
||||
mFirstChild = nsnull;
|
||||
}
|
||||
|
||||
nsIContent* content = GetContentInternal();
|
||||
if (content) {
|
||||
content->RemoveMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +118,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttribute)
|
||||
if (tmp->mChild) {
|
||||
static_cast<nsTextNode*>(tmp->mChild)->UnbindFromAttribute();
|
||||
NS_RELEASE(tmp->mChild);
|
||||
tmp->mFirstChild = nsnull;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
|
||||
@ -115,8 +129,8 @@ DOMCI_DATA(Attr, nsDOMAttribute)
|
||||
// QueryInterface implementation for nsDOMAttribute
|
||||
NS_INTERFACE_TABLE_HEAD(nsDOMAttribute)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_NODE_INTERFACE_TABLE5(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsIDOMNode,
|
||||
nsIDOM3Attr, nsPIDOMEventTarget)
|
||||
NS_NODE_INTERFACE_TABLE6(nsDOMAttribute, nsIDOMAttr, nsIAttribute, nsIDOMNode,
|
||||
nsIDOM3Attr, nsPIDOMEventTarget, nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttribute)
|
||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
|
||||
new nsNodeSupportsWeakRefTearoff(this))
|
||||
@ -144,6 +158,11 @@ nsDOMAttribute::SetMap(nsDOMAttributeMap *aMap)
|
||||
// need to locally cache value. GetValue() does that.
|
||||
GetValue(mValue);
|
||||
}
|
||||
|
||||
nsIContent* content = GetContentInternal();
|
||||
if (content) {
|
||||
content->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
mAttrMap = aMap;
|
||||
}
|
||||
@ -306,11 +325,7 @@ nsDOMAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
|
||||
NS_IMETHODIMP
|
||||
nsDOMAttribute::HasChildNodes(PRBool* aHasChildNodes)
|
||||
{
|
||||
PRBool hasChild;
|
||||
nsresult rv = EnsureChildState(PR_FALSE, hasChild);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aHasChildNodes = hasChild;
|
||||
*aHasChildNodes = mFirstChild != nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -330,12 +345,8 @@ nsDOMAttribute::GetFirstChild(nsIDOMNode** aFirstChild)
|
||||
{
|
||||
*aFirstChild = nsnull;
|
||||
|
||||
PRBool hasChild;
|
||||
nsresult rv = EnsureChildState(PR_TRUE, hasChild);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mChild) {
|
||||
CallQueryInterface(mChild, aFirstChild);
|
||||
if (mFirstChild) {
|
||||
CallQueryInterface(mFirstChild, aFirstChild);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -584,38 +595,30 @@ nsDOMAttribute::IsNodeOfType(PRUint32 aFlags) const
|
||||
PRUint32
|
||||
nsDOMAttribute::GetChildCount() const
|
||||
{
|
||||
return GetChildCount(PR_FALSE);
|
||||
return mFirstChild ? 1 : 0;
|
||||
}
|
||||
|
||||
nsIContent *
|
||||
nsDOMAttribute::GetChildAt(PRUint32 aIndex) const
|
||||
{
|
||||
// Don't need to check result of EnsureChildState since mChild will be null.
|
||||
PRBool hasChild;
|
||||
EnsureChildState(PR_TRUE, hasChild);
|
||||
|
||||
return aIndex == 0 && hasChild ? mChild : nsnull;
|
||||
return aIndex == 0 ? mFirstChild : nsnull;
|
||||
}
|
||||
|
||||
nsIContent * const *
|
||||
nsDOMAttribute::GetChildArray(PRUint32* aChildCount) const
|
||||
{
|
||||
*aChildCount = GetChildCount(PR_TRUE);
|
||||
return &mChild;
|
||||
*aChildCount = GetChildCount();
|
||||
return &mFirstChild;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsDOMAttribute::IndexOf(nsINode* aPossibleChild) const
|
||||
{
|
||||
// No need to call EnsureChildState here. If we don't already have a child
|
||||
// then aPossibleChild can't possibly be our child.
|
||||
if (!aPossibleChild || aPossibleChild != mChild) {
|
||||
if (!aPossibleChild || aPossibleChild != mFirstChild) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PRBool hasChild;
|
||||
EnsureChildState(PR_FALSE, hasChild);
|
||||
return hasChild ? 0 : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -659,8 +662,6 @@ nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationE
|
||||
if (guard.Mutated(0) && mChild != child) {
|
||||
return NS_OK;
|
||||
}
|
||||
NS_RELEASE(mChild);
|
||||
static_cast<nsTextNode*>(child.get())->UnbindFromAttribute();
|
||||
|
||||
nsString nullString;
|
||||
SetDOMStringToNull(nullString);
|
||||
@ -724,34 +725,52 @@ nsDOMAttribute::GetSystemEventGroup(nsIDOMEventGroup** aGroup)
|
||||
return elm->GetSystemEventGroupLM(aGroup);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMAttribute::EnsureChildState(PRBool aSetText, PRBool &aHasChild) const
|
||||
void
|
||||
nsDOMAttribute::EnsureChildState()
|
||||
{
|
||||
aHasChild = PR_FALSE;
|
||||
|
||||
nsDOMAttribute* mutableThis = const_cast<nsDOMAttribute*>(this);
|
||||
NS_PRECONDITION(!mChild, "Someone screwed up");
|
||||
|
||||
nsAutoString value;
|
||||
mutableThis->GetValue(value);
|
||||
GetValue(value);
|
||||
|
||||
if (!mChild && !value.IsEmpty()) {
|
||||
nsresult rv = NS_NewTextNode(&mutableThis->mChild,
|
||||
mNodeInfo->NodeInfoManager());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!value.IsEmpty()) {
|
||||
NS_NewTextNode(&mChild, mNodeInfo->NodeInfoManager());
|
||||
|
||||
static_cast<nsTextNode*>(mChild)->BindToAttribute(mutableThis);
|
||||
}
|
||||
static_cast<nsTextNode*>(mChild)->BindToAttribute(this);
|
||||
mFirstChild = mChild;
|
||||
|
||||
aHasChild = !value.IsEmpty();
|
||||
|
||||
if (aSetText && aHasChild) {
|
||||
// aNotify should probably be PR_TRUE sometimes, but it's unlikely that
|
||||
// anyone cares. And we aren't updating the node when the attribute changes
|
||||
// anyway so any notifications are way late.
|
||||
mChild->SetText(value, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
void
|
||||
nsDOMAttribute::AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType)
|
||||
{
|
||||
nsIContent* content = GetContentInternal();
|
||||
if (aContent != content) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aNameSpaceID != mNodeInfo->NamespaceID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(content);
|
||||
if (nameAtom != aAttribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Just blow away our mChild and recreate it if needed
|
||||
if (mChild) {
|
||||
static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
|
||||
NS_RELEASE(mChild);
|
||||
mFirstChild = nsnull;
|
||||
}
|
||||
EnsureChildState();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -53,12 +53,14 @@
|
||||
#include "nsDOMAttributeMap.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
// Attribute helper class used to wrap up an attribute with a dom
|
||||
// object that implements nsIDOMAttr, nsIDOM3Attr, nsIDOMNode, nsIDOM3Node
|
||||
class nsDOMAttribute : public nsIAttribute,
|
||||
public nsIDOMAttr,
|
||||
public nsIDOM3Attr
|
||||
public nsIDOM3Attr,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
nsDOMAttribute(nsDOMAttributeMap* aAttrMap, nsINodeInfo *aNodeInfo,
|
||||
@ -118,6 +120,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDOMAttribute,
|
||||
nsIAttribute)
|
||||
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
|
||||
protected:
|
||||
virtual mozilla::dom::Element* GetNameSpaceElement()
|
||||
{
|
||||
@ -129,15 +133,7 @@ protected:
|
||||
private:
|
||||
already_AddRefed<nsIAtom> GetNameAtom(nsIContent* aContent);
|
||||
|
||||
nsresult EnsureChildState(PRBool aSetText, PRBool &aHasChild) const;
|
||||
|
||||
PRUint32 GetChildCount(PRBool aSetText) const
|
||||
{
|
||||
PRBool hasChild;
|
||||
EnsureChildState(aSetText, hasChild);
|
||||
|
||||
return hasChild ? 1 : 0;
|
||||
}
|
||||
void EnsureChildState();
|
||||
|
||||
nsString mValue;
|
||||
// XXX For now, there's only a single child - a text element
|
||||
|
Loading…
Reference in New Issue
Block a user