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
This commit is contained in:
peter%propagandism.org 2003-10-30 13:47:29 +00:00
parent caf1987140
commit 3ba29338bc
21 changed files with 392 additions and 241 deletions

View File

@ -39,6 +39,7 @@
#define nsIContent_h___
#include <stdio.h>
#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<nsINodeInfo>) 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

View File

@ -81,28 +81,31 @@ nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName,
NS_ENSURE_ARG_POINTER(aAttribute);
*aAttribute = nsnull;
nsresult rv = NS_OK;
if (mContent) {
nsCOMPtr<nsINodeInfo> ni;
mContent->NormalizeAttrString(aAttrName, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni =
mContent->GetExistingAttrNameFromQName(aAttrName);
if (!ni) {
return NS_OK;
}
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> 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<nsINodeInfo> ni;
mContent->NormalizeAttrString(name, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(name);
if (ni) {
nsCOMPtr<nsIAtom> nameAtom = ni->GetNameAtom();
PRInt32 nsid = ni->GetNamespaceID();
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> 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<nsINodeInfo> contentNi = mContent->GetNodeInfo();
NS_ENSURE_TRUE(contentNi, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfoManager> 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<nsINodeInfo> ni;
mContent->NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aName);
if (!ni) {
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> nameAtom = ni->GetNameAtom();
nsCOMPtr<nsIDOMNode> 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;
}

View File

@ -694,12 +694,10 @@ nsGenericDOMDataNode::GetClassAttributeName() const
return nsnull;
}
NS_IMETHODIMP
nsGenericDOMDataNode::NormalizeAttrString(const nsAString& aStr,
nsINodeInfo** aNodeInfo)
NS_IMETHODIMP_(already_AddRefed<nsINodeInfo>)
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;

View File

@ -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<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
const nsAString& aValue, PRBool aNotify);
NS_IMETHOD SetAttr(nsINodeInfo *aNodeInfo,

View File

@ -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<nsINodeInfo> ni;
NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (!ni) {
SetDOMStringToNull(aReturn);
return NS_OK;
}
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> 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<nsINodeInfo> ni;
NormalizeAttrString(aName, getter_AddRefs(ni));
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (!ni) {
nsCOMPtr<nsINodeInfoManager> 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<nsINodeInfo> ni;
NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (!ni) {
return NS_OK;
}
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> tag = ni->GetNameAtom();
@ -1547,14 +1555,9 @@ nsGenericElement::HasAttribute(const nsAString& aName, PRBool* aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
nsCOMPtr<nsINodeInfo> ni;
NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ENSURE_TRUE(ni, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
*aReturn = (ni != nsnull);
PRInt32 nsid = ni->GetNamespaceID();
nsCOMPtr<nsIAtom> 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<nsINodeInfo>)
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<nsINodeInfoManager> nimgr;
mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr));
NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE);
return nimgr->GetNodeInfo(aStr, nsnull, kNameSpaceID_None, aNodeInfo);
return nsnull;
}
nsresult

View File

@ -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<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
PRBool aNotify);

View File

@ -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;
}

View File

@ -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<nsIAtom> 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___ */

View File

@ -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);

View File

@ -117,11 +117,9 @@ public:
return nsnull;
}
NS_IMETHOD NormalizeAttrString(const nsAString& aStr,
nsINodeInfo** aNodeInfo)
NS_IMETHOD_(already_AddRefed<nsINodeInfo>) 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;

View File

@ -378,6 +378,28 @@ nsGenericHTMLElement::GetTagName(nsAString& aTagName)
return GetNodeName(aTagName);
}
NS_IMETHODIMP
nsGenericHTMLElement::SetAttribute(const nsAString& aName,
const nsAString& aValue)
{
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (ni) {
return SetAttr(ni, aValue, PR_TRUE);
}
nsCOMPtr<nsIAtom> 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<nsINodeInfoManager> 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<nsINodeInfo>
nsGenericHTMLElement::GetExistingAttrNameFromQName(const nsAString& aStr)
{
if (!mAttributes) {
return nsnull;
}
NS_ConvertUCS2toUTF8 lower(aStr);
if (mNodeInfo->NamespaceEquals(kNameSpaceID_None)) {
ToLowerCase(lower);
}
nsCOMPtr<nsIAtom> 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<nsINodeInfoManager> nimgr;
mNodeInfo->GetNodeInfoManager(getter_AddRefs(nimgr));
NS_ENSURE_TRUE(nimgr, nsnull);
nsINodeInfo* nodeInfo;
nimgr->GetNodeInfo(nameAtom, prefixAtom, nameSpace, &nodeInfo);
return nodeInfo;
}
}
return nsnull;
}
nsresult

View File

@ -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<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
PRBool aNotify);

View File

@ -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<nsINodeInfo>)
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<nsINodeInfoManager> 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<nsINodeInfo> inpNodeInfo;
if (NS_FAILED(rv = mContent->NormalizeAttrString(aName, getter_AddRefs(inpNodeInfo))))
return rv;
nsCOMPtr<nsINodeInfo> 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();

View File

@ -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<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD GetAttrNameAt(PRInt32 aIndex,
PRInt32* aNameSpaceID,
nsIAtom** aName,

View File

@ -305,11 +305,10 @@ nsSVGElement::GetIDAttributeName() const
return nsSVGAtoms::id;
}
NS_IMETHODIMP
nsSVGElement::NormalizeAttrString(const nsAString& aStr,
nsINodeInfo** aNodeInfo)
NS_IMETHODIMP_(already_AddRefed<nsINodeInfo>)
nsSVGElement::GetExistingAttrNameFromQName(const nsAString& aStr)
{
return mAttributes->NormalizeAttrString(aStr, aNodeInfo);
return mAttributes->GetExistingAttrNameFromQName(aStr);
}
NS_IMETHODIMP

View File

@ -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<nsINodeInfo>) GetExistingAttrNameFromQName(const nsAString& aStr);
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
PRBool aNotify);

View File

@ -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<nsINodeInfo> inpNodeInfo;
if (NS_FAILED(rv = mContent->NormalizeAttrString(aName, getter_AddRefs(inpNodeInfo))))
return rv;
nsCOMPtr<nsINodeInfo> inpNodeInfo =
mContent->GetExistingAttrNameFromQName(aName);
if (!inpNodeInfo) {
return NS_OK;
}
// if (kNameSpaceID_Unknown == nameSpaceID) {
// nameSpaceID = kNameSpaceID_None; // ignore unknown prefix XXX is this correct?

View File

@ -1199,18 +1199,18 @@ NS_IMETHODIMP
nsXULElement::GetAttribute(const nsAString& aName,
nsAString& aReturn)
{
nsCOMPtr<nsINodeInfo> nodeInfo;
nsresult rv = NormalizeAttrString(aName,
getter_AddRefs(nodeInfo));
if (NS_FAILED(rv)) {
NS_WARNING("unable to normalize attribute name");
return rv;
nsCOMPtr<nsINodeInfo> nodeInfo = GetExistingAttrNameFromQName(aName);
if (!nodeInfo) {
aReturn.Truncate();
return NS_OK;
}
nsCOMPtr<nsIAtom> 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<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (!ni) {
nsCOMPtr<nsINodeInfoManager> nimgr;
NodeInfo()->GetNodeInfoManager(getter_AddRefs(nimgr));
NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE);
nsCOMPtr<nsINodeInfo> 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<nsINodeInfo> ni;
nsresult rv = NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse attribute name");
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIAtom> tag = ni->GetNameAtom();
PRInt32 nameSpaceID = ni->GetNamespaceID();
rv = UnsetAttr(nameSpaceID, tag, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to remove attribute");
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
if (!ni) {
return NS_OK;
}
return NS_OK;
nsCOMPtr<nsIAtom> 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<nsINodeInfo> ni;
nsCOMPtr<nsINodeInfo> ni = GetExistingAttrNameFromQName(aName);
*aReturn = (ni != nsnull);
nsresult rv = NormalizeAttrString(aName, getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAtom> 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<nsINodeInfo>)
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<nsINodeInfoManager> nimgr;
NodeInfo()->GetNodeInfoManager(getter_AddRefs(nimgr));
NS_ENSURE_TRUE(nimgr, NS_ERROR_FAILURE);
return nimgr->GetNodeInfo(aStr, nsnull, kNameSpaceID_None, aNodeInfo);
return nsnull;
}
void

View File

@ -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<nsINodeInfo>) 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;

View File

@ -1527,12 +1527,20 @@ nsXULDocument::Persist(const nsAString& aID,
if (! element)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsINodeInfo> ni;
rv = element->NormalizeAttrString(aAttr, getter_AddRefs(ni));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIAtom> tag;
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> tag = ni->GetNameAtom();
PRInt32 nameSpaceID = ni->GetNamespaceID();
nsCOMPtr<nsINodeInfo> 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;

View File

@ -865,13 +865,21 @@ nsXULContentBuilder::AddPersistentAttributes(nsIContent* aTemplateNode,
if (attribute.IsEmpty())
break;
nsCOMPtr<nsINodeInfo> ni;
rv = aTemplateNode->NormalizeAttrString(attribute,
getter_AddRefs(ni));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIAtom> tag;
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> tag = ni->GetNameAtom();
PRInt32 nameSpaceID = ni->GetNamespaceID();
nsCOMPtr<nsINodeInfo> 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<nsIRDFResource> property;
rv = nsXULContentUtils::GetResource(nameSpaceID, tag, getter_AddRefs(property));