diff --git a/content/html/content/public/nsIForm.h b/content/html/content/public/nsIForm.h index 142da196f79..7d81714a9df 100644 --- a/content/html/content/public/nsIForm.h +++ b/content/html/content/public/nsIForm.h @@ -84,6 +84,19 @@ public: */ NS_IMETHOD RemoveElement(nsIFormControl* aElement) = 0; + /** + * Remove an element from the lookup table mainted by the form. + * We can't fold this method into RemoveElement() because when + * RemoveElement() is called it doesn't know if the element is + * removed because the id attribute has changed, or bacause the + * name attribute has changed. + * + * @param aElement the element to remove + * @param aName the name or id of the element to remove + * @return NS_OK if the element was successfully removed. + */ + NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement, const nsString& aName) = 0; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const = 0; }; diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 767f5aafdac..3206ed1bb97 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -3607,8 +3607,14 @@ nsGenericHTMLLeafFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, // Add the control to the hash table nsCOMPtr control; control = do_QueryInterface(mContent); - if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName)) + if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName)) { + nsAutoString tmp; + nsresult rv = GetAttribute(kNameSpaceID_None, aName, tmp); + if (rv == NS_CONTENT_ATTR_HAS_VALUE) + mForm->RemoveElementFromTable(control, tmp); + mForm->AddElementToTable(control, aValue); + } return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify); } diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index 919d07d21d5..59f67d9a4f3 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -189,10 +189,7 @@ nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo) nsHTMLButtonElement::~nsHTMLButtonElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -614,15 +611,32 @@ nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLFieldSetElement.cpp b/content/html/content/src/nsHTMLFieldSetElement.cpp index 83efb13ac5b..c61980ff788 100644 --- a/content/html/content/src/nsHTMLFieldSetElement.cpp +++ b/content/html/content/src/nsHTMLFieldSetElement.cpp @@ -110,10 +110,7 @@ nsHTMLFieldSetElement::nsHTMLFieldSetElement(nsINodeInfo *aNodeInfo) nsHTMLFieldSetElement::~nsHTMLFieldSetElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -187,15 +184,32 @@ nsHTMLFieldSetElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 24978ba6aa0..fb8d0f092a3 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -117,6 +117,7 @@ public: NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const; NS_IMETHOD GetElementCount(PRUint32* aCount) const; NS_IMETHOD RemoveElement(nsIFormControl* aElement); + NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement, const nsString& aName); protected: nsFormControlList* mControls; @@ -145,7 +146,7 @@ public: nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj); nsresult AddElementToTable(nsIFormControl* aChild, const nsString& aName); - nsresult RemoveElementFromTable(nsIFormControl* aChild); + nsresult RemoveElementFromTable(nsIFormControl* aChild, const nsString& aName); #ifdef DEBUG nsresult SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; @@ -470,13 +471,17 @@ nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild, const nsString& aNa NS_IMETHODIMP nsHTMLFormElement::RemoveElement(nsIFormControl* aChild) -{ - PRBool rv = mControls->mElements.RemoveElement(aChild); - if (rv) { - mControls->RemoveElementFromTable(aChild); - // WEAK - don't release - } - return rv; +{ + mControls->mElements.RemoveElement(aChild); + + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::RemoveElementFromTable(nsIFormControl* aElement, + const nsString& aName) +{ + return mControls->RemoveElementFromTable(aElement, aName); } NS_IMETHODIMP @@ -607,7 +612,36 @@ nsHTMLFormElement::Resolve(JSContext *aContext, JSObject *aObj, jsval aID) return PR_FALSE; } - if (nsnull != obj) { + if (!obj && mInner.mDocument) { + nsCOMPtr htmlDoc = do_QueryInterface(mInner.mDocument); + if (htmlDoc) { + nsCOMPtr list; + result = htmlDoc->GetElementsByName(name, getter_AddRefs(list)); + if (NS_FAILED(result)) { + return PR_FALSE; + } + if (list) { + PRUint32 count; + list->GetLength(&count); + if (count > 0) { + nsCOMPtr node; + result = list->Item(0, getter_AddRefs(node)); + if (NS_FAILED(result)) { + return PR_FALSE; + } + if (node) { + nsCOMPtr owner = do_QueryInterface(node); + result = owner->GetScriptObject(scriptContext, (void**)&obj); + if (NS_FAILED(result)) { + return PR_FALSE; + } + } + } + } + } + } + + if (obj) { JSObject* myObj; result = mInner.GetScriptObject(scriptContext, (void**)&myObj); ret = ::JS_DefineProperty(aContext, myObj, @@ -690,14 +724,10 @@ nsFormControlList::SetForm(nsIDOMHTMLFormElement* aForm) void nsFormControlList::Clear() { - PRUint32 numElements = mElements.Count(); - for (PRUint32 i = 0; i < numElements; i++) { - nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i); - if (mLookupTable) { - RemoveElementFromTable(elem); - } - // WEAK, don't release - } + mElements.Clear(); + + if (mLookupTable) + mLookupTable->Reset(); } NS_IMPL_ISUPPORTS3(nsFormControlList, nsIDOMHTMLCollection, nsIDOMHTMLFormControlList, nsIScriptObjectOwner) @@ -985,15 +1015,13 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, const nsString& aNa } nsresult -nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild) +nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild, + const nsString& aName) { nsAutoString name; nsCOMPtr content = do_QueryInterface(aChild); - 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); + if (mLookupTable && content) { + nsStringKey key(aName); nsCOMPtr supports; supports = dont_AddRef((nsISupports *)mLookupTable->Get(&key)); diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 908c7b2f0e4..8a0ed07240e 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -237,10 +237,7 @@ nsHTMLInputElement::nsHTMLInputElement(nsINodeInfo *aNodeInfo) nsHTMLInputElement::~nsHTMLInputElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -1179,15 +1176,32 @@ nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLLabelElement.cpp b/content/html/content/src/nsHTMLLabelElement.cpp index 4ab958b810d..798db1953ad 100644 --- a/content/html/content/src/nsHTMLLabelElement.cpp +++ b/content/html/content/src/nsHTMLLabelElement.cpp @@ -191,10 +191,7 @@ nsHTMLLabelElement::nsHTMLLabelElement(nsINodeInfo *aNodeInfo) nsHTMLLabelElement::~nsHTMLLabelElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -268,15 +265,32 @@ nsHTMLLabelElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLLegendElement.cpp b/content/html/content/src/nsHTMLLegendElement.cpp index 269c45c715c..f005725713b 100644 --- a/content/html/content/src/nsHTMLLegendElement.cpp +++ b/content/html/content/src/nsHTMLLegendElement.cpp @@ -112,10 +112,7 @@ nsHTMLLegendElement::nsHTMLLegendElement(nsINodeInfo *aNodeInfo) nsHTMLLegendElement::~nsHTMLLegendElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } NS_IMPL_ADDREF(nsHTMLLegendElement) @@ -187,15 +184,32 @@ nsHTMLLegendElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(NS_GET_IID(nsIFormControl), getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLSelectElement.cpp b/content/html/content/src/nsHTMLSelectElement.cpp index 738fa1c7fd5..b5d69e67741 100644 --- a/content/html/content/src/nsHTMLSelectElement.cpp +++ b/content/html/content/src/nsHTMLSelectElement.cpp @@ -248,10 +248,7 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsINodeInfo *aNodeInfo) nsHTMLSelectElement::~nsHTMLSelectElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); if (nsnull != mOptions) { mOptions->Clear(); mOptions->DropReference(); @@ -1151,15 +1148,32 @@ nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp index d678072d12e..80c761127e3 100644 --- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -151,10 +151,7 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo) nsHTMLTextAreaElement::~nsHTMLTextAreaElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } NS_IMPL_ADDREF(nsHTMLTextAreaElement) @@ -555,15 +552,32 @@ nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/public/nsIForm.h b/layout/html/content/public/nsIForm.h index 142da196f79..7d81714a9df 100644 --- a/layout/html/content/public/nsIForm.h +++ b/layout/html/content/public/nsIForm.h @@ -84,6 +84,19 @@ public: */ NS_IMETHOD RemoveElement(nsIFormControl* aElement) = 0; + /** + * Remove an element from the lookup table mainted by the form. + * We can't fold this method into RemoveElement() because when + * RemoveElement() is called it doesn't know if the element is + * removed because the id attribute has changed, or bacause the + * name attribute has changed. + * + * @param aElement the element to remove + * @param aName the name or id of the element to remove + * @return NS_OK if the element was successfully removed. + */ + NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement, const nsString& aName) = 0; + NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const = 0; }; diff --git a/layout/html/content/src/nsGenericHTMLElement.cpp b/layout/html/content/src/nsGenericHTMLElement.cpp index 767f5aafdac..3206ed1bb97 100644 --- a/layout/html/content/src/nsGenericHTMLElement.cpp +++ b/layout/html/content/src/nsGenericHTMLElement.cpp @@ -3607,8 +3607,14 @@ nsGenericHTMLLeafFormElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, // Add the control to the hash table nsCOMPtr control; control = do_QueryInterface(mContent); - if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName)) + if (mForm && (nsHTMLAtoms::name == aName || nsHTMLAtoms::id == aName)) { + nsAutoString tmp; + nsresult rv = GetAttribute(kNameSpaceID_None, aName, tmp); + if (rv == NS_CONTENT_ATTR_HAS_VALUE) + mForm->RemoveElementFromTable(control, tmp); + mForm->AddElementToTable(control, aValue); + } return nsGenericHTMLElement::SetAttribute(aNameSpaceID, aName, aValue, aNotify); } diff --git a/layout/html/content/src/nsHTMLButtonElement.cpp b/layout/html/content/src/nsHTMLButtonElement.cpp index 919d07d21d5..59f67d9a4f3 100644 --- a/layout/html/content/src/nsHTMLButtonElement.cpp +++ b/layout/html/content/src/nsHTMLButtonElement.cpp @@ -189,10 +189,7 @@ nsHTMLButtonElement::nsHTMLButtonElement(nsINodeInfo *aNodeInfo) nsHTMLButtonElement::~nsHTMLButtonElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -614,15 +611,32 @@ nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLFieldSetElement.cpp b/layout/html/content/src/nsHTMLFieldSetElement.cpp index 83efb13ac5b..c61980ff788 100644 --- a/layout/html/content/src/nsHTMLFieldSetElement.cpp +++ b/layout/html/content/src/nsHTMLFieldSetElement.cpp @@ -110,10 +110,7 @@ nsHTMLFieldSetElement::nsHTMLFieldSetElement(nsINodeInfo *aNodeInfo) nsHTMLFieldSetElement::~nsHTMLFieldSetElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -187,15 +184,32 @@ nsHTMLFieldSetElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLFormElement.cpp b/layout/html/content/src/nsHTMLFormElement.cpp index 24978ba6aa0..fb8d0f092a3 100644 --- a/layout/html/content/src/nsHTMLFormElement.cpp +++ b/layout/html/content/src/nsHTMLFormElement.cpp @@ -117,6 +117,7 @@ public: NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const; NS_IMETHOD GetElementCount(PRUint32* aCount) const; NS_IMETHOD RemoveElement(nsIFormControl* aElement); + NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement, const nsString& aName); protected: nsFormControlList* mControls; @@ -145,7 +146,7 @@ public: nsresult GetNamedObject(JSContext* aContext, jsval aID, JSObject** aObj); nsresult AddElementToTable(nsIFormControl* aChild, const nsString& aName); - nsresult RemoveElementFromTable(nsIFormControl* aChild); + nsresult RemoveElementFromTable(nsIFormControl* aChild, const nsString& aName); #ifdef DEBUG nsresult SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const; @@ -470,13 +471,17 @@ nsHTMLFormElement::AddElementToTable(nsIFormControl* aChild, const nsString& aNa NS_IMETHODIMP nsHTMLFormElement::RemoveElement(nsIFormControl* aChild) -{ - PRBool rv = mControls->mElements.RemoveElement(aChild); - if (rv) { - mControls->RemoveElementFromTable(aChild); - // WEAK - don't release - } - return rv; +{ + mControls->mElements.RemoveElement(aChild); + + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::RemoveElementFromTable(nsIFormControl* aElement, + const nsString& aName) +{ + return mControls->RemoveElementFromTable(aElement, aName); } NS_IMETHODIMP @@ -607,7 +612,36 @@ nsHTMLFormElement::Resolve(JSContext *aContext, JSObject *aObj, jsval aID) return PR_FALSE; } - if (nsnull != obj) { + if (!obj && mInner.mDocument) { + nsCOMPtr htmlDoc = do_QueryInterface(mInner.mDocument); + if (htmlDoc) { + nsCOMPtr list; + result = htmlDoc->GetElementsByName(name, getter_AddRefs(list)); + if (NS_FAILED(result)) { + return PR_FALSE; + } + if (list) { + PRUint32 count; + list->GetLength(&count); + if (count > 0) { + nsCOMPtr node; + result = list->Item(0, getter_AddRefs(node)); + if (NS_FAILED(result)) { + return PR_FALSE; + } + if (node) { + nsCOMPtr owner = do_QueryInterface(node); + result = owner->GetScriptObject(scriptContext, (void**)&obj); + if (NS_FAILED(result)) { + return PR_FALSE; + } + } + } + } + } + } + + if (obj) { JSObject* myObj; result = mInner.GetScriptObject(scriptContext, (void**)&myObj); ret = ::JS_DefineProperty(aContext, myObj, @@ -690,14 +724,10 @@ nsFormControlList::SetForm(nsIDOMHTMLFormElement* aForm) void nsFormControlList::Clear() { - PRUint32 numElements = mElements.Count(); - for (PRUint32 i = 0; i < numElements; i++) { - nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i); - if (mLookupTable) { - RemoveElementFromTable(elem); - } - // WEAK, don't release - } + mElements.Clear(); + + if (mLookupTable) + mLookupTable->Reset(); } NS_IMPL_ISUPPORTS3(nsFormControlList, nsIDOMHTMLCollection, nsIDOMHTMLFormControlList, nsIScriptObjectOwner) @@ -985,15 +1015,13 @@ nsFormControlList::AddElementToTable(nsIFormControl* aChild, const nsString& aNa } nsresult -nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild) +nsFormControlList::RemoveElementFromTable(nsIFormControl* aChild, + const nsString& aName) { nsAutoString name; nsCOMPtr content = do_QueryInterface(aChild); - 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); + if (mLookupTable && content) { + nsStringKey key(aName); nsCOMPtr supports; supports = dont_AddRef((nsISupports *)mLookupTable->Get(&key)); diff --git a/layout/html/content/src/nsHTMLInputElement.cpp b/layout/html/content/src/nsHTMLInputElement.cpp index 908c7b2f0e4..8a0ed07240e 100644 --- a/layout/html/content/src/nsHTMLInputElement.cpp +++ b/layout/html/content/src/nsHTMLInputElement.cpp @@ -237,10 +237,7 @@ nsHTMLInputElement::nsHTMLInputElement(nsINodeInfo *aNodeInfo) nsHTMLInputElement::~nsHTMLInputElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -1179,15 +1176,32 @@ nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLLabelElement.cpp b/layout/html/content/src/nsHTMLLabelElement.cpp index 4ab958b810d..798db1953ad 100644 --- a/layout/html/content/src/nsHTMLLabelElement.cpp +++ b/layout/html/content/src/nsHTMLLabelElement.cpp @@ -191,10 +191,7 @@ nsHTMLLabelElement::nsHTMLLabelElement(nsINodeInfo *aNodeInfo) nsHTMLLabelElement::~nsHTMLLabelElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } // nsISupports @@ -268,15 +265,32 @@ nsHTMLLabelElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLLegendElement.cpp b/layout/html/content/src/nsHTMLLegendElement.cpp index 269c45c715c..f005725713b 100644 --- a/layout/html/content/src/nsHTMLLegendElement.cpp +++ b/layout/html/content/src/nsHTMLLegendElement.cpp @@ -112,10 +112,7 @@ nsHTMLLegendElement::nsHTMLLegendElement(nsINodeInfo *aNodeInfo) nsHTMLLegendElement::~nsHTMLLegendElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } NS_IMPL_ADDREF(nsHTMLLegendElement) @@ -187,15 +184,32 @@ nsHTMLLegendElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(NS_GET_IID(nsIFormControl), getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLSelectElement.cpp b/layout/html/content/src/nsHTMLSelectElement.cpp index 738fa1c7fd5..b5d69e67741 100644 --- a/layout/html/content/src/nsHTMLSelectElement.cpp +++ b/layout/html/content/src/nsHTMLSelectElement.cpp @@ -248,10 +248,7 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsINodeInfo *aNodeInfo) nsHTMLSelectElement::~nsHTMLSelectElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); if (nsnull != mOptions) { mOptions->Clear(); mOptions->DropReference(); @@ -1151,15 +1148,32 @@ nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else { diff --git a/layout/html/content/src/nsHTMLTextAreaElement.cpp b/layout/html/content/src/nsHTMLTextAreaElement.cpp index d678072d12e..80c761127e3 100644 --- a/layout/html/content/src/nsHTMLTextAreaElement.cpp +++ b/layout/html/content/src/nsHTMLTextAreaElement.cpp @@ -151,10 +151,7 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo) nsHTMLTextAreaElement::~nsHTMLTextAreaElement() { // Null out form's pointer to us - no ref counting here! - if (mForm) { - mForm->RemoveElement(this); - mForm = nsnull; - } + SetForm(nsnull); } NS_IMPL_ADDREF(nsHTMLTextAreaElement) @@ -555,15 +552,32 @@ nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm) nsresult result = QueryInterface(kIFormControlIID, getter_AddRefs(formControl)); if (NS_FAILED(result)) formControl = nsnull; - if (mForm && formControl) + nsAutoString nameVal, idVal; + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::name, nameVal); + mInner.GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, idVal); + + if (mForm && formControl) { mForm->RemoveElement(formControl); + if (nameVal.Length()) + mForm->RemoveElementFromTable(this, nameVal); + + if (idVal.Length()) + mForm->RemoveElementFromTable(this, idVal); + } + if (aForm) { nsCOMPtr theForm = do_QueryInterface(aForm, &result); mForm = theForm; // Even if we fail, update mForm (nsnull in failure) if ((NS_OK == result) && theForm) { if (formControl) { theForm->AddElement(formControl); + + if (nameVal.Length()) + theForm->AddElementToTable(this, nameVal); + + if (idVal.Length()) + theForm->AddElementToTable(this, idVal); } } } else {