зеркало из https://github.com/mozilla/pjs.git
Bug 232639: Make nsXULElement::GetAttrNameAt actually work.
r/sr=bz
This commit is contained in:
Родитель
a69e0b9f81
Коммит
2ee4c4c0f2
|
@ -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
|
||||
|
||||
aIndex -= localAttrCount;
|
||||
|
||||
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);
|
||||
// Is the index low enough to just grab a local attr?
|
||||
if (aIndex < localCount) {
|
||||
return mAttrsAndChildren.AttrNameAt(aIndex);
|
||||
}
|
||||
// else, we are out of attrs to return, fall-through
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ATTRIBUTE_STATS
|
||||
fprintf(stderr, " not found\n");
|
||||
#endif
|
||||
aIndex -= localCount;
|
||||
|
||||
// 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++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!haveLocalAttributes ||
|
||||
!mAttrsAndChildren.GetAttr(attrName->LocalName(),
|
||||
attrName->NamespaceID())) {
|
||||
++count;
|
||||
#ifdef DEBUG_ATTRIBUTE_STATS
|
||||
} else {
|
||||
dups++;
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче