From 3ba29338bc745b6072b5f2bc8d2189a45a11ef76 Mon Sep 17 00:00:00 2001 From: "peter%propagandism.org" Date: Thu, 30 Oct 2003 13:47:29 +0000 Subject: [PATCH] Fix for bug 126765 (Change NormalizeAttrString to GetAttrWithName). Original fix by Daniel Bratell and sicking, r=sicking, sr=jst. git-svn-id: svn://10.0.0.236/trunk@148564 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsIContent.h | 21 ++-- .../content/base/src/nsDOMAttributeMap.cpp | 116 ++++++++++-------- .../content/base/src/nsGenericDOMDataNode.cpp | 16 +-- .../content/base/src/nsGenericDOMDataNode.h | 3 +- mozilla/content/base/src/nsGenericElement.cpp | 63 +++++----- mozilla/content/base/src/nsGenericElement.h | 4 +- mozilla/content/base/src/nsNodeInfo.cpp | 61 ++++++++- mozilla/content/base/src/nsNodeInfo.h | 23 ++++ .../content/base/src/nsNodeInfoManager.cpp | 7 +- .../html/content/src/nsAttributeContent.cpp | 14 +-- .../html/content/src/nsGenericHTMLElement.cpp | 110 +++++++++++++++-- .../html/content/src/nsGenericHTMLElement.h | 8 +- .../svg/content/src/nsSVGAttributes.cpp | 36 +++--- .../content/svg/content/src/nsSVGAttributes.h | 3 +- .../content/svg/content/src/nsSVGElement.cpp | 7 +- .../content/svg/content/src/nsSVGElement.h | 3 +- .../xul/content/src/nsXULAttributes.cpp | 10 +- .../content/xul/content/src/nsXULElement.cpp | 88 +++++-------- .../content/xul/content/src/nsXULElement.h | 2 +- .../xul/document/src/nsXULDocument.cpp | 18 ++- .../xul/templates/src/nsXULContentBuilder.cpp | 20 ++- 21 files changed, 392 insertions(+), 241 deletions(-) diff --git a/mozilla/content/base/public/nsIContent.h b/mozilla/content/base/public/nsIContent.h index 98f3cb67304..a2b89e09d75 100644 --- a/mozilla/content/base/public/nsIContent.h +++ b/mozilla/content/base/public/nsIContent.h @@ -39,6 +39,7 @@ #define nsIContent_h___ #include +#include "nsCOMPtr.h" #include "nsISupports.h" #include "nsEvent.h" #include "nsAString.h" @@ -217,17 +218,16 @@ public: NS_IMETHOD_(nsIAtom*) GetClassAttributeName() const = 0; /** - * Normalizes an attribute string into an atom that represents the - * qualified attribute name of the attribute. This method is intended - * for character case conversion if the content object is case - * insensitive (e.g. HTML). + * Normalizes an attribute name and returns it as a nodeinfo if an attribute + * with that name exists. This method is intended for character case + * conversion if the content object is case insensitive (e.g. HTML). Returns + * the nodeinfo of the attribute with the specified name if one exists or + * null otherwise. * * @param aStr the unparsed attribute string - * @param aName out parameter representing the complete name of the - * attribute + * @return the node info. May be nsnull. */ - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) = 0; + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr) = 0; /** * Set attribute values. All attribute values are assumed to have a @@ -524,8 +524,9 @@ public: * sink of your choice to do so. This is an efficiency measure. * * If you also need to determine whether the parser is the one creating your - * element (through createElement() or cloneNode() generally) * aFromParser to the NS_NewXXX() constructor for your element and have the - * parser pass true. See nsHTMLInputElement.cpp and + * element (through createElement() or cloneNode() generally) then add a + * boolean aFromParser to the NS_NewXXX() constructor for your element and + * have the parser pass true. See nsHTMLInputElement.cpp and * nsHTMLContentSink::MakeContentObject(). * * DO NOT USE THIS METHOD to get around the fact that it's hard to deal with diff --git a/mozilla/content/base/src/nsDOMAttributeMap.cpp b/mozilla/content/base/src/nsDOMAttributeMap.cpp index 7455b1f2acc..fbf01736e40 100644 --- a/mozilla/content/base/src/nsDOMAttributeMap.cpp +++ b/mozilla/content/base/src/nsDOMAttributeMap.cpp @@ -81,28 +81,31 @@ nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, NS_ENSURE_ARG_POINTER(aAttribute); *aAttribute = nsnull; - nsresult rv = NS_OK; if (mContent) { - nsCOMPtr ni; - mContent->NormalizeAttrString(aAttrName, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = + mContent->GetExistingAttrNameFromQName(aAttrName); + if (!ni) { + return NS_OK; + } PRInt32 nsid = ni->GetNamespaceID(); nsCOMPtr nameAtom = ni->GetNameAtom(); nsAutoString value; - nsresult attrResult = mContent->GetAttr(nsid, nameAtom, value); + // Eventually we shouldn't need to get the value here at all + nsresult rv = mContent->GetAttr(nsid, nameAtom, value); + NS_ASSERTION(rv != NS_CONTENT_ATTR_NOT_THERE, "unable to get attribute"); + NS_ENSURE_SUCCESS(rv, rv); - if (NS_CONTENT_ATTR_NOT_THERE != attrResult && NS_SUCCEEDED(attrResult)) { - nsDOMAttribute* domAttribute; - domAttribute = new nsDOMAttribute(mContent, ni, value); - NS_ENSURE_TRUE(domAttribute, NS_ERROR_OUT_OF_MEMORY); - - rv = CallQueryInterface(domAttribute, aAttribute); + nsDOMAttribute* domAttribute = new nsDOMAttribute(mContent, ni, value); + if (!domAttribute) { + return NS_ERROR_OUT_OF_MEMORY; } + + NS_ADDREF(*aAttribute = domAttribute); } - return rv; + return NS_OK; } NS_IMETHODIMP @@ -137,33 +140,44 @@ nsDOMAttributeMap::SetNamedItem(nsIDOMNode *aNode, nsIDOMNode **aReturn) } } + // get node-info and value of old attribute nsAutoString name, value; - attribute->GetName(name); - nsCOMPtr ni; - mContent->NormalizeAttrString(name, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = mContent->GetExistingAttrNameFromQName(name); + if (ni) { + nsCOMPtr nameAtom = ni->GetNameAtom(); + PRInt32 nsid = ni->GetNamespaceID(); - PRInt32 nsid = ni->GetNamespaceID(); - nsCOMPtr nameAtom = ni->GetNameAtom(); + rv = mContent->GetAttr(nsid, nameAtom, value); + NS_ASSERTION(rv != NS_CONTENT_ATTR_NOT_THERE, "unable to get attribute"); + NS_ENSURE_SUCCESS(rv, rv); - nsresult attrResult = mContent->GetAttr(nsid, nameAtom, value); - - if (NS_CONTENT_ATTR_NOT_THERE != attrResult && NS_SUCCEEDED(attrResult)) { - nsDOMAttribute* domAttribute; - // We pass a null content here since the attr node we return isn't - // tied to this content anymore. - domAttribute = new nsDOMAttribute(nsnull, ni, value); + // Create the attributenode to pass back. We pass a null content here + // since the attr node we return isn't tied to this content anymore. + nsDOMAttribute* domAttribute = new nsDOMAttribute(nsnull, ni, value); if (!domAttribute) { return NS_ERROR_OUT_OF_MEMORY; } - rv = CallQueryInterface(domAttribute, aReturn); + NS_ADDREF(*aReturn = domAttribute); + } + else { + nsCOMPtr contentNi = mContent->GetNodeInfo(); + NS_ENSURE_TRUE(contentNi, NS_ERROR_FAILURE); + + nsCOMPtr nimgr; + contentNi->GetNodeInfoManager(getter_AddRefs(nimgr)); + NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); + + rv = nimgr->GetNodeInfo(name, nsnull, kNameSpaceID_None, + getter_AddRefs(ni)); + NS_ENSURE_SUCCESS(rv, rv); + // value is already empty } + // Set the new attributevalue attribute->GetValue(value); - rv = mContent->SetAttr(ni, value, PR_TRUE); // Not all attributes implement nsIAttribute. @@ -186,31 +200,26 @@ nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, nsresult rv = NS_OK; if (mContent) { - nsCOMPtr ni; - mContent->NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = mContent->GetExistingAttrNameFromQName(aName); + if (!ni) { + return NS_ERROR_DOM_NOT_FOUND_ERR; + } PRInt32 nsid = ni->GetNamespaceID(); nsCOMPtr nameAtom = ni->GetNameAtom(); - nsCOMPtr attribute; - - nsresult attrResult; nsAutoString value; - attrResult = mContent->GetAttr(nsid, nameAtom, value); + rv = mContent->GetAttr(nsid, nameAtom, value); + NS_ASSERTION(rv != NS_CONTENT_ATTR_NOT_THERE, "unable to get attribute"); + NS_ENSURE_SUCCESS(rv, rv); - if (NS_CONTENT_ATTR_NOT_THERE != attrResult && NS_SUCCEEDED(attrResult)) { - nsDOMAttribute* domAttribute; - domAttribute = new nsDOMAttribute(nsnull, ni, value); - if (!domAttribute) { - return NS_ERROR_OUT_OF_MEMORY; - } - - rv = CallQueryInterface(domAttribute, aReturn); - } else { - return NS_ERROR_DOM_NOT_FOUND_ERR; + nsDOMAttribute* domAttribute = new nsDOMAttribute(nsnull, ni, value); + if (!domAttribute) { + return NS_ERROR_OUT_OF_MEMORY; } + NS_ADDREF(*aReturn = domAttribute); + rv = mContent->UnsetAttr(nsid, nameAtom, PR_TRUE); } @@ -309,11 +318,12 @@ nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI, nimgr->GetNodeInfo(nameAtom, prefix, nameSpaceID, getter_AddRefs(ni)); NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); - nsDOMAttribute* domAttribute; - domAttribute = new nsDOMAttribute(mContent, ni, value); - NS_ENSURE_TRUE(domAttribute, NS_ERROR_OUT_OF_MEMORY); + nsDOMAttribute* domAttribute = new nsDOMAttribute(mContent, ni, value); + if (!domAttribute) { + return NS_ERROR_OUT_OF_MEMORY; + } - rv = CallQueryInterface(domAttribute, aReturn); + NS_ADDREF(*aReturn = domAttribute); } } @@ -369,15 +379,14 @@ nsDOMAttributeMap::SetNamedItemNS(nsIDOMNode* aArg, nsIDOMNode** aReturn) nsresult attrResult = mContent->GetAttr(nameSpaceID, nameAtom, value); if (NS_CONTENT_ATTR_NOT_THERE != attrResult && NS_SUCCEEDED(attrResult)) { - nsDOMAttribute* domAttribute; // We pass a null content here since the attr node we return isn't // tied to this content anymore. - domAttribute = new nsDOMAttribute(nsnull, ni, value); + nsDOMAttribute* domAttribute = new nsDOMAttribute(nsnull, ni, value); if (!domAttribute) { return NS_ERROR_OUT_OF_MEMORY; } - rv = CallQueryInterface(domAttribute, aReturn); + NS_ADDREF(*aReturn = domAttribute); } attribute->GetValue(value); @@ -434,13 +443,12 @@ nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, nimgr->GetNodeInfo(nameAtom, prefix, nameSpaceID, getter_AddRefs(ni)); NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); - nsDOMAttribute* domAttribute; - domAttribute = new nsDOMAttribute(nsnull, ni, value); + nsDOMAttribute* domAttribute = new nsDOMAttribute(nsnull, ni, value); if (!domAttribute) { return NS_ERROR_OUT_OF_MEMORY; } - rv = CallQueryInterface(domAttribute, aReturn); + NS_ADDREF(*aReturn = domAttribute); } else { return NS_ERROR_DOM_NOT_FOUND_ERR; } diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 9cae2b5871f..38035a99706 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -694,12 +694,10 @@ nsGenericDOMDataNode::GetClassAttributeName() const return nsnull; } -NS_IMETHODIMP -nsGenericDOMDataNode::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +NS_IMETHODIMP_(already_AddRefed) +nsGenericDOMDataNode::GetExistingAttrNameFromQName(const nsAString& aStr) { - *aNodeInfo = nsnull; - return NS_OK; + return nsnull; } NS_IMETHODIMP @@ -1345,12 +1343,8 @@ nsGenericDOMDataNode::AppendTextTo(nsAString& aResult) if (mText.Is2b()) { aResult.Append(mText.Get2b(), mText.GetLength()); } else { - - // XXX we would like to have a AppendASCIItoUCS2 here - - aResult.Append(NS_ConvertASCIItoUCS2(mText.Get1b(), - mText.GetLength()).get(), - mText.GetLength()); + // XXX we would like to have a AppendASCIItoUTF16 here + AppendUTF8toUTF16(mText.Get1b(), aResult); } return NS_OK; diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index b6cb71bf813..ddefde072b9 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -179,8 +179,7 @@ public: NS_IMETHOD GetNameSpaceID(PRInt32* aID) const; NS_IMETHOD_(nsIAtom*) GetIDAttributeName() const; NS_IMETHOD_(nsIAtom*) GetClassAttributeName() const; - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, const nsAString& aValue, PRBool aNotify); NS_IMETHOD SetAttr(nsINodeInfo *aNodeInfo, diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 2c4c1ec370b..dd43f4f48e4 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -1250,7 +1250,7 @@ nsGenericElement::HasAttributes(PRBool* aReturn) NS_IMETHODIMP nsGenericElement::GetAttributes(nsIDOMNamedNodeMap** aAttributes) { - NS_PRECONDITION(aAttributes, "null pointer argument"); + NS_ENSURE_ARG_POINTER(aAttributes); nsDOMSlots *slots = GetDOMSlots(); if (!slots->mAttributeMap) { @@ -1275,18 +1275,17 @@ nsresult nsGenericElement::GetAttribute(const nsAString& aName, nsAString& aReturn) { - nsCOMPtr ni; - NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (!ni) { + SetDOMStringToNull(aReturn); + + return NS_OK; + } PRInt32 nsid = ni->GetNamespaceID(); nsCOMPtr nameAtom = ni->GetNameAtom(); - nsresult rv = GetAttr(nsid, nameAtom, aReturn); - - if (rv == NS_CONTENT_ATTR_NOT_THERE) { - SetDOMStringToNull(aReturn); - } + GetAttr(nsid, nameAtom, aReturn); return NS_OK; } @@ -1295,8 +1294,16 @@ nsresult nsGenericElement::SetAttribute(const nsAString& aName, const nsAString& aValue) { - nsCOMPtr ni; - NormalizeAttrString(aName, getter_AddRefs(ni)); + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (!ni) { + nsCOMPtr nimgr; + mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr)); + NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); + + nsresult rv = nimgr->GetNodeInfo(aName, nsnull, kNameSpaceID_None, + getter_AddRefs(ni)); + NS_ENSURE_SUCCESS(rv, rv); + } return SetAttr(ni, aValue, PR_TRUE); } @@ -1304,9 +1311,10 @@ nsGenericElement::SetAttribute(const nsAString& aName, nsresult nsGenericElement::RemoveAttribute(const nsAString& aName) { - nsCOMPtr ni; - NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (!ni) { + return NS_OK; + } PRInt32 nsid = ni->GetNamespaceID(); nsCOMPtr tag = ni->GetNameAtom(); @@ -1547,14 +1555,9 @@ nsGenericElement::HasAttribute(const nsAString& aName, PRBool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); - nsCOMPtr ni; - NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE); + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + *aReturn = (ni != nsnull); - PRInt32 nsid = ni->GetNamespaceID(); - nsCOMPtr nameAtom = ni->GetNameAtom(); - - *aReturn = HasAttr(nsid, nameAtom); return NS_OK; } @@ -3175,9 +3178,8 @@ nsGenericContainerElement::~nsGenericContainerElement() } } -nsresult -nsGenericContainerElement::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +NS_IMETHODIMP_(already_AddRefed) +nsGenericContainerElement::GetExistingAttrNameFromQName(const nsAString& aStr) { if (mAttributes) { NS_ConvertUCS2toUTF8 utf8String(aStr); @@ -3187,19 +3189,16 @@ nsGenericContainerElement::NormalizeAttrString(const nsAString& aStr, nsGenericAttribute* attr = (nsGenericAttribute*)mAttributes->ElementAt(indx); - if (attr->mNodeInfo->QualifiedNameEquals(utf8String)) { - NS_ADDREF(*aNodeInfo = attr->mNodeInfo); + nsINodeInfo *ni = attr->mNodeInfo; + if (ni->QualifiedNameEquals(utf8String)) { + NS_ADDREF(ni); - return NS_OK; + return ni; } } } - nsCOMPtr nimgr; - mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr)); - NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); - - return nimgr->GetNodeInfo(aStr, nsnull, kNameSpaceID_None, aNodeInfo); + return nsnull; } nsresult diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index 5cdda2df9a2..987f4c2b9d3 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -71,7 +71,6 @@ class nsDOMCSSDeclaration; class nsIDOMCSSStyleDeclaration; class nsDOMAttributeMap; class nsIURI; -class nsINodeInfo; typedef unsigned long PtrBits; @@ -754,8 +753,7 @@ public: } // Remainder of nsIContent - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, const nsAString& aValue, PRBool aNotify); diff --git a/mozilla/content/base/src/nsNodeInfo.cpp b/mozilla/content/base/src/nsNodeInfo.cpp index d50ef228951..a6835b5f2a7 100644 --- a/mozilla/content/base/src/nsNodeInfo.cpp +++ b/mozilla/content/base/src/nsNodeInfo.cpp @@ -47,6 +47,22 @@ #include "nsContentUtils.h" #include "nsReadableUtils.h" +// static +nsNodeInfo* +nsNodeInfo::Create() +{ + if (sCachedNodeInfo) { + // We have cached unused instances of this class, return a cached + // instance instead of always creating a new one. + nsNodeInfo *nodeInfo = sCachedNodeInfo; + sCachedNodeInfo = nsnull; + return nodeInfo; + } + + // Create a new one + return new nsNodeInfo(); +} + nsNodeInfo::nsNodeInfo() : nsINodeInfo(), mOwnerManager(nsnull) { @@ -54,6 +70,12 @@ nsNodeInfo::nsNodeInfo() nsNodeInfo::~nsNodeInfo() +{ + Clear(); +} + +void +nsNodeInfo::Clear() { if (mOwnerManager) { mOwnerManager->RemoveNodeInfo(this); @@ -91,8 +113,9 @@ nsNodeInfo::Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID, // nsISupports -NS_IMPL_ISUPPORTS1(nsNodeInfo, nsINodeInfo) - +NS_IMPL_ADDREF(nsNodeInfo) +NS_IMPL_RELEASE_WITH_DESTROY(nsNodeInfo, LastRelease()) +NS_IMPL_QUERY_INTERFACE1(nsNodeInfo, nsINodeInfo) // nsINodeInfo @@ -296,3 +319,37 @@ nsNodeInfo::GetDocumentPrincipal(nsIPrincipal** aPrincipal) const { return mOwnerManager->GetDocumentPrincipal(aPrincipal); } + +// static +nsNodeInfo *nsNodeInfo::sCachedNodeInfo = nsnull; + +// static +void +nsNodeInfo::ClearCache() +{ + // Clear our cache. + delete sCachedNodeInfo; + sCachedNodeInfo = nsnull; +} + +void +nsNodeInfo::LastRelease() +{ + if (sCachedNodeInfo) { + // No room in cache + delete this; + return; + } + + // There's space in the cache for one instance. Put + // this instance in the cache instead of deleting it. + sCachedNodeInfo = this; + + // Clear object so that we have no references to anything external + Clear(); + + // The refcount balancing and destructor re-entrancy protection + // code in Release() sets mRefCnt to 1 so we have to set it to 0 + // here to prevent leaks + mRefCnt = 0; +} diff --git a/mozilla/content/base/src/nsNodeInfo.h b/mozilla/content/base/src/nsNodeInfo.h index d58525c0fe9..90d49c6daa5 100644 --- a/mozilla/content/base/src/nsNodeInfo.h +++ b/mozilla/content/base/src/nsNodeInfo.h @@ -75,9 +75,15 @@ public: NS_IMETHOD GetDocumentPrincipal(nsIPrincipal** aPrincipal) const; // nsNodeInfo + // Create objects with Create +public: + static nsNodeInfo *Create(); +private: nsNodeInfo(); +protected: virtual ~nsNodeInfo(); +public: /* * Note! Init() must be called exactly once on every nsNodeInfo before * the object is used, if Init() returns an error code the nsNodeInfo @@ -88,10 +94,27 @@ public: nsresult Init(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID, nsNodeInfoManager *aOwnerManager); + /** + * Call before shutdown to clear the cache and free memory for this class. + */ + static void ClearCache(); + protected: nsCOMPtr mIDAttributeAtom; nsNodeInfoManager* mOwnerManager; // Strong reference! + +private: + void Clear(); + + static nsNodeInfo *sCachedNodeInfo; + + /** + * This method gets called by Release() when it's time to delete + * this object, instead of always deleting the object we'll put the + * object in the cache unless the cache is already full. + */ + void LastRelease(); }; #endif /* nsNodeInfo_h___ */ diff --git a/mozilla/content/base/src/nsNodeInfoManager.cpp b/mozilla/content/base/src/nsNodeInfoManager.cpp index 9d32c54e117..6639bb2ef05 100644 --- a/mozilla/content/base/src/nsNodeInfoManager.cpp +++ b/mozilla/content/base/src/nsNodeInfoManager.cpp @@ -138,6 +138,11 @@ nsNodeInfoManager::~nsNodeInfoManager() if (mNodeInfoHash) PL_HashTableDestroy(mNodeInfoHash); + + if (gNodeManagerCount == 0) { + nsNodeInfo::ClearCache(); + } + #ifdef DEBUG_jst printf ("Removing NodeInfoManager, gcount = %d\n", gNodeManagerCount); #endif @@ -201,7 +206,7 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, return NS_OK; } - nsNodeInfo *newNodeInfo = new nsNodeInfo(); + nsNodeInfo *newNodeInfo = nsNodeInfo::Create(); NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(newNodeInfo); diff --git a/mozilla/content/html/content/src/nsAttributeContent.cpp b/mozilla/content/html/content/src/nsAttributeContent.cpp index ebe7097144e..5c4d9cacd1f 100644 --- a/mozilla/content/html/content/src/nsAttributeContent.cpp +++ b/mozilla/content/html/content/src/nsAttributeContent.cpp @@ -117,11 +117,9 @@ public: return nsnull; } - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr) { - *aNodeInfo = nsnull; - return NS_OK; + return nsnull; } NS_IMETHOD SetFocus(nsIPresContext* aPresContext) { return NS_OK; } @@ -450,7 +448,7 @@ nsAttributeContent::CopyText(nsAString& aResult) } else { const char *data = mText.Get1b(); - CopyASCIItoUCS2(Substring(data, data + mText.GetLength()), aResult); + CopyASCIItoUTF16(Substring(data, data + mText.GetLength()), aResult); } return NS_OK; } @@ -575,10 +573,8 @@ nsAttributeContent::AppendTextTo(nsAString& aResult) aResult.Append(mText.Get2b(), mText.GetLength()); } else { - // XXX we would like to have a AppendASCIItoUCS2 here - aResult.Append(NS_ConvertASCIItoUCS2(mText.Get1b(), - mText.GetLength()).get(), - mText.GetLength()); + // XXX we would like to have a AppendASCIItoUTF16 here + AppendUTF8toUTF16(mText.Get1b(), aResult); } return NS_OK; diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index ffaf03d00b6..111216deb5b 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -378,6 +378,28 @@ nsGenericHTMLElement::GetTagName(nsAString& aTagName) return GetNodeName(aTagName); } +NS_IMETHODIMP +nsGenericHTMLElement::SetAttribute(const nsAString& aName, + const nsAString& aValue) +{ + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (ni) { + return SetAttr(ni, aValue, PR_TRUE); + } + + nsCOMPtr nameAtom; + if (mNodeInfo->NamespaceEquals(kNameSpaceID_None)) { + nsAutoString lower(aName); + ToLowerCase(lower); + nameAtom = do_GetAtom(lower); + } + else { + nameAtom = do_GetAtom(aName); + } + + return SetAttr(kNameSpaceID_None, nameAtom, aValue, PR_TRUE); +} + nsresult nsGenericHTMLElement::GetNodeName(nsAString& aNodeName) { @@ -1610,19 +1632,87 @@ nsGenericHTMLElement::GetNameSpaceID(PRInt32* aID) const return NS_OK; } -nsresult -nsGenericHTMLElement::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +// Based on nsNodeInfo::QualifiedNameEquals +static PRBool +QualifiedNameEquals(const nsACString& aQualifiedName, nsIAtom* aName, + nsIAtom* aPrefix) { - // XXX need to validate/strip namespace prefix - nsAutoString lower(aStr); - ToLowerCase(lower); + if (!aPrefix) { + return aName->EqualsUTF8(aQualifiedName); + } - nsCOMPtr nimgr; - mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr)); - NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); + nsACString::const_iterator start; + aQualifiedName.BeginReading(start); - return nimgr->GetNodeInfo(lower, nsnull, kNameSpaceID_None, aNodeInfo); + nsACString::const_iterator colon(start); + + const char* prefix; + aPrefix->GetUTF8String(&prefix); + + PRUint32 len = strlen(prefix); + + if (len >= aQualifiedName.Length()) { + return PR_FALSE; + } + + colon.advance(len); + + // If the character at the prefix length index is not a colon, + // aQualifiedName is not equal to this string. + if (*colon != ':') { + return PR_FALSE; + } + + // Compare the prefix to the string from the start to the colon + if (!aPrefix->EqualsUTF8(Substring(start, colon))) { + return PR_FALSE; + } + + ++colon; // Skip the ':' + + nsACString::const_iterator end; + aQualifiedName.EndReading(end); + + // Compare the local name to the string between the colon and the + // end of aQualifiedName + return aName->EqualsUTF8(Substring(colon, end)); +} + +already_AddRefed +nsGenericHTMLElement::GetExistingAttrNameFromQName(const nsAString& aStr) +{ + if (!mAttributes) { + return nsnull; + } + + NS_ConvertUCS2toUTF8 lower(aStr); + if (mNodeInfo->NamespaceEquals(kNameSpaceID_None)) { + ToLowerCase(lower); + } + + nsCOMPtr nameAtom, prefixAtom; + PRInt32 nameSpace; + + PRInt32 indx, count; + mAttributes->GetAttributeCount(count); + for (indx = 0; indx < count; ++indx) { + mAttributes->GetAttributeNameAt(indx, &nameSpace, + getter_AddRefs(nameAtom), + getter_AddRefs(prefixAtom)); + + if (QualifiedNameEquals(lower, nameAtom, prefixAtom)) { + nsCOMPtr nimgr; + mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr)); + NS_ENSURE_TRUE(nimgr, nsnull); + + nsINodeInfo* nodeInfo; + nimgr->GetNodeInfo(nameAtom, prefixAtom, nameSpace, &nodeInfo); + + return nodeInfo; + } + } + + return nsnull; } nsresult diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.h b/mozilla/content/html/content/src/nsGenericHTMLElement.h index d16fe50ed97..62269acf528 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.h @@ -117,10 +117,7 @@ public: return nsGenericElement::GetAttribute(aName, aReturn); } NS_METHOD SetAttribute(const nsAString& aName, - const nsAString& aValue) - { - return nsGenericElement::SetAttribute(aName, aValue); - } + const nsAString& aValue); NS_METHOD GetTagName(nsAString& aTagName); NS_METHOD GetElementsByTagName(const nsAString& aTagname, nsIDOMNodeList** aReturn); @@ -177,8 +174,7 @@ public: NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers); NS_IMETHOD GetNameSpaceID(PRInt32* aID) const; - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, const nsAString& aValue, PRBool aNotify); diff --git a/mozilla/content/svg/content/src/nsSVGAttributes.cpp b/mozilla/content/svg/content/src/nsSVGAttributes.cpp index b1ff658aba9..ca85a10b9bb 100644 --- a/mozilla/content/svg/content/src/nsSVGAttributes.cpp +++ b/mozilla/content/svg/content/src/nsSVGAttributes.cpp @@ -772,30 +772,22 @@ nsSVGAttributes::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const return PR_FALSE; } -NS_IMETHODIMP -nsSVGAttributes::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +NS_IMETHODIMP_(already_AddRefed) +nsSVGAttributes::GetExistingAttrNameFromQName(const nsAString& aStr) { PRInt32 indx, count = Count(); NS_ConvertUCS2toUTF8 utf8String(aStr); for (indx = 0; indx < count; indx++) { nsSVGAttribute* attr = ElementAt(indx); - if (attr->GetNodeInfo()->QualifiedNameEquals(utf8String)) { - *aNodeInfo = attr->GetNodeInfo(); - NS_ADDREF(*aNodeInfo); - - return NS_OK; + nsINodeInfo* ni = attr->GetNodeInfo(); + if (ni->QualifiedNameEquals(utf8String)) { + NS_ADDREF(ni); + + return ni; } } - NS_ASSERTION(mContent,"no owner content"); - if (!mContent) return NS_ERROR_FAILURE; - - nsCOMPtr nimgr; - mContent->GetNodeInfo()->GetNodeInfoManager(getter_AddRefs(nimgr)); - NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); - - return nimgr->GetNodeInfo(aStr, nsnull, kNameSpaceID_None, aNodeInfo); + return nsnull; } NS_IMETHODIMP @@ -900,14 +892,14 @@ nsSVGAttributes::GetNamedItem(const nsAString& aName, if (! aReturn) return NS_ERROR_NULL_POINTER; - nsresult rv; *aReturn = nsnull; - nsCOMPtr inpNodeInfo; - - if (NS_FAILED(rv = mContent->NormalizeAttrString(aName, getter_AddRefs(inpNodeInfo)))) - return rv; - + nsCOMPtr inpNodeInfo = + mContent->GetExistingAttrNameFromQName(aName); + if (!inpNodeInfo) { + return NS_OK; + } + for (PRInt32 i = mAttributes.Count() - 1; i >= 0; --i) { nsSVGAttribute* attr = (nsSVGAttribute*) mAttributes[i]; nsINodeInfo *ni = attr->GetNodeInfo(); diff --git a/mozilla/content/svg/content/src/nsSVGAttributes.h b/mozilla/content/svg/content/src/nsSVGAttributes.h index 070129663ac..e3834dc08ac 100644 --- a/mozilla/content/svg/content/src/nsSVGAttributes.h +++ b/mozilla/content/svg/content/src/nsSVGAttributes.h @@ -172,8 +172,7 @@ public: PRBool aNotify); NS_IMETHOD_(PRBool) HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const; - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD GetAttrNameAt(PRInt32 aIndex, PRInt32* aNameSpaceID, nsIAtom** aName, diff --git a/mozilla/content/svg/content/src/nsSVGElement.cpp b/mozilla/content/svg/content/src/nsSVGElement.cpp index 5b66b575396..f821930cf35 100644 --- a/mozilla/content/svg/content/src/nsSVGElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGElement.cpp @@ -305,11 +305,10 @@ nsSVGElement::GetIDAttributeName() const return nsSVGAtoms::id; } -NS_IMETHODIMP -nsSVGElement::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +NS_IMETHODIMP_(already_AddRefed) +nsSVGElement::GetExistingAttrNameFromQName(const nsAString& aStr) { - return mAttributes->NormalizeAttrString(aStr, aNodeInfo); + return mAttributes->GetExistingAttrNameFromQName(aStr); } NS_IMETHODIMP diff --git a/mozilla/content/svg/content/src/nsSVGElement.h b/mozilla/content/svg/content/src/nsSVGElement.h index 0ceb2a042c1..024d8cdc9eb 100644 --- a/mozilla/content/svg/content/src/nsSVGElement.h +++ b/mozilla/content/svg/content/src/nsSVGElement.h @@ -85,8 +85,7 @@ public: PRBool aDeepSetDocument); NS_IMETHOD RemoveChildAt(PRUint32 aIndex, PRBool aNotify); NS_IMETHOD_(nsIAtom *) GetIDAttributeName() const; - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, const nsAString& aValue, PRBool aNotify); diff --git a/mozilla/content/xul/content/src/nsXULAttributes.cpp b/mozilla/content/xul/content/src/nsXULAttributes.cpp index 52ee578a84d..1f153de592b 100644 --- a/mozilla/content/xul/content/src/nsXULAttributes.cpp +++ b/mozilla/content/xul/content/src/nsXULAttributes.cpp @@ -597,16 +597,16 @@ nsXULAttributes::GetNamedItem(const nsAString& aName, if (! aReturn) return NS_ERROR_NULL_POINTER; - nsresult rv; *aReturn = nsnull; // XXX nameSpaceID only used in dead code (that was giving us a warning). // XXX I'd remove it completely, but maybe it is a useful reminder??? // PRInt32 nameSpaceID; - nsCOMPtr inpNodeInfo; - - if (NS_FAILED(rv = mContent->NormalizeAttrString(aName, getter_AddRefs(inpNodeInfo)))) - return rv; + nsCOMPtr inpNodeInfo = + mContent->GetExistingAttrNameFromQName(aName); + if (!inpNodeInfo) { + return NS_OK; + } // if (kNameSpaceID_Unknown == nameSpaceID) { // nameSpaceID = kNameSpaceID_None; // ignore unknown prefix XXX is this correct? diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index 484942efe31..dd05e7da4d4 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -1199,18 +1199,18 @@ NS_IMETHODIMP nsXULElement::GetAttribute(const nsAString& aName, nsAString& aReturn) { - nsCOMPtr nodeInfo; - nsresult rv = NormalizeAttrString(aName, - getter_AddRefs(nodeInfo)); - if (NS_FAILED(rv)) { - NS_WARNING("unable to normalize attribute name"); - return rv; + nsCOMPtr nodeInfo = GetExistingAttrNameFromQName(aName); + if (!nodeInfo) { + aReturn.Truncate(); + + return NS_OK; } nsCOMPtr nameAtom = nodeInfo->GetNameAtom(); PRInt32 nameSpaceID = nodeInfo->GetNamespaceID(); GetAttr(nameSpaceID, nameAtom, aReturn); + return NS_OK; } @@ -1219,39 +1219,33 @@ NS_IMETHODIMP nsXULElement::SetAttribute(const nsAString& aName, const nsAString& aValue) { - nsresult rv; + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (!ni) { + nsCOMPtr nimgr; + NodeInfo()->GetNodeInfoManager(getter_AddRefs(nimgr)); + NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); - nsCOMPtr ni; - - rv = NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to normalize attribute name"); - - if (NS_SUCCEEDED(rv)) { - rv = SetAttr(ni, aValue, PR_TRUE); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set attribute"); + nsresult rv = nimgr->GetNodeInfo(aName, nsnull, kNameSpaceID_None, + getter_AddRefs(ni)); + NS_ENSURE_SUCCESS(rv, rv); } - return NS_OK; + return SetAttr(ni, aValue, PR_TRUE); } NS_IMETHODIMP nsXULElement::RemoveAttribute(const nsAString& aName) { - nsCOMPtr ni; - - nsresult rv = NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse attribute name"); - - if (NS_SUCCEEDED(rv)) { - nsCOMPtr tag = ni->GetNameAtom(); - PRInt32 nameSpaceID = ni->GetNamespaceID(); - - rv = UnsetAttr(nameSpaceID, tag, PR_TRUE); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to remove attribute"); + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + if (!ni) { + return NS_OK; } - return NS_OK; + nsCOMPtr tag = ni->GetNameAtom(); + PRInt32 nameSpaceID = ni->GetNamespaceID(); + + return UnsetAttr(nameSpaceID, tag, PR_TRUE); } @@ -1452,15 +1446,9 @@ nsXULElement::HasAttribute(const nsAString& aName, PRBool* aReturn) { NS_ENSURE_ARG_POINTER(aReturn); - nsCOMPtr ni; + nsCOMPtr ni = GetExistingAttrNameFromQName(aName); + *aReturn = (ni != nsnull); - nsresult rv = NormalizeAttrString(aName, getter_AddRefs(ni)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr name = ni->GetNameAtom(); - PRInt32 nsid = ni->GetNamespaceID(); - - *aReturn = HasAttr(nsid, name); return NS_OK; } @@ -2222,43 +2210,35 @@ nsXULElement::GetTag(nsIAtom** aResult) const return NS_OK; } -NS_IMETHODIMP -nsXULElement::NormalizeAttrString(const nsAString& aStr, - nsINodeInfo** aNodeInfo) +NS_IMETHODIMP_(already_AddRefed) +nsXULElement::GetExistingAttrNameFromQName(const nsAString& aStr) { - PRInt32 i, count = Attributes() ? Attributes()->Count() : 0; NS_ConvertUCS2toUTF8 utf8String(aStr); - - for (i = 0; i < count; i++) { + + PRInt32 i, count = Attributes() ? Attributes()->Count() : 0; + for (i = 0; i < count; ++i) { nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, Attributes()->ElementAt(i)); nsINodeInfo *ni = attr->GetNodeInfo(); if (ni->QualifiedNameEquals(utf8String)) { - *aNodeInfo = ni; - NS_ADDREF(*aNodeInfo); + NS_ADDREF(ni); - return NS_OK; + return ni; } } count = mPrototype ? mPrototype->mNumAttributes : 0; for (i = 0; i < count; i++) { nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]); - nsINodeInfo *ni = attr->mNodeInfo; if (ni->QualifiedNameEquals(utf8String)) { - *aNodeInfo = ni; - NS_ADDREF(*aNodeInfo); + NS_ADDREF(ni); - return NS_OK; + return ni; } } - nsCOMPtr nimgr; - NodeInfo()->GetNodeInfoManager(getter_AddRefs(nimgr)); - NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE); - - return nimgr->GetNodeInfo(aStr, nsnull, kNameSpaceID_None, aNodeInfo); + return nsnull; } void diff --git a/mozilla/content/xul/content/src/nsXULElement.h b/mozilla/content/xul/content/src/nsXULElement.h index c4c66a19bb0..32e1f40ab0b 100644 --- a/mozilla/content/xul/content/src/nsXULElement.h +++ b/mozilla/content/xul/content/src/nsXULElement.h @@ -438,7 +438,7 @@ public: NS_IMETHOD_(nsINodeInfo *) GetNodeInfo() const; NS_IMETHOD_(nsIAtom *) GetIDAttributeName() const; NS_IMETHOD_(nsIAtom *) GetClassAttributeName() const; - NS_IMETHOD NormalizeAttrString(const nsAString& aStr, nsINodeInfo** aNodeInfo); + NS_IMETHOD_(already_AddRefed) GetExistingAttrNameFromQName(const nsAString& aStr); NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, const nsAString& aValue, PRBool aNotify); NS_IMETHOD SetAttr(nsINodeInfo *aNodeInfo, const nsAString& aValue, PRBool aNotify); NS_IMETHOD GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsAString& aResult) const; diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index 1a20c217fb3..d407130c5ff 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -1527,12 +1527,20 @@ nsXULDocument::Persist(const nsAString& aID, if (! element) return NS_ERROR_UNEXPECTED; - nsCOMPtr ni; - rv = element->NormalizeAttrString(aAttr, getter_AddRefs(ni)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr tag; + PRInt32 nameSpaceID; - nsCOMPtr tag = ni->GetNameAtom(); - PRInt32 nameSpaceID = ni->GetNamespaceID(); + nsCOMPtr ni = element->GetExistingAttrNameFromQName(aAttr); + if (ni) { + tag = ni->GetNameAtom(); + nameSpaceID = ni->GetNamespaceID(); + } + else { + tag = do_GetAtom(aAttr); + NS_ENSURE_TRUE(tag, NS_ERROR_OUT_OF_MEMORY); + + nameSpaceID = kNameSpaceID_None; + } rv = Persist(element, nameSpaceID, tag); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp index a87d3d4bf00..083ff895b58 100644 --- a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp @@ -865,13 +865,21 @@ nsXULContentBuilder::AddPersistentAttributes(nsIContent* aTemplateNode, if (attribute.IsEmpty()) break; - nsCOMPtr ni; - rv = aTemplateNode->NormalizeAttrString(attribute, - getter_AddRefs(ni)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr tag; + PRInt32 nameSpaceID; - nsCOMPtr tag = ni->GetNameAtom(); - PRInt32 nameSpaceID = ni->GetNamespaceID(); + nsCOMPtr ni = + aTemplateNode->GetExistingAttrNameFromQName(attribute); + if (ni) { + tag = ni->GetNameAtom(); + nameSpaceID = ni->GetNamespaceID(); + } + else { + tag = do_GetAtom(attribute); + NS_ENSURE_TRUE(tag, NS_ERROR_OUT_OF_MEMORY); + + nameSpaceID = kNameSpaceID_None; + } nsCOMPtr property; rv = nsXULContentUtils::GetResource(nameSpaceID, tag, getter_AddRefs(property));