mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
fix hashtable lookup for xbl binding files to remove 15% of time paging up/down in mailnews r=waterson,hyatt
stop creating nsISupportsArrays and instead chain nsIXBLAttributeEntrys r=hyatt remove unnecessary creation of atoms r=hyatt (around 20% speedup to mailnews tree scrolling)
This commit is contained in:
parent
c06efd2fc4
commit
f3b435d030
@ -81,6 +81,8 @@ public:
|
||||
|
||||
NS_IMETHOD GetAttribute(nsIAtom** aResult) = 0;
|
||||
NS_IMETHOD GetElement(nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) = 0;
|
||||
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -89,8 +91,12 @@ public:
|
||||
NS_IMETHOD GetAttribute(nsIAtom** aResult) { *aResult = mAttribute; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
NS_IMETHOD GetElement(nsIContent** aResult) { *aResult = mElement; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
|
||||
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) { NS_IF_ADDREF(*aResult = mNext); return NS_OK; }
|
||||
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) { mNext = aEntry; return NS_OK; }
|
||||
|
||||
nsCOMPtr<nsIContent> mElement;
|
||||
nsCOMPtr<nsIAtom> mAttribute;
|
||||
nsCOMPtr<nsIXBLAttributeEntry> mNext;
|
||||
|
||||
nsXBLAttributeEntry(nsIAtom* aAtom, nsIContent* aContent) {
|
||||
NS_INIT_REFCNT(); mAttribute = aAtom; mElement = aContent;
|
||||
@ -910,64 +916,59 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
|
||||
if (!entry)
|
||||
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(supports);
|
||||
if (!xblAttr)
|
||||
return NS_OK;
|
||||
|
||||
// Iterate over the elements in the array.
|
||||
PRUint32 count;
|
||||
entry->Count(&count);
|
||||
|
||||
for (PRUint32 i=0; i<count; i++) {
|
||||
nsCOMPtr<nsISupports> item;
|
||||
entry->GetElementAt(i, getter_AddRefs(item));
|
||||
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(item);
|
||||
if (xblAttr) {
|
||||
nsCOMPtr<nsIContent> element;
|
||||
nsCOMPtr<nsIAtom> setAttr;
|
||||
xblAttr->GetElement(getter_AddRefs(element));
|
||||
xblAttr->GetAttribute(getter_AddRefs(setAttr));
|
||||
while (xblAttr) {
|
||||
nsCOMPtr<nsIContent> element;
|
||||
nsCOMPtr<nsIAtom> setAttr;
|
||||
xblAttr->GetElement(getter_AddRefs(element));
|
||||
xblAttr->GetAttribute(getter_AddRefs(setAttr));
|
||||
|
||||
if (aRemoveFlag)
|
||||
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
|
||||
else {
|
||||
if (aRemoveFlag)
|
||||
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
|
||||
else {
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
|
||||
if (attrPresent)
|
||||
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
element->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
element->ChildCount(childCount);
|
||||
if (childCount > 0)
|
||||
element->RemoveChildAt(0, PR_TRUE);
|
||||
|
||||
if (!aRemoveFlag) {
|
||||
// Construct a new text node and insert it.
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
|
||||
if (attrPresent)
|
||||
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
element->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
element->ChildCount(childCount);
|
||||
if (childCount > 0)
|
||||
element->RemoveChildAt(0, PR_TRUE);
|
||||
|
||||
if (!aRemoveFlag) {
|
||||
// Construct a new text node and insert it.
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
if (!value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
|
||||
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
|
||||
nsCOMPtr<nsIDOMNode> dummy;
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
|
||||
domElement->AppendChild(textNode, getter_AddRefs(dummy));
|
||||
}
|
||||
if (!value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
|
||||
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
|
||||
nsCOMPtr<nsIDOMNode> dummy;
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
|
||||
domElement->AppendChild(textNode, getter_AddRefs(dummy));
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
|
||||
tmpAttr->GetNext(getter_AddRefs(xblAttr));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1173,13 +1174,16 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
||||
if (!inherits.IsEmpty()) {
|
||||
if (!mAttributeTable) {
|
||||
mAttributeTable = new nsSupportsHashtable(8);
|
||||
mAttributeTable = new nsSupportsHashtable(4);
|
||||
}
|
||||
|
||||
// The user specified at least one attribute.
|
||||
char* str = inherits.ToNewCString();
|
||||
char* newStr;
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
// XXX We should use a strtok function that tokenizes PRUnichar's
|
||||
// so that we don't have to convert from Unicode to ASCII and then back
|
||||
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
while( token != NULL ) {
|
||||
// Build an atom out of this attribute.
|
||||
nsCOMPtr<nsIAtom> atom;
|
||||
@ -1194,12 +1198,13 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
attr.Left(left, index);
|
||||
attr.Right(right, attr.Length()-index-1);
|
||||
|
||||
atom = getter_AddRefs(NS_NewAtom(left));
|
||||
attribute = getter_AddRefs(NS_NewAtom(right));
|
||||
atom = getter_AddRefs(NS_NewAtom(left.GetUnicode()));
|
||||
attribute = getter_AddRefs(NS_NewAtom(right.GetUnicode()));
|
||||
}
|
||||
else {
|
||||
atom = getter_AddRefs(NS_NewAtom(token));
|
||||
attribute = getter_AddRefs(NS_NewAtom(token));
|
||||
nsAutoString tok; tok.AssignWithConversion(token);
|
||||
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
|
||||
attribute = atom;
|
||||
}
|
||||
|
||||
// Create an XBL attribute entry.
|
||||
@ -1211,18 +1216,20 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
|
||||
nsCOMPtr<nsIXBLAttributeEntry> entry = do_QueryInterface(supports);
|
||||
if (!entry) {
|
||||
// Make a new entry.
|
||||
NS_NewISupportsArray(getter_AddRefs(entry));
|
||||
|
||||
// Put it in the table.
|
||||
mAttributeTable->Put(&key, entry);
|
||||
mAttributeTable->Put(&key, xblAttr);
|
||||
} else {
|
||||
nsCOMPtr<nsIXBLAttributeEntry> attr = entry;
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = entry;
|
||||
do {
|
||||
attr = tmpAttr;
|
||||
attr->GetNext(getter_AddRefs(tmpAttr));
|
||||
} while (tmpAttr);
|
||||
attr->SetNext(xblAttr);
|
||||
}
|
||||
|
||||
// Append ourselves to our entry.
|
||||
entry->AppendElement(xblAttr);
|
||||
|
||||
// Now make sure that this attribute is initially set.
|
||||
// XXX How to deal with NAMESPACES!!!?
|
||||
nsAutoString value;
|
||||
|
@ -133,10 +133,10 @@ public:
|
||||
virtual ~nsXBLService();
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
|
||||
NS_IMETHOD GetBindingDocument(nsIURL* aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD GetBindingDocument(const nsCString& aURI, nsIDocument** aResult);
|
||||
|
||||
// This method synchronously loads and parses an XBL file.
|
||||
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
|
||||
@ -145,34 +145,6 @@ public:
|
||||
// that contain only whitespace.
|
||||
NS_IMETHOD StripWhitespaceNodes(nsIContent* aContent);
|
||||
|
||||
protected:
|
||||
// This URIkey class is used to hash URLs into an XBL binding
|
||||
// cache.
|
||||
class nsIURIKey : public nsHashKey {
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mKey;
|
||||
|
||||
public:
|
||||
nsIURIKey(nsIURI* key) : mKey(key) {}
|
||||
~nsIURIKey(void) {}
|
||||
|
||||
PRUint32 HashValue(void) const {
|
||||
nsXPIDLCString spec;
|
||||
mKey->GetSpec(getter_Copies(spec));
|
||||
return (PRUint32) PL_HashString(spec);
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
PRBool eq;
|
||||
mKey->Equals( ((nsIURIKey*) aKey)->mKey, &eq );
|
||||
return eq;
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIURIKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
static nsSupportsHashtable* mBindingTable; // This is a table of all the bindings files
|
||||
@ -378,26 +350,22 @@ nsXBLService::GetBaseTag(nsIContent* aContent, nsIAtom** aResult)
|
||||
|
||||
// Internal helper methods ////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult)
|
||||
NS_IMETHODIMP nsXBLService::GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
if (aURLStr.IsEmpty())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
// XXX Obtain the # marker and remove it from the URL.
|
||||
nsXPIDLCString ref;
|
||||
uri->GetRef(getter_Copies(ref));
|
||||
uri->SetRef("");
|
||||
nsCAutoString uri(aURLStr);
|
||||
PRInt32 indx = uri.RFindChar('#');
|
||||
nsCAutoString ref;
|
||||
uri.Right(ref, uri.Length() - (indx + 1));
|
||||
uri.Truncate(indx);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
GetBindingDocument(uri, getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -454,17 +422,25 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** a
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetBindingDocument(nsIURL* aURI, nsIDocument** aResult)
|
||||
nsXBLService::GetBindingDocument(const nsCString& aURLStr, nsIDocument** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
// We've got a file. Check our key binding file cache.
|
||||
nsIURIKey key(aURI);
|
||||
nsStringKey key(aURLStr);
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
document = dont_AddRef(NS_STATIC_CAST(nsIDocument*, mBindingTable->Get(&key)));
|
||||
|
||||
if (!document) {
|
||||
FetchBindingDocument(aURI, getter_AddRefs(document));
|
||||
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
FetchBindingDocument(uri, getter_AddRefs(document));
|
||||
if (document) {
|
||||
// Put the key binding doc into our table.
|
||||
mBindingTable->Put(&key, document);
|
||||
|
@ -81,6 +81,8 @@ public:
|
||||
|
||||
NS_IMETHOD GetAttribute(nsIAtom** aResult) = 0;
|
||||
NS_IMETHOD GetElement(nsIContent** aResult) = 0;
|
||||
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) = 0;
|
||||
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -89,8 +91,12 @@ public:
|
||||
NS_IMETHOD GetAttribute(nsIAtom** aResult) { *aResult = mAttribute; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
NS_IMETHOD GetElement(nsIContent** aResult) { *aResult = mElement; NS_IF_ADDREF(*aResult); return NS_OK; };
|
||||
|
||||
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) { NS_IF_ADDREF(*aResult = mNext); return NS_OK; }
|
||||
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) { mNext = aEntry; return NS_OK; }
|
||||
|
||||
nsCOMPtr<nsIContent> mElement;
|
||||
nsCOMPtr<nsIAtom> mAttribute;
|
||||
nsCOMPtr<nsIXBLAttributeEntry> mNext;
|
||||
|
||||
nsXBLAttributeEntry(nsIAtom* aAtom, nsIContent* aContent) {
|
||||
NS_INIT_REFCNT(); mAttribute = aAtom; mElement = aContent;
|
||||
@ -910,64 +916,59 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
|
||||
if (!entry)
|
||||
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(supports);
|
||||
if (!xblAttr)
|
||||
return NS_OK;
|
||||
|
||||
// Iterate over the elements in the array.
|
||||
PRUint32 count;
|
||||
entry->Count(&count);
|
||||
|
||||
for (PRUint32 i=0; i<count; i++) {
|
||||
nsCOMPtr<nsISupports> item;
|
||||
entry->GetElementAt(i, getter_AddRefs(item));
|
||||
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(item);
|
||||
if (xblAttr) {
|
||||
nsCOMPtr<nsIContent> element;
|
||||
nsCOMPtr<nsIAtom> setAttr;
|
||||
xblAttr->GetElement(getter_AddRefs(element));
|
||||
xblAttr->GetAttribute(getter_AddRefs(setAttr));
|
||||
while (xblAttr) {
|
||||
nsCOMPtr<nsIContent> element;
|
||||
nsCOMPtr<nsIAtom> setAttr;
|
||||
xblAttr->GetElement(getter_AddRefs(element));
|
||||
xblAttr->GetAttribute(getter_AddRefs(setAttr));
|
||||
|
||||
if (aRemoveFlag)
|
||||
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
|
||||
else {
|
||||
if (aRemoveFlag)
|
||||
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
|
||||
else {
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
|
||||
if (attrPresent)
|
||||
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
element->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
element->ChildCount(childCount);
|
||||
if (childCount > 0)
|
||||
element->RemoveChildAt(0, PR_TRUE);
|
||||
|
||||
if (!aRemoveFlag) {
|
||||
// Construct a new text node and insert it.
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
|
||||
if (attrPresent)
|
||||
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
element->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
element->ChildCount(childCount);
|
||||
if (childCount > 0)
|
||||
element->RemoveChildAt(0, PR_TRUE);
|
||||
|
||||
if (!aRemoveFlag) {
|
||||
// Construct a new text node and insert it.
|
||||
nsAutoString value;
|
||||
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
if (!value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
|
||||
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
|
||||
nsCOMPtr<nsIDOMNode> dummy;
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
|
||||
domElement->AppendChild(textNode, getter_AddRefs(dummy));
|
||||
}
|
||||
if (!value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
|
||||
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
|
||||
nsCOMPtr<nsIDOMNode> dummy;
|
||||
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
|
||||
domElement->AppendChild(textNode, getter_AddRefs(dummy));
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
|
||||
tmpAttr->GetNext(getter_AddRefs(xblAttr));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1173,13 +1174,16 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
||||
if (!inherits.IsEmpty()) {
|
||||
if (!mAttributeTable) {
|
||||
mAttributeTable = new nsSupportsHashtable(8);
|
||||
mAttributeTable = new nsSupportsHashtable(4);
|
||||
}
|
||||
|
||||
// The user specified at least one attribute.
|
||||
char* str = inherits.ToNewCString();
|
||||
char* newStr;
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
// XXX We should use a strtok function that tokenizes PRUnichar's
|
||||
// so that we don't have to convert from Unicode to ASCII and then back
|
||||
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
while( token != NULL ) {
|
||||
// Build an atom out of this attribute.
|
||||
nsCOMPtr<nsIAtom> atom;
|
||||
@ -1194,12 +1198,13 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
attr.Left(left, index);
|
||||
attr.Right(right, attr.Length()-index-1);
|
||||
|
||||
atom = getter_AddRefs(NS_NewAtom(left));
|
||||
attribute = getter_AddRefs(NS_NewAtom(right));
|
||||
atom = getter_AddRefs(NS_NewAtom(left.GetUnicode()));
|
||||
attribute = getter_AddRefs(NS_NewAtom(right.GetUnicode()));
|
||||
}
|
||||
else {
|
||||
atom = getter_AddRefs(NS_NewAtom(token));
|
||||
attribute = getter_AddRefs(NS_NewAtom(token));
|
||||
nsAutoString tok; tok.AssignWithConversion(token);
|
||||
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
|
||||
attribute = atom;
|
||||
}
|
||||
|
||||
// Create an XBL attribute entry.
|
||||
@ -1211,18 +1216,20 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
|
||||
nsCOMPtr<nsIXBLAttributeEntry> entry = do_QueryInterface(supports);
|
||||
if (!entry) {
|
||||
// Make a new entry.
|
||||
NS_NewISupportsArray(getter_AddRefs(entry));
|
||||
|
||||
// Put it in the table.
|
||||
mAttributeTable->Put(&key, entry);
|
||||
mAttributeTable->Put(&key, xblAttr);
|
||||
} else {
|
||||
nsCOMPtr<nsIXBLAttributeEntry> attr = entry;
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = entry;
|
||||
do {
|
||||
attr = tmpAttr;
|
||||
attr->GetNext(getter_AddRefs(tmpAttr));
|
||||
} while (tmpAttr);
|
||||
attr->SetNext(xblAttr);
|
||||
}
|
||||
|
||||
// Append ourselves to our entry.
|
||||
entry->AppendElement(xblAttr);
|
||||
|
||||
// Now make sure that this attribute is initially set.
|
||||
// XXX How to deal with NAMESPACES!!!?
|
||||
nsAutoString value;
|
||||
|
@ -133,10 +133,10 @@ public:
|
||||
virtual ~nsXBLService();
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
|
||||
NS_IMETHOD GetBindingDocument(nsIURL* aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD GetBindingDocument(const nsCString& aURI, nsIDocument** aResult);
|
||||
|
||||
// This method synchronously loads and parses an XBL file.
|
||||
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
|
||||
@ -145,34 +145,6 @@ public:
|
||||
// that contain only whitespace.
|
||||
NS_IMETHOD StripWhitespaceNodes(nsIContent* aContent);
|
||||
|
||||
protected:
|
||||
// This URIkey class is used to hash URLs into an XBL binding
|
||||
// cache.
|
||||
class nsIURIKey : public nsHashKey {
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mKey;
|
||||
|
||||
public:
|
||||
nsIURIKey(nsIURI* key) : mKey(key) {}
|
||||
~nsIURIKey(void) {}
|
||||
|
||||
PRUint32 HashValue(void) const {
|
||||
nsXPIDLCString spec;
|
||||
mKey->GetSpec(getter_Copies(spec));
|
||||
return (PRUint32) PL_HashString(spec);
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
PRBool eq;
|
||||
mKey->Equals( ((nsIURIKey*) aKey)->mKey, &eq );
|
||||
return eq;
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIURIKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
static nsSupportsHashtable* mBindingTable; // This is a table of all the bindings files
|
||||
@ -378,26 +350,22 @@ nsXBLService::GetBaseTag(nsIContent* aContent, nsIAtom** aResult)
|
||||
|
||||
// Internal helper methods ////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult)
|
||||
NS_IMETHODIMP nsXBLService::GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
if (aURLStr.IsEmpty())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
// XXX Obtain the # marker and remove it from the URL.
|
||||
nsXPIDLCString ref;
|
||||
uri->GetRef(getter_Copies(ref));
|
||||
uri->SetRef("");
|
||||
nsCAutoString uri(aURLStr);
|
||||
PRInt32 indx = uri.RFindChar('#');
|
||||
nsCAutoString ref;
|
||||
uri.Right(ref, uri.Length() - (indx + 1));
|
||||
uri.Truncate(indx);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
GetBindingDocument(uri, getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -454,17 +422,25 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** a
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetBindingDocument(nsIURL* aURI, nsIDocument** aResult)
|
||||
nsXBLService::GetBindingDocument(const nsCString& aURLStr, nsIDocument** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
// We've got a file. Check our key binding file cache.
|
||||
nsIURIKey key(aURI);
|
||||
nsStringKey key(aURLStr);
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
document = dont_AddRef(NS_STATIC_CAST(nsIDocument*, mBindingTable->Get(&key)));
|
||||
|
||||
if (!document) {
|
||||
FetchBindingDocument(aURI, getter_AddRefs(document));
|
||||
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
FetchBindingDocument(uri, getter_AddRefs(document));
|
||||
if (document) {
|
||||
// Put the key binding doc into our table.
|
||||
mBindingTable->Put(&key, document);
|
||||
|
Loading…
Reference in New Issue
Block a user