Fix for bug 30091. nsFormControlList::NamedItem() was doing a linear walk through the form control list. Now it uses a hash table lookup. This greatly reduces the time for the screen to update when one clicks on the Program list box on the Bugzilla query page.

This commit is contained in:
nisheeth%netscape.com 2000-04-19 07:49:07 +00:00
Родитель e731b49281
Коммит d6a5b5bf19
24 изменённых файлов: 468 добавлений и 88 удалений

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

@ -23,6 +23,7 @@
#define nsIForm_h___
#include "nsISupports.h"
#include "nsString.h"
class nsIFormControl;
class nsISizeOfHandler;
@ -51,6 +52,15 @@ public:
*/
NS_IMETHOD AddElement(nsIFormControl* aElement) = 0;
/**
* Add an element to the lookup table mainted by the form.
* We can't fold this method into AddElement() because when
* AddElement() is called, the form control has no
* attributes. The name or id attributes of the form control
* are used as a key into the table.
*/
NS_IMETHOD AddElementToTable(nsIFormControl* aElement, const nsString& aName) = 0;
/**
* Get the element at a specified index position
* @param aIndex the index

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

@ -3121,3 +3121,69 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
return NS_OK;
}
//----------------------------------------------------------------------
nsGenericHTMLContainerFormElement::nsGenericHTMLContainerFormElement()
{
mForm = nsnull;
}
nsGenericHTMLContainerFormElement::~nsGenericHTMLContainerFormElement()
{
// Do nothing
}
nsresult
nsGenericHTMLContainerFormElement::SetForm(nsIForm* aForm)
{
mForm = aForm;
return NS_OK;
}
nsresult
nsGenericHTMLContainerFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify)
{
// Add the control to the hash table
nsCOMPtr<nsIFormControl> control;
control = do_QueryInterface(mContent);
if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName))
mForm->AddElementToTable(control, aValue);
return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify);
}
//----------------------------------------------------------------------
nsGenericHTMLLeafFormElement::nsGenericHTMLLeafFormElement()
{
mForm = nsnull;
}
nsGenericHTMLLeafFormElement::~nsGenericHTMLLeafFormElement()
{
// Do nothing
}
nsresult
nsGenericHTMLLeafFormElement::SetForm(nsIForm* aForm)
{
mForm = aForm;
return NS_OK;
}
nsresult
nsGenericHTMLLeafFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify)
{
// Add the control to the hash table
nsCOMPtr<nsIFormControl> control;
control = do_QueryInterface(mContent);
if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName))
mForm->AddElementToTable(control, aValue);
return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify);
}
//----------------------------------------------------------------------

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

@ -454,6 +454,42 @@ public:
//----------------------------------------------------------------------
class nsGenericHTMLContainerFormElement : public nsGenericHTMLContainerElement {
public:
nsGenericHTMLContainerFormElement();
~nsGenericHTMLContainerFormElement();
nsresult SetForm(nsIForm* aForm);
nsresult SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify);
nsresult SetAttribute(const nsString& aName, const nsString& aValue)
{
return nsGenericHTMLElement::SetAttribute(aName, aValue);
}
nsIForm* mForm;
};
//----------------------------------------------------------------------
class nsGenericHTMLLeafFormElement : public nsGenericHTMLLeafElement {
public:
nsGenericHTMLLeafFormElement();
~nsGenericHTMLLeafFormElement();
nsresult SetForm(nsIForm* aForm);
nsresult SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify);
nsresult SetAttribute(const nsString& aName, const nsString& aValue)
{
return nsGenericHTMLElement::SetAttribute(aName, aValue);
}
nsIForm* mForm;
};
//----------------------------------------------------------------------
/**
* Implement the nsIDOMHTMLElement API by forwarding the methods to a
* generic content object (either nsGenericHTMLLeafElement or

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

@ -97,9 +97,9 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
PRInt32 mType;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
PRInt32 mType;
};
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
@ -528,6 +528,9 @@ nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -79,8 +79,8 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
// construction, destruction
@ -224,6 +224,9 @@ nsHTMLFieldSetElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -44,6 +44,9 @@
#include "nsIScriptGlobalObject.h"
#include "nsDOMError.h"
#include "nsLayoutUtils.h"
#include "nsHashTable.h"
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 64;
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
@ -109,6 +112,7 @@ public:
// nsIForm
NS_IMETHOD AddElement(nsIFormControl* aElement);
NS_IMETHOD AddElementToTable(nsIFormControl* aChild, const nsString& aName);
NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const;
NS_IMETHOD GetElementCount(PRUint32* aCount) const;
NS_IMETHOD RemoveElement(nsIFormControl* aElement, PRBool aChildIsRef = PR_TRUE);
@ -137,14 +141,21 @@ public:
NS_DECL_IDOMHTMLCOLLECTION
NS_DECL_IDOMHTMLFORMCONTROLLIST
nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj);
nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj);
nsresult AddElementToTable(nsIFormControl* aChild, const nsString& aName);
nsresult RemoveElementFromTable(nsIFormControl* aChild, PRBool aChildIsRef);
#ifdef DEBUG
nsresult SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
void *mScriptObject;
nsVoidArray mElements;
nsVoidArray mElements;
nsIDOMHTMLFormElement* mForm; // WEAK - the form owns me
protected:
nsHashtable* mLookupTable; // A map from an ID or NAME attribute to the form control
};
// nsHTMLFormElement implementation
@ -468,21 +479,32 @@ nsHTMLFormElement::GetElementAt(PRInt32 aIndex, nsIFormControl** aFormControl) c
}
NS_IMETHODIMP
nsHTMLFormElement::AddElement(nsIFormControl* aChild)
nsHTMLFormElement::AddElement(nsIFormControl* aChild)
{
PRBool rv = mControls->mElements.AppendElement(aChild);
if (rv) {
NS_ADDREF(aChild);
NS_ADDREF(aChild);
}
return rv;
}
NS_IMETHODIMP
nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild, const nsString& aName)
{
return mControls->AddElementToTable(aChild, aName);
}
NS_IMETHODIMP
nsHTMLFormElement::RemoveElement(nsIFormControl* aChild, PRBool aChildIsRef)
{
PRBool rv = mControls->mElements.RemoveElement(aChild);
if (rv && aChildIsRef) {
NS_RELEASE(aChild);
if (rv) {
mControls->RemoveElementFromTable(aChild, aChildIsRef);
if (aChildIsRef) {
NS_RELEASE(aChild);
}
}
return rv;
}
@ -701,10 +723,15 @@ nsFormControlList::nsFormControlList(nsIDOMHTMLFormElement* aForm)
NS_INIT_REFCNT();
mScriptObject = nsnull;
mForm = aForm; // WEAK - the form owns me
mLookupTable = nsnull;
}
nsFormControlList::~nsFormControlList()
{
if (mLookupTable) {
delete mLookupTable;
mLookupTable = nsnull;
}
mForm = nsnull;
Clear();
}
@ -728,6 +755,9 @@ nsFormControlList::Clear()
PRUint32 numElements = mElements.Count();
for (PRUint32 i = 0; i < numElements; i++) {
nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i);
if (mLookupTable) {
RemoveElementFromTable(elem, PR_TRUE);
}
NS_IF_RELEASE(elem);
}
}
@ -947,31 +977,57 @@ nsFormControlList::NamedItem(JSContext* cx, jsval* argv, PRUint32 argc, jsval* a
NS_IMETHODIMP
nsFormControlList::NamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
PRUint32 count = mElements.Count();
nsresult result = NS_OK;
nsStringKey key(aName);
nsIFormControl* control = nsnull;
*aReturn = nsnull;
for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) {
nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(i);
if (nsnull != control) {
nsIContent *content;
result = control->QueryInterface(kIContentIID, (void **)&content);
if (NS_OK == result) {
nsAutoString name;
// XXX Should it be an EqualsIgnoreCase?
if (((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
(aName.Equals(name))) ||
((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
(aName.Equals(name)))) {
result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn);
}
NS_RELEASE(content);
}
}
if (mLookupTable) {
control = (nsIFormControl*) mLookupTable->Get(&key);
}
if (control) {
result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn);
}
return result;
}
nsresult
nsFormControlList::AddElementToTable(nsIFormControl* aChild, const nsString& aName)
{
nsStringKey key(aName);
if (!mLookupTable)
mLookupTable = (nsHashtable*) new nsHashtable(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
mLookupTable->Put(&key, NS_STATIC_CAST(void*, aChild));
return NS_OK;
}
nsresult
nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild, PRBool aChildIsRef)
{
// This nsIContent* cannot be a COM pointer because it shouldn't
// be released at the end of this function when aChildIsRef is FALSE.
nsIContent* content = nsnull;
nsAutoString name;
aChild->QueryInterface(kIContentIID, (void**) &content);
if (mLookupTable && content &&
(content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name) == NS_CONTENT_ATTR_HAS_VALUE ||
content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, name) == NS_CONTENT_ATTR_HAS_VALUE))
{
nsStringKey key(name);
mLookupTable->Remove(&key);
}
return result;
if (aChildIsRef)
{
NS_RELEASE(content);
}
return NS_OK;
}
#ifdef DEBUG

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

@ -159,7 +159,7 @@ protected:
nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd);
protected:
nsGenericHTMLLeafElement mInner;
nsGenericHTMLLeafFormElement mInner;
nsIForm* mForm;
PRInt32 mType;
PRBool mSkipFocusEvent;
@ -167,6 +167,7 @@ protected:
nsCOMPtr<nsIXBLBinding> mBinding;
PRBool mDidMouseDown;
PRBool IsImage() const {
nsAutoString tmp;
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::type, tmp);
@ -1072,6 +1073,9 @@ nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -128,8 +128,8 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
// construction, destruction
@ -272,6 +272,9 @@ nsHTMLLabelElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -83,8 +83,8 @@ public:
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
nsresult
@ -199,6 +199,9 @@ nsHTMLLegendElement::SetForm(nsIDOMHTMLFormElement* aForm)
NS_RELEASE(formControl);
}
}
mInner.SetForm(mForm);
return result;
}

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

@ -108,7 +108,7 @@ protected:
nsGenericHTMLContainerElement mInner;
// Get the primary frame associated with this content
nsresult GetPrimaryFrame(nsIFormControlFrame *&aFormControlFrame);
nsresult GetPrimaryFrame(nsIFormControlFrame *&aFormControlFrame, PRBool aFlushNotifications = PR_TRUE);
// Get the select content element that contains this option
nsresult GetSelect(nsIDOMHTMLSelectElement *&aSelectElement);
@ -249,14 +249,14 @@ nsHTMLOptionElement::GetSelected(PRBool* aValue)
*aValue = value.EqualsWithConversion("1");
}
}
return rv;
return rv;
}
NS_IMETHODIMP
nsHTMLOptionElement::SetSelected(PRBool aValue)
{
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = GetPrimaryFrame(fcFrame);
nsresult result = GetPrimaryFrame(fcFrame, PR_FALSE);
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
nsISelectControlFrame* selectFrame = nsnull;
result = fcFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame),(void **) &selectFrame);
@ -542,7 +542,7 @@ nsHTMLOptionElement::SetText(const nsString& aText)
// Options don't have frames - get the select content node
// then call nsGenericHTMLElement::GetPrimaryFrame()
nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormControlFrame)
nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormControlFrame, PRBool aFlushNotifications)
{
nsIDOMHTMLSelectElement* selectElement = nsnull;
nsresult res = GetSelect(selectElement);
@ -552,7 +552,7 @@ nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormContro
NS_RELEASE(selectElement);
if (NS_OK == gotContent) {
res = nsGenericHTMLElement::GetPrimaryFrame(selectContent, aIFormControlFrame);
res = nsGenericHTMLElement::GetPrimaryFrame(selectContent, aIFormControlFrame, aFlushNotifications);
NS_RELEASE(selectContent);
}
}

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

@ -209,7 +209,7 @@ public:
protected:
NS_IMETHOD GetPresState(nsIPresState** aPresState, nsISupportsArray** aValueArray);
nsGenericHTMLContainerElement mInner;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
nsHTMLOptionCollection* mOptions;
PRBool mIsDoneAddingContent;
@ -1128,6 +1128,9 @@ nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -125,7 +125,7 @@ public:
NS_IMETHOD GetBaseTag(nsIAtom** aResult);
protected:
nsGenericHTMLContainerElement mInner;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
nsCOMPtr<nsIControllers> mControllers;
nsCOMPtr<nsIXBLBinding> mBinding;
@ -564,6 +564,9 @@ nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -23,6 +23,7 @@
#define nsIForm_h___
#include "nsISupports.h"
#include "nsString.h"
class nsIFormControl;
class nsISizeOfHandler;
@ -51,6 +52,15 @@ public:
*/
NS_IMETHOD AddElement(nsIFormControl* aElement) = 0;
/**
* Add an element to the lookup table mainted by the form.
* We can't fold this method into AddElement() because when
* AddElement() is called, the form control has no
* attributes. The name or id attributes of the form control
* are used as a key into the table.
*/
NS_IMETHOD AddElementToTable(nsIFormControl* aElement, const nsString& aName) = 0;
/**
* Get the element at a specified index position
* @param aIndex the index

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

@ -3121,3 +3121,69 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
return NS_OK;
}
//----------------------------------------------------------------------
nsGenericHTMLContainerFormElement::nsGenericHTMLContainerFormElement()
{
mForm = nsnull;
}
nsGenericHTMLContainerFormElement::~nsGenericHTMLContainerFormElement()
{
// Do nothing
}
nsresult
nsGenericHTMLContainerFormElement::SetForm(nsIForm* aForm)
{
mForm = aForm;
return NS_OK;
}
nsresult
nsGenericHTMLContainerFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify)
{
// Add the control to the hash table
nsCOMPtr<nsIFormControl> control;
control = do_QueryInterface(mContent);
if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName))
mForm->AddElementToTable(control, aValue);
return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify);
}
//----------------------------------------------------------------------
nsGenericHTMLLeafFormElement::nsGenericHTMLLeafFormElement()
{
mForm = nsnull;
}
nsGenericHTMLLeafFormElement::~nsGenericHTMLLeafFormElement()
{
// Do nothing
}
nsresult
nsGenericHTMLLeafFormElement::SetForm(nsIForm* aForm)
{
mForm = aForm;
return NS_OK;
}
nsresult
nsGenericHTMLLeafFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify)
{
// Add the control to the hash table
nsCOMPtr<nsIFormControl> control;
control = do_QueryInterface(mContent);
if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName))
mForm->AddElementToTable(control, aValue);
return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify);
}
//----------------------------------------------------------------------

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

@ -454,6 +454,42 @@ public:
//----------------------------------------------------------------------
class nsGenericHTMLContainerFormElement : public nsGenericHTMLContainerElement {
public:
nsGenericHTMLContainerFormElement();
~nsGenericHTMLContainerFormElement();
nsresult SetForm(nsIForm* aForm);
nsresult SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify);
nsresult SetAttribute(const nsString& aName, const nsString& aValue)
{
return nsGenericHTMLElement::SetAttribute(aName, aValue);
}
nsIForm* mForm;
};
//----------------------------------------------------------------------
class nsGenericHTMLLeafFormElement : public nsGenericHTMLLeafElement {
public:
nsGenericHTMLLeafFormElement();
~nsGenericHTMLLeafFormElement();
nsresult SetForm(nsIForm* aForm);
nsresult SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, const nsString& aValue,
PRBool aNotify);
nsresult SetAttribute(const nsString& aName, const nsString& aValue)
{
return nsGenericHTMLElement::SetAttribute(aName, aValue);
}
nsIForm* mForm;
};
//----------------------------------------------------------------------
/**
* Implement the nsIDOMHTMLElement API by forwarding the methods to a
* generic content object (either nsGenericHTMLLeafElement or

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

@ -97,9 +97,9 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
PRInt32 mType;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
PRInt32 mType;
};
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
@ -528,6 +528,9 @@ nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -79,8 +79,8 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
// construction, destruction
@ -224,6 +224,9 @@ nsHTMLFieldSetElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -44,6 +44,9 @@
#include "nsIScriptGlobalObject.h"
#include "nsDOMError.h"
#include "nsLayoutUtils.h"
#include "nsHashTable.h"
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 64;
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
@ -109,6 +112,7 @@ public:
// nsIForm
NS_IMETHOD AddElement(nsIFormControl* aElement);
NS_IMETHOD AddElementToTable(nsIFormControl* aChild, const nsString& aName);
NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const;
NS_IMETHOD GetElementCount(PRUint32* aCount) const;
NS_IMETHOD RemoveElement(nsIFormControl* aElement, PRBool aChildIsRef = PR_TRUE);
@ -137,14 +141,21 @@ public:
NS_DECL_IDOMHTMLCOLLECTION
NS_DECL_IDOMHTMLFORMCONTROLLIST
nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj);
nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj);
nsresult AddElementToTable(nsIFormControl* aChild, const nsString& aName);
nsresult RemoveElementFromTable(nsIFormControl* aChild, PRBool aChildIsRef);
#ifdef DEBUG
nsresult SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
#endif
void *mScriptObject;
nsVoidArray mElements;
nsVoidArray mElements;
nsIDOMHTMLFormElement* mForm; // WEAK - the form owns me
protected:
nsHashtable* mLookupTable; // A map from an ID or NAME attribute to the form control
};
// nsHTMLFormElement implementation
@ -468,21 +479,32 @@ nsHTMLFormElement::GetElementAt(PRInt32 aIndex, nsIFormControl** aFormControl) c
}
NS_IMETHODIMP
nsHTMLFormElement::AddElement(nsIFormControl* aChild)
nsHTMLFormElement::AddElement(nsIFormControl* aChild)
{
PRBool rv = mControls->mElements.AppendElement(aChild);
if (rv) {
NS_ADDREF(aChild);
NS_ADDREF(aChild);
}
return rv;
}
NS_IMETHODIMP
nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild, const nsString& aName)
{
return mControls->AddElementToTable(aChild, aName);
}
NS_IMETHODIMP
nsHTMLFormElement::RemoveElement(nsIFormControl* aChild, PRBool aChildIsRef)
{
PRBool rv = mControls->mElements.RemoveElement(aChild);
if (rv && aChildIsRef) {
NS_RELEASE(aChild);
if (rv) {
mControls->RemoveElementFromTable(aChild, aChildIsRef);
if (aChildIsRef) {
NS_RELEASE(aChild);
}
}
return rv;
}
@ -701,10 +723,15 @@ nsFormControlList::nsFormControlList(nsIDOMHTMLFormElement* aForm)
NS_INIT_REFCNT();
mScriptObject = nsnull;
mForm = aForm; // WEAK - the form owns me
mLookupTable = nsnull;
}
nsFormControlList::~nsFormControlList()
{
if (mLookupTable) {
delete mLookupTable;
mLookupTable = nsnull;
}
mForm = nsnull;
Clear();
}
@ -728,6 +755,9 @@ nsFormControlList::Clear()
PRUint32 numElements = mElements.Count();
for (PRUint32 i = 0; i < numElements; i++) {
nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i);
if (mLookupTable) {
RemoveElementFromTable(elem, PR_TRUE);
}
NS_IF_RELEASE(elem);
}
}
@ -947,31 +977,57 @@ nsFormControlList::NamedItem(JSContext* cx, jsval* argv, PRUint32 argc, jsval* a
NS_IMETHODIMP
nsFormControlList::NamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
PRUint32 count = mElements.Count();
nsresult result = NS_OK;
nsStringKey key(aName);
nsIFormControl* control = nsnull;
*aReturn = nsnull;
for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) {
nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(i);
if (nsnull != control) {
nsIContent *content;
result = control->QueryInterface(kIContentIID, (void **)&content);
if (NS_OK == result) {
nsAutoString name;
// XXX Should it be an EqualsIgnoreCase?
if (((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
(aName.Equals(name))) ||
((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
(aName.Equals(name)))) {
result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn);
}
NS_RELEASE(content);
}
}
if (mLookupTable) {
control = (nsIFormControl*) mLookupTable->Get(&key);
}
if (control) {
result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn);
}
return result;
}
nsresult
nsFormControlList::AddElementToTable(nsIFormControl* aChild, const nsString& aName)
{
nsStringKey key(aName);
if (!mLookupTable)
mLookupTable = (nsHashtable*) new nsHashtable(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
mLookupTable->Put(&key, NS_STATIC_CAST(void*, aChild));
return NS_OK;
}
nsresult
nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild, PRBool aChildIsRef)
{
// This nsIContent* cannot be a COM pointer because it shouldn't
// be released at the end of this function when aChildIsRef is FALSE.
nsIContent* content = nsnull;
nsAutoString name;
aChild->QueryInterface(kIContentIID, (void**) &content);
if (mLookupTable && content &&
(content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name) == NS_CONTENT_ATTR_HAS_VALUE ||
content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, name) == NS_CONTENT_ATTR_HAS_VALUE))
{
nsStringKey key(name);
mLookupTable->Remove(&key);
}
return result;
if (aChildIsRef)
{
NS_RELEASE(content);
}
return NS_OK;
}
#ifdef DEBUG

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

@ -159,7 +159,7 @@ protected:
nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd);
protected:
nsGenericHTMLLeafElement mInner;
nsGenericHTMLLeafFormElement mInner;
nsIForm* mForm;
PRInt32 mType;
PRBool mSkipFocusEvent;
@ -167,6 +167,7 @@ protected:
nsCOMPtr<nsIXBLBinding> mBinding;
PRBool mDidMouseDown;
PRBool IsImage() const {
nsAutoString tmp;
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::type, tmp);
@ -1072,6 +1073,9 @@ nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -128,8 +128,8 @@ public:
NS_IMETHOD Init() { return NS_OK; }
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
// construction, destruction
@ -272,6 +272,9 @@ nsHTMLLabelElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -83,8 +83,8 @@ public:
protected:
nsGenericHTMLContainerElement mInner;
nsIForm* mForm;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
};
nsresult
@ -199,6 +199,9 @@ nsHTMLLegendElement::SetForm(nsIDOMHTMLFormElement* aForm)
NS_RELEASE(formControl);
}
}
mInner.SetForm(mForm);
return result;
}

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

@ -108,7 +108,7 @@ protected:
nsGenericHTMLContainerElement mInner;
// Get the primary frame associated with this content
nsresult GetPrimaryFrame(nsIFormControlFrame *&aFormControlFrame);
nsresult GetPrimaryFrame(nsIFormControlFrame *&aFormControlFrame, PRBool aFlushNotifications = PR_TRUE);
// Get the select content element that contains this option
nsresult GetSelect(nsIDOMHTMLSelectElement *&aSelectElement);
@ -249,14 +249,14 @@ nsHTMLOptionElement::GetSelected(PRBool* aValue)
*aValue = value.EqualsWithConversion("1");
}
}
return rv;
return rv;
}
NS_IMETHODIMP
nsHTMLOptionElement::SetSelected(PRBool aValue)
{
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = GetPrimaryFrame(fcFrame);
nsresult result = GetPrimaryFrame(fcFrame, PR_FALSE);
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
nsISelectControlFrame* selectFrame = nsnull;
result = fcFrame->QueryInterface(NS_GET_IID(nsISelectControlFrame),(void **) &selectFrame);
@ -542,7 +542,7 @@ nsHTMLOptionElement::SetText(const nsString& aText)
// Options don't have frames - get the select content node
// then call nsGenericHTMLElement::GetPrimaryFrame()
nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormControlFrame)
nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormControlFrame, PRBool aFlushNotifications)
{
nsIDOMHTMLSelectElement* selectElement = nsnull;
nsresult res = GetSelect(selectElement);
@ -552,7 +552,7 @@ nsresult nsHTMLOptionElement::GetPrimaryFrame(nsIFormControlFrame *&aIFormContro
NS_RELEASE(selectElement);
if (NS_OK == gotContent) {
res = nsGenericHTMLElement::GetPrimaryFrame(selectContent, aIFormControlFrame);
res = nsGenericHTMLElement::GetPrimaryFrame(selectContent, aIFormControlFrame, aFlushNotifications);
NS_RELEASE(selectContent);
}
}

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

@ -209,7 +209,7 @@ public:
protected:
NS_IMETHOD GetPresState(nsIPresState** aPresState, nsISupportsArray** aValueArray);
nsGenericHTMLContainerElement mInner;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
nsHTMLOptionCollection* mOptions;
PRBool mIsDoneAddingContent;
@ -1128,6 +1128,9 @@ nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}

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

@ -125,7 +125,7 @@ public:
NS_IMETHOD GetBaseTag(nsIAtom** aResult);
protected:
nsGenericHTMLContainerElement mInner;
nsGenericHTMLContainerFormElement mInner;
nsIForm* mForm;
nsCOMPtr<nsIControllers> mControllers;
nsCOMPtr<nsIXBLBinding> mBinding;
@ -564,6 +564,9 @@ nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm)
}
}
NS_IF_RELEASE(formControl);
mInner.SetForm(mForm);
return result;
}