Bug 232639: Make nsXULElement::GetAttrNameAt actually work.

r/sr=bz
This commit is contained in:
cvshook%sicking.cc 2005-12-30 20:12:35 +00:00
Родитель a69e0b9f81
Коммит 2ee4c4c0f2
6 изменённых файлов: 99 добавлений и 127 удалений

Просмотреть файл

@ -453,6 +453,20 @@ nsAttrAndChildArray::RemoveAttrAt(PRUint32 aPos)
return NS_OK;
}
const nsAttrName*
nsAttrAndChildArray::AttrNameAt(PRUint32 aPos) const
{
NS_ASSERTION(aPos < AttrCount(),
"out-of-bounds access in nsAttrAndChildArray");
PRUint32 mapped = MappedAttrCount();
if (aPos < mapped) {
return mImpl->mMappedAttrs->NameAt(aPos);
}
return &ATTRS(mImpl)[aPos - mapped].mName;
}
const nsAttrName*
nsAttrAndChildArray::GetSafeAttrNameAt(PRUint32 aPos) const
{

Просмотреть файл

@ -97,7 +97,13 @@ public:
nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
nsresult SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue);
nsresult RemoveAttrAt(PRUint32 aPos);
// Returns attribute name at given position, *not* out-of-bounds safe
const nsAttrName* AttrNameAt(PRUint32 aPos) const;
// Returns attribute name at given position or null if aPos is out-of-boundss
const nsAttrName* GetSafeAttrNameAt(PRUint32 aPos) const;
// aName is UTF-8 encoded
const nsAttrName* GetExistingAttrNameFromQName(const nsACString& aName) const;
PRInt32 IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;

Просмотреть файл

@ -3864,7 +3864,7 @@ nsGenericElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep) const
for (i = 0; i < count; ++i) {
// XXX Once we have access to existing nsDOMAttributes for this element, we
// should call CloneNode or ImportNode on them.
const nsAttrName* name = mAttrsAndChildren.GetSafeAttrNameAt(i);
const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
nsAutoString valStr;
value->ToString(valStr);
@ -4190,7 +4190,7 @@ nsGenericElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const
PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
if (index >= 0) {
return nsAttrInfo(mAttrsAndChildren.GetSafeAttrNameAt(index),
return nsAttrInfo(mAttrsAndChildren.AttrNameAt(index),
mAttrsAndChildren.AttrAt(index));
}
@ -4363,7 +4363,7 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent) const
nsAutoString buffer;
// name
mAttrsAndChildren.GetSafeAttrNameAt(index)->GetQualifiedName(buffer);
mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(buffer);
// value
buffer.AppendLiteral("=");

Просмотреть файл

@ -282,7 +282,7 @@ nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep) const
for (i = 0; i < count; ++i) {
// XXX Once we have access to existing nsDOMAttributes for this element, we
// should call CloneNode or ImportNode on them.
const nsAttrName *name = mAttrsAndChildren.GetSafeAttrNameAt(i);
const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
if (name->Equals(nsHTMLAtoms::style, kNameSpaceID_None) &&
value->Type() == nsAttrValue::eCSSStyleRule) {

Просмотреть файл

@ -546,7 +546,7 @@ nsSVGElement::DidModifySVGObservable(nsISVGValue* aObservable,
return NS_ERROR_UNEXPECTED;
}
const nsAttrName* attrName = mMappedAttributes.GetSafeAttrNameAt(i);
const nsAttrName* attrName = mMappedAttributes.AttrNameAt(i);
PRBool modification = PR_FALSE;
PRBool hasListeners = PR_FALSE;
if (IsInDoc()) {
@ -660,7 +660,7 @@ nsSVGElement::UpdateContentStyleRule()
PRUint32 attrCount = mAttrsAndChildren.AttrCount();
for (PRUint32 i = 0; i < attrCount; ++i) {
const nsAttrName* attrName = mAttrsAndChildren.GetSafeAttrNameAt(i);
const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
continue;

Просмотреть файл

@ -54,17 +54,6 @@
* use in OS2
*/
/*
Implementation for a XUL content element.
TO DO
1. Possibly clean up the attribute walking code (e.g., in
SetDocument, GetAttrCount, etc.) by extracting into an iterator.
*/
#include "jsapi.h" // for JS_AddNamedRoot and JS_RemoveRootRT
#include "jsxdrapi.h"
#include "nsCOMPtr.h"
@ -190,22 +179,6 @@ static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
//----------------------------------------------------------------------
#if 0 /* || defined(DEBUG_shaver) || defined(DEBUG_waterson) */
#define DEBUG_ATTRIBUTE_STATS
#endif
#ifdef DEBUG_ATTRIBUTE_STATS
#include <execinfo.h>
static struct {
PRUint32 UnsetAttr;
PRUint32 Create;
PRUint32 Total;
} gFaults;
#endif
//----------------------------------------------------------------------
// XXX This function is called for every attribute on every element for
// XXX which we SetDocument, among other places. A linear search might
@ -391,21 +364,6 @@ NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
NS_ADDREF(*aResult = element);
#ifdef DEBUG_ATTRIBUTE_STATS
{
gFaults.Create++; gFaults.Total++;
nsAutoString tagstr;
element->NodeInfo()->GetQualifiedName(tagstr);
char *tagcstr = ToNewCString(tagstr);
fprintf(stderr, "XUL: Heavyweight create of <%s>: %d/%d\n",
tagcstr, gFaults.Create, gFaults.Total);
nsMemory::Free(tagcstr);
void *back[5];
backtrace(back, sizeof(back) / sizeof(back[0]));
backtrace_symbols_fd(back, sizeof(back) / sizeof(back[0]), 2);
}
#endif
return NS_OK;
}
@ -896,7 +854,7 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
PRBool haveLocalAttributes = (count > 0);
PRInt32 i;
for (i = 0; i < count; i++) {
AddListenerFor(*mAttrsAndChildren.GetSafeAttrNameAt(i),
AddListenerFor(*mAttrsAndChildren.AttrNameAt(i),
aCompileEventHandlers);
}
@ -1381,12 +1339,6 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
// fully fault and remove the local copy.
rv = MakeHeavyweight();
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_ATTRIBUTE_STATS
gFaults.UnsetAttr++; gFaults.Total++;
fprintf(stderr, "XUL: Faulting for UnsetAttr: %d/%d\n",
gFaults.UnsetAttr, gFaults.Total);
#endif
}
PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
@ -1495,50 +1447,57 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
const nsAttrName*
nsXULElement::GetAttrNameAt(PRUint32 aIndex) const
{
#ifdef DEBUG_ATTRIBUTE_STATS
int proto = mPrototype ? mPrototype->mNumAttributes : 0;
fprintf(stderr, "GANA: %p[%d] of %d/%d:", (void *)this, aIndex,
mAttrsAndChildren.AttrCount(), proto);
#endif
PRUint32 localCount = mAttrsAndChildren.AttrCount();
PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
PRUint32 localAttrCount = mAttrsAndChildren.AttrCount();
if (aIndex < localAttrCount) {
#ifdef DEBUG_ATTRIBUTE_STATS
fprintf(stderr, " local!\n");
#endif
return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
if (localCount > protoCount) {
// More local than proto, put local first
// Is the index low enough to just grab a local attr?
if (aIndex < localCount) {
return mAttrsAndChildren.AttrNameAt(aIndex);
}
aIndex -= localAttrCount;
aIndex -= localCount;
if (mPrototype && aIndex < mPrototype->mNumAttributes) {
// XXX This code looks very wrong. See bug 232639.
PRBool skip;
nsXULPrototypeAttribute* attr;
do {
attr = &mPrototype->mAttributes[aIndex];
skip = localAttrCount &&
mAttrsAndChildren.GetAttr(attr->mName.LocalName(),
attr->mName.NamespaceID());
#ifdef DEBUG_ATTRIBUTE_STATS
if (skip)
fprintf(stderr, " [skip %d/%d]", aIndex, aIndex + localAttrCount);
#endif
} while (skip && aIndex++ < mPrototype->mNumAttributes);
if (aIndex <= mPrototype->mNumAttributes) {
#ifdef DEBUG_ATTRIBUTE_STATS
fprintf(stderr, " proto[%d]!\n", aIndex);
#endif
return &(attr->mName);
// Search though prototype attributes while skipping names that exist in
// the local array.
for (PRUint32 i = 0; i < protoCount; i++) {
const nsAttrName* name = &mPrototype->mAttributes[i].mName;
if (mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
aIndex++;
}
// else, we are out of attrs to return, fall-through
if (i == aIndex) {
return name;
}
}
}
else {
// More proto than local, put proto first
// Is the index low enough to just grab a proto attr?
if (aIndex < protoCount) {
return &mPrototype->mAttributes[aIndex].mName;
}
#ifdef DEBUG_ATTRIBUTE_STATS
fprintf(stderr, " not found\n");
#endif
aIndex -= protoCount;
// Search though local attributes while skipping names that exist in
// the prototype array.
for (PRUint32 i = 0; i < localCount; i++) {
const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
for (PRUint32 j = 0; j < protoCount; j++) {
if (mPrototype->mAttributes[j].mName.Equals(*name)) {
aIndex++;
break;
}
}
if (i == aIndex) {
return name;
}
}
}
return nsnull;
}
@ -1546,45 +1505,38 @@ nsXULElement::GetAttrNameAt(PRUint32 aIndex) const
PRUint32
nsXULElement::GetAttrCount() const
{
PRBool haveLocalAttributes;
PRUint32 localCount = mAttrsAndChildren.AttrCount();
PRUint32 protoCount = mPrototype ? mPrototype->mNumAttributes : 0;
PRUint32 count = mAttrsAndChildren.AttrCount();
haveLocalAttributes = count > 0;
if (localCount > protoCount) {
// More local than proto, remove dups from proto array
PRUint32 count = localCount;
#ifdef DEBUG_ATTRIBUTE_STATS
int dups = 0;
#endif
for (PRUint32 i = 0; i < protoCount; i++) {
const nsAttrName* name = &mPrototype->mAttributes[i].mName;
if (!mAttrsAndChildren.GetAttr(name->LocalName(), name->NamespaceID())) {
count++;
}
}
if (mPrototype) {
for (PRUint32 i = 0; i < mPrototype->mNumAttributes; i++) {
nsAttrName* attrName = &mPrototype->mAttributes[i].mName;
return count;
}
if (!haveLocalAttributes ||
!mAttrsAndChildren.GetAttr(attrName->LocalName(),
attrName->NamespaceID())) {
++count;
#ifdef DEBUG_ATTRIBUTE_STATS
} else {
dups++;
#endif
// More proto than local, remove dups from local array
PRUint32 count = protoCount;
for (PRUint32 i = 0; i < localCount; i++) {
const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
count++;
for (PRUint32 j = 0; j < protoCount; j++) {
if (mPrototype->mAttributes[j].mName.Equals(*name)) {
count--;
break;
}
}
}
#ifdef DEBUG_ATTRIBUTE_STATS
{
int local = mAttrsAndChildren.AttrCount();
int proto = mPrototype ? mPrototype->mNumAttributes : 0;
nsAutoString tagstr;
mNodeInfo->GetName(tagstr);
char *tagcstr = ToNewCString(tagstr);
fprintf(stderr, "GAC: %p has %d+%d-%d=%d <%s%s>\n", (void *)this,
local, proto, dups, count, mPrototype ? "" : "*", tagcstr);
nsMemory::Free(tagcstr);
}
#endif
return count;
}