Bug 51444 Make xbl:inherits work with namespaced attributes p=smaug@welho.com r+sr=bz

This commit is contained in:
neil%parkwaycc.co.uk 2005-01-01 18:02:03 +00:00
Родитель 9030bead0f
Коммит 36fef2db76
6 изменённых файлов: 169 добавлений и 50 удалений

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

@ -294,6 +294,14 @@ public:
static nsresult CheckQName(const nsAString& aQualifiedName, static nsresult CheckQName(const nsAString& aQualifiedName,
PRBool aNamespaceAware = PR_TRUE); PRBool aNamespaceAware = PR_TRUE);
static nsresult SplitQName(nsIContent* aNamespaceResolver,
const nsAFlatString& aQName,
PRInt32 *aNamespace, nsIAtom **aLocalName);
static nsresult LookupNamespaceURI(nsIContent* aNamespaceResolver,
const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI);
static nsresult GetNodeInfoFromQName(const nsAString& aNamespaceURI, static nsresult GetNodeInfoFromQName(const nsAString& aNamespaceURI,
const nsAString& aQualifiedName, const nsAString& aQualifiedName,
nsNodeInfoManager* aNodeInfoManager, nsNodeInfoManager* aNodeInfoManager,

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

@ -1627,6 +1627,66 @@ nsContentUtils::CheckQName(const nsAString& aQualifiedName,
aNamespaceAware, &colon); aNamespaceAware, &colon);
} }
//static
nsresult
nsContentUtils::SplitQName(nsIContent* aNamespaceResolver,
const nsAFlatString& aQName,
PRInt32 *aNamespace, nsIAtom **aLocalName)
{
nsIParserService* parserService = GetParserServiceWeakRef();
NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
const PRUnichar* colon;
nsresult rv = parserService->CheckQName(aQName, PR_TRUE, &colon);
NS_ENSURE_SUCCESS(rv, rv);
if (colon) {
const PRUnichar* end;
aQName.EndReading(end);
nsAutoString nameSpace;
rv = LookupNamespaceURI(aNamespaceResolver, Substring(aQName.get(), colon),
nameSpace);
NS_ENSURE_SUCCESS(rv, rv);
GetNSManagerWeakRef()->GetNameSpaceID(nameSpace, aNamespace);
if (*aNamespace == kNameSpaceID_Unknown)
return NS_ERROR_FAILURE;
*aLocalName = NS_NewAtom(Substring(colon + 1, end));
}
else {
*aNamespace = kNameSpaceID_None;
*aLocalName = NS_NewAtom(aQName);
}
NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
// static
nsresult
nsContentUtils::LookupNamespaceURI(nsIContent* aNamespaceResolver,
const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI)
{
nsCOMPtr<nsIAtom> name;
if (!aNamespacePrefix.IsEmpty()) {
name = do_GetAtom(aNamespacePrefix);
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
}
else {
name = nsLayoutAtoms::xmlnsNameSpace;
}
// Trace up the content parent chain looking for the namespace
// declaration that declares aNamespacePrefix.
for (nsIContent* content = aNamespaceResolver; content;
content = content->GetParent()) {
if (content->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI) ==
NS_CONTENT_ATTR_HAS_VALUE)
return NS_OK;
}
return NS_ERROR_FAILURE;
}
// static // static
nsresult nsresult
nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI, nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,

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

@ -460,28 +460,11 @@ NS_IMETHODIMP
nsNode3Tearoff::LookupNamespaceURI(const nsAString& aNamespacePrefix, nsNode3Tearoff::LookupNamespaceURI(const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI) nsAString& aNamespaceURI)
{ {
nsCOMPtr<nsIAtom> name; if (NS_FAILED(nsContentUtils::LookupNamespaceURI(mContent,
aNamespacePrefix,
if (!aNamespacePrefix.IsEmpty()) { aNamespaceURI))) {
name = do_GetAtom(aNamespacePrefix); SetDOMStringToNull(aNamespaceURI);
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
} else {
name = nsLayoutAtoms::xmlnsNameSpace;
} }
// Trace up the content parent chain looking for the namespace
// declaration that declares aNamespacePrefix.
for (nsIContent* content = mContent; content;
content = content->GetParent()) {
nsresult rv = content->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI);
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
return NS_OK;
}
}
SetDOMStringToNull(aNamespaceURI);
return NS_OK; return NS_OK;
} }

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

@ -66,7 +66,6 @@ XBL_ATOM(image, "image")
XBL_ATOM(stylesheet, "stylesheet") XBL_ATOM(stylesheet, "stylesheet")
XBL_ATOM(implementation, "implementation") XBL_ATOM(implementation, "implementation")
XBL_ATOM(implements, "implements") XBL_ATOM(implements, "implements")
XBL_ATOM(xbltext, "xbl:text")
XBL_ATOM(method, "method") XBL_ATOM(method, "method")
XBL_ATOM(property, "property") XBL_ATOM(property, "property")
XBL_ATOM(field, "field") XBL_ATOM(field, "field")

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

@ -73,6 +73,7 @@
#include "nsXBLAtoms.h" #include "nsXBLAtoms.h"
#include "nsXBLProtoImpl.h" #include "nsXBLProtoImpl.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsContentUtils.h"
#include "nsIScriptContext.h" #include "nsIScriptContext.h"
@ -88,6 +89,7 @@ class nsXBLAttributeEntry {
public: public:
nsIAtom* GetSrcAttribute() { return mSrcAttribute; } nsIAtom* GetSrcAttribute() { return mSrcAttribute; }
nsIAtom* GetDstAttribute() { return mDstAttribute; } nsIAtom* GetDstAttribute() { return mDstAttribute; }
PRInt32 GetDstNameSpace() { return mDstNameSpace; }
nsIContent* GetElement() { return mElement; } nsIContent* GetElement() { return mElement; }
@ -95,9 +97,10 @@ public:
void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; } void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; }
static nsXBLAttributeEntry* static nsXBLAttributeEntry*
Create(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, nsIContent* aContent) { Create(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, PRInt32 aDstNameSpace, nsIContent* aContent) {
void* place = nsXBLPrototypeBinding::kAttrPool->Alloc(sizeof(nsXBLAttributeEntry)); void* place = nsXBLPrototypeBinding::kAttrPool->Alloc(sizeof(nsXBLAttributeEntry));
return place ? ::new (place) nsXBLAttributeEntry(aSrcAtom, aDstAtom, aContent) : nsnull; return place ? ::new (place) nsXBLAttributeEntry(aSrcAtom, aDstAtom, aDstNameSpace,
aContent) : nsnull;
} }
static void static void
@ -111,13 +114,15 @@ protected:
nsCOMPtr<nsIAtom> mSrcAttribute; nsCOMPtr<nsIAtom> mSrcAttribute;
nsCOMPtr<nsIAtom> mDstAttribute; nsCOMPtr<nsIAtom> mDstAttribute;
PRInt32 mDstNameSpace;
nsXBLAttributeEntry* mNext; nsXBLAttributeEntry* mNext;
nsXBLAttributeEntry(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, nsXBLAttributeEntry(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, PRInt32 aDstNameSpace,
nsIContent* aContent) nsIContent* aContent)
: mElement(aContent), : mElement(aContent),
mSrcAttribute(aSrcAtom), mSrcAttribute(aSrcAtom),
mDstAttribute(aDstAtom), mDstAttribute(aDstAtom),
mDstNameSpace(aDstNameSpace),
mNext(nsnull) { } mNext(nsnull) { }
~nsXBLAttributeEntry() { delete mNext; } ~nsXBLAttributeEntry() { delete mNext; }
@ -226,7 +231,7 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding()
mHasBaseProto(PR_TRUE), mHasBaseProto(PR_TRUE),
mKeyHandlersRegistered(PR_FALSE), mKeyHandlersRegistered(PR_FALSE),
mResources(nsnull), mResources(nsnull),
mAttributeTable(nsnull), mAttributeTable(nsnull),
mInsertionPointTable(nsnull), mInsertionPointTable(nsnull),
mInterfaceTable(nsnull) mInterfaceTable(nsnull)
{ {
@ -436,9 +441,15 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute,
{ {
if (!mAttributeTable) if (!mAttributeTable)
return; return;
nsPRUint32Key nskey(aNameSpaceID);
nsObjectHashtable *attributesNS = NS_STATIC_CAST(nsObjectHashtable*,
mAttributeTable->Get(&nskey));
if (!attributesNS)
return;
nsISupportsKey key(aAttribute); nsISupportsKey key(aAttribute);
nsXBLAttributeEntry* xblAttr = NS_STATIC_CAST(nsXBLAttributeEntry*, mAttributeTable->Get(&key)); nsXBLAttributeEntry* xblAttr = NS_STATIC_CAST(nsXBLAttributeEntry*,
attributesNS->Get(&key));
if (!xblAttr) if (!xblAttr)
return; return;
@ -453,15 +464,16 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute,
if (realElement) { if (realElement) {
nsIAtom* dstAttr = xblAttr->GetDstAttribute(); nsIAtom* dstAttr = xblAttr->GetDstAttribute();
PRInt32 dstNs = xblAttr->GetDstNameSpace();
if (aRemoveFlag) if (aRemoveFlag)
realElement->UnsetAttr(aNameSpaceID, dstAttr, aNotify); realElement->UnsetAttr(dstNs, dstAttr, aNotify);
else { else {
PRBool attrPresent = PR_TRUE; PRBool attrPresent = PR_TRUE;
nsAutoString value; nsAutoString value;
// Check to see if the src attribute is xbl:text. If so, then we need to obtain the // Check to see if the src attribute is xbl:text. If so, then we need to obtain the
// children of the real element and get the text nodes' values. // children of the real element and get the text nodes' values.
if (aAttribute == nsXBLAtoms::xbltext) { if (aAttribute == nsHTMLAtoms::text && aNameSpaceID == kNameSpaceID_XBL) {
nsXBLBinding::GetTextData(aChangedElement, value); nsXBLBinding::GetTextData(aChangedElement, value);
value.StripChar(PRUnichar('\n')); value.StripChar(PRUnichar('\n'));
value.StripChar(PRUnichar('\r')); value.StripChar(PRUnichar('\r'));
@ -477,14 +489,14 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute,
} }
if (attrPresent) if (attrPresent)
realElement->SetAttr(aNameSpaceID, dstAttr, value, aNotify); realElement->SetAttr(dstNs, dstAttr, value, aNotify);
} }
// See if we're the <html> tag in XUL, and see if value is being // See if we're the <html> tag in XUL, and see if value is being
// set or unset on us. We may also be a tag that is having // set or unset on us. We may also be a tag that is having
// xbl:text set on us. // xbl:text set on us.
if (dstAttr == nsXBLAtoms::xbltext || if ((dstAttr == nsHTMLAtoms::text && dstNs == kNameSpaceID_XBL) ||
realElement->GetNodeInfo()->Equals(nsHTMLAtoms::html, realElement->GetNodeInfo()->Equals(nsHTMLAtoms::html,
kNameSpaceID_XUL) && kNameSpaceID_XUL) &&
dstAttr == nsHTMLAtoms::value) { dstAttr == nsHTMLAtoms::value) {
@ -833,6 +845,7 @@ struct nsXBLAttrChangeData
nsXBLPrototypeBinding* mProto; nsXBLPrototypeBinding* mProto;
nsIContent* mBoundElement; nsIContent* mBoundElement;
nsIContent* mContent; nsIContent* mContent;
PRInt32 mSrcNamespace;
nsXBLAttrChangeData(nsXBLPrototypeBinding* aProto, nsXBLAttrChangeData(nsXBLPrototypeBinding* aProto,
nsIContent* aElt, nsIContent* aContent) nsIContent* aElt, nsIContent* aContent)
@ -841,15 +854,15 @@ struct nsXBLAttrChangeData
PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure) PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
{ {
// XXX How to deal with NAMESPACES!!!?
nsXBLAttributeEntry* entry = NS_STATIC_CAST(nsXBLAttributeEntry*, aData); nsXBLAttributeEntry* entry = NS_STATIC_CAST(nsXBLAttributeEntry*, aData);
nsXBLAttrChangeData* changeData = NS_STATIC_CAST(nsXBLAttrChangeData*, aClosure); nsXBLAttrChangeData* changeData = NS_STATIC_CAST(nsXBLAttrChangeData*, aClosure);
nsIAtom* src = entry->GetSrcAttribute(); nsIAtom* src = entry->GetSrcAttribute();
PRInt32 srcNs = changeData->mSrcNamespace;
nsAutoString value; nsAutoString value;
PRBool attrPresent = PR_TRUE; PRBool attrPresent = PR_TRUE;
if (src == nsXBLAtoms::xbltext) { if (src == nsHTMLAtoms::text && srcNs == kNameSpaceID_XBL) {
nsXBLBinding::GetTextData(changeData->mBoundElement, value); nsXBLBinding::GetTextData(changeData->mBoundElement, value);
value.StripChar(PRUnichar('\n')); value.StripChar(PRUnichar('\n'));
value.StripChar(PRUnichar('\r')); value.StripChar(PRUnichar('\r'));
@ -860,7 +873,7 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
attrPresent = PR_FALSE; attrPresent = PR_FALSE;
} }
else { else {
nsresult result = changeData->mBoundElement->GetAttr(kNameSpaceID_None, src, value); nsresult result = changeData->mBoundElement->GetAttr(srcNs, src, value);
attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE || attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
result == NS_CONTENT_ATTR_HAS_VALUE); result == NS_CONTENT_ATTR_HAS_VALUE);
} }
@ -872,6 +885,7 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
nsXBLAttributeEntry* curr = entry; nsXBLAttributeEntry* curr = entry;
while (curr) { while (curr) {
nsIAtom* dst = curr->GetDstAttribute(); nsIAtom* dst = curr->GetDstAttribute();
PRInt32 dstNs = curr->GetDstNameSpace();
nsIContent* element = curr->GetElement(); nsIContent* element = curr->GetElement();
nsCOMPtr<nsIContent> realElement; nsCOMPtr<nsIContent> realElement;
@ -880,9 +894,9 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
changeData->mContent, changeData->mContent,
element); element);
if (realElement) { if (realElement) {
realElement->SetAttr(kNameSpaceID_None, dst, value, PR_FALSE); realElement->SetAttr(dstNs, dst, value, PR_FALSE);
if (dst == nsXBLAtoms::xbltext || if ((dst == nsHTMLAtoms::text && dstNs == kNameSpaceID_XBL) ||
(realElement->GetNodeInfo()->Equals(nsHTMLAtoms::html, (realElement->GetNodeInfo()->Equals(nsHTMLAtoms::html,
kNameSpaceID_XUL) && kNameSpaceID_XUL) &&
dst == nsHTMLAtoms::value && !value.IsEmpty())) { dst == nsHTMLAtoms::value && !value.IsEmpty())) {
@ -904,12 +918,26 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
return PR_TRUE; return PR_TRUE;
} }
PRBool PR_CALLBACK SetAttrsNS(nsHashKey* aKey, void* aData, void* aClosure)
{
if (aData && aClosure) {
nsPRUint32Key * key = NS_STATIC_CAST(nsPRUint32Key*, aKey);
nsObjectHashtable* xblAttributes =
NS_STATIC_CAST(nsObjectHashtable*, aData);
nsXBLAttrChangeData * changeData = NS_STATIC_CAST(nsXBLAttrChangeData *,
aClosure);
changeData->mSrcNamespace = key->GetValue();
xblAttributes->Enumerate(SetAttrs, (void*)changeData);
}
return PR_TRUE;
}
void void
nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent) nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent)
{ {
if (mAttributeTable) { if (mAttributeTable) {
nsXBLAttrChangeData data(this, aBoundElement, aAnonymousContent); nsXBLAttrChangeData data(this, aBoundElement, aAnonymousContent);
mAttributeTable->Enumerate(SetAttrs, (void*)&data); mAttributeTable->Enumerate(SetAttrsNS, (void*)&data);
} }
} }
@ -936,9 +964,14 @@ nsXBLPrototypeBinding::GetStyleSheets()
PRBool PRBool
nsXBLPrototypeBinding::ShouldBuildChildFrames() nsXBLPrototypeBinding::ShouldBuildChildFrames()
{ {
if (mAttributeTable) { if (!mAttributeTable)
nsISupportsKey key(nsXBLAtoms::xbltext); return PR_TRUE;
void* entry = mAttributeTable->Get(&key); nsPRUint32Key nskey(kNameSpaceID_XBL);
nsObjectHashtable* xblAttributes =
NS_STATIC_CAST(nsObjectHashtable*, mAttributeTable->Get(&nskey));
if (xblAttributes) {
nsISupportsKey key(nsHTMLAtoms::text);
void* entry = xblAttributes->Get(&key);
return !entry; return !entry;
} }
@ -952,6 +985,13 @@ DeleteAttributeEntry(nsHashKey* aKey, void* aData, void* aClosure)
return PR_TRUE; return PR_TRUE;
} }
static PRBool PR_CALLBACK
DeleteAttributeTable(nsHashKey* aKey, void* aData, void* aClosure)
{
delete NS_STATIC_CAST(nsObjectHashtable*, aData);
return PR_TRUE;
}
void void
nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement) nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
{ {
@ -961,7 +1001,7 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
if (!inherits.IsEmpty()) { if (!inherits.IsEmpty()) {
if (!mAttributeTable) { if (!mAttributeTable) {
mAttributeTable = new nsObjectHashtable(nsnull, nsnull, mAttributeTable = new nsObjectHashtable(nsnull, nsnull,
DeleteAttributeEntry, nsnull, 4); DeleteAttributeTable, nsnull, 4);
if (!mAttributeTable) if (!mAttributeTable)
return; return;
} }
@ -976,38 +1016,66 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
while( token != NULL ) { while( token != NULL ) {
// Build an atom out of this attribute. // Build an atom out of this attribute.
nsCOMPtr<nsIAtom> atom; nsCOMPtr<nsIAtom> atom;
PRInt32 atomNsID = kNameSpaceID_None;
nsCOMPtr<nsIAtom> attribute; nsCOMPtr<nsIAtom> attribute;
PRInt32 attributeNsID = kNameSpaceID_None;
// Figure out if this token contains a :. // Figure out if this token contains a :.
nsAutoString attrTok; attrTok.AssignWithConversion(token); nsAutoString attrTok; attrTok.AssignWithConversion(token);
PRInt32 index = attrTok.Find("=", PR_TRUE); PRInt32 index = attrTok.Find("=", PR_TRUE);
nsresult rv;
if (index != -1) { if (index != -1) {
// This attribute maps to something different. // This attribute maps to something different.
nsAutoString left, right; nsAutoString left, right;
attrTok.Left(left, index); attrTok.Left(left, index);
attrTok.Right(right, attrTok.Length()-index-1); attrTok.Right(right, attrTok.Length()-index-1);
atom = do_GetAtom(right); rv = nsContentUtils::SplitQName(aElement, left, &attributeNsID,
attribute = do_GetAtom(left); getter_AddRefs(attribute));
if (NS_FAILED(rv))
return;
rv = nsContentUtils::SplitQName(aElement, right, &atomNsID,
getter_AddRefs(atom));
if (NS_FAILED(rv))
return;
} }
else { else {
nsAutoString tok; nsAutoString tok;
tok.AssignWithConversion(token); tok.AssignWithConversion(token);
atom = do_GetAtom(tok); rv = nsContentUtils::SplitQName(aElement, tok, &atomNsID,
getter_AddRefs(atom));
if (NS_FAILED(rv))
return;
attribute = atom; attribute = atom;
attributeNsID = atomNsID;
}
nsPRUint32Key nskey(atomNsID);
nsObjectHashtable* attributesNS =
NS_STATIC_CAST(nsObjectHashtable*, mAttributeTable->Get(&nskey));
if (!attributesNS) {
attributesNS = new nsObjectHashtable(nsnull, nsnull,
DeleteAttributeEntry, nsnull, 4);
if (!attributesNS)
return;
mAttributeTable->Put(&nskey, attributesNS);
} }
// Create an XBL attribute entry. // Create an XBL attribute entry.
nsXBLAttributeEntry* xblAttr = nsXBLAttributeEntry::Create(atom, attribute, aElement); nsXBLAttributeEntry* xblAttr =
nsXBLAttributeEntry::Create(atom, attribute, attributeNsID, aElement);
// Now we should see if some element within our anonymous // Now we should see if some element within our anonymous
// content is already observing this attribute. // content is already observing this attribute.
nsISupportsKey key(atom); nsISupportsKey key(atom);
nsXBLAttributeEntry* entry = NS_STATIC_CAST(nsXBLAttributeEntry*, mAttributeTable->Get(&key)); nsXBLAttributeEntry* entry = NS_STATIC_CAST(nsXBLAttributeEntry*,
attributesNS->Get(&key));
if (!entry) { if (!entry) {
// Put it in the table. // Put it in the table.
mAttributeTable->Put(&key, xblAttr); attributesNS->Put(&key, xblAttr);
} else { } else {
while (entry->GetNext()) while (entry->GetNext())
entry = entry->GetNext(); entry = entry->GetNext();
@ -1250,7 +1318,7 @@ nsXBLPrototypeBinding::CreateKeyHandlers()
PRInt32 count = mKeyHandlers.Count(); PRInt32 count = mKeyHandlers.Count();
PRInt32 i; PRInt32 i;
nsXBLKeyEventHandler* handler; nsXBLKeyEventHandler* handler = nsnull;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
handler = mKeyHandlers[i]; handler = mKeyHandlers[i];
if (handler->Matches(eventAtom, phase, type)) if (handler->Matches(eventAtom, phase, type))

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

@ -236,8 +236,9 @@ protected:
nsIXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us. nsIXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us.
nsObjectHashtable* mAttributeTable; // A table for attribute entries. Used to efficiently nsObjectHashtable* mAttributeTable; // A table for attribute containers. Namespace IDs are used as
// handle attribute changes. // keys in the table. Containers are nsObjectHashtables.
// This table is used to efficiently handle attribute changes.
nsObjectHashtable* mInsertionPointTable; // A table of insertion points for placing explicit content nsObjectHashtable* mInsertionPointTable; // A table of insertion points for placing explicit content
// underneath anonymous content. // underneath anonymous content.