WebCore:
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Nov 2007 23:13:36 +0000 (23:13 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Nov 2007 23:13:36 +0000 (23:13 +0000)
        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=15806
          <rdar://problem/5561626> ASSERT(element->isRadioButton()) fires destroying form elements

        Test: fast/forms/remove-radio-button-assert.html

        * html/HTMLGenericFormElement.cpp: (WebCore::HTMLGenericFormElement::removeFromForm):
        Added protected function to be used by derived classes that need to do the same sort
        of removal from form that's automatically done by the base class in certain circumstances.
        * html/HTMLGenericFormElement.h: Added removeFromForm.

        * html/HTMLInputElement.cpp: (WebCore::HTMLInputElement::~HTMLInputElement):
        Call removeFromForm here so the element is removed before we destroy the HTMLInputElement
        part of this object. By the time we get to the base class's destructor it's too late.
        The problem is specific to radio buttons so we don't have to worry about other classes
        derived from HTMLGenericFormElement.

LayoutTests:

        Reviewed by Mitz.

        - test for http://bugs.webkit.org/show_bug.cgi?id=15806
          <rdar://problem/5561626> ASSERT(element->isRadioButton()) fires destroying form elements

        * fast/forms/remove-radio-button-assert-expected.txt: Added.
        * fast/forms/remove-radio-button-assert.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27380 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/remove-radio-button-assert-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/remove-radio-button-assert.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/html/HTMLGenericFormElement.cpp
WebCore/html/HTMLGenericFormElement.h
WebCore/html/HTMLInputElement.cpp

index 824e4f11613b290748ed33577f1312d18c3d4413..ab74c7ef736aabbe7bc225a75111cb6fd62e14fa 100644 (file)
@@ -1,3 +1,13 @@
+2007-11-02  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - test for http://bugs.webkit.org/show_bug.cgi?id=15806
+          <rdar://problem/5561626> ASSERT(element->isRadioButton()) fires destroying form elements
+
+        * fast/forms/remove-radio-button-assert-expected.txt: Added.
+        * fast/forms/remove-radio-button-assert.html: Added.
+
 2007-11-02  Darin Adler  <darin@apple.com>
 
         Reviewed by Mitz.
diff --git a/LayoutTests/fast/forms/remove-radio-button-assert-expected.txt b/LayoutTests/fast/forms/remove-radio-button-assert-expected.txt
new file mode 100644 (file)
index 0000000..92f7700
--- /dev/null
@@ -0,0 +1,3 @@
+This tests the code path for destruction of a radio button when it's checked, when the form outlives the radio button, but where the radio button is never explicitly removed from the form.
+
+If you can see this text, the test has run.
diff --git a/LayoutTests/fast/forms/remove-radio-button-assert.html b/LayoutTests/fast/forms/remove-radio-button-assert.html
new file mode 100644 (file)
index 0000000..cbe5919
--- /dev/null
@@ -0,0 +1,10 @@
+<p>This tests the code path for destruction of a radio button when it's checked, when the form outlives the radio button, but where the radio button is never explicitly removed from the form.</p>
+<div id="container"><form id="form"><input type="radio" name="button" checked></form></div>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+var form = document.getElementById("form");
+document.getElementById("container").removeChild(form);
+form.innerHTML="";
+document.getElementById("container").innerHTML="If you can see this text, the test has run.";
+</script>
index 8c02e39b5777d09726d52679d52333a8135696b9..c333c8c20dc6cee8084198970da6e82c39723b9c 100644 (file)
@@ -1,3 +1,23 @@
+2007-11-02  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=15806
+          <rdar://problem/5561626> ASSERT(element->isRadioButton()) fires destroying form elements
+
+        Test: fast/forms/remove-radio-button-assert.html
+
+        * html/HTMLGenericFormElement.cpp: (WebCore::HTMLGenericFormElement::removeFromForm):
+        Added protected function to be used by derived classes that need to do the same sort
+        of removal from form that's automatically done by the base class in certain circumstances.
+        * html/HTMLGenericFormElement.h: Added removeFromForm.
+
+        * html/HTMLInputElement.cpp: (WebCore::HTMLInputElement::~HTMLInputElement):
+        Call removeFromForm here so the element is removed before we destroy the HTMLInputElement
+        part of this object. By the time we get to the base class's destructor it's too late.
+        The problem is specific to radio buttons so we don't have to worry about other classes
+        derived from HTMLGenericFormElement.
+
 2007-11-02  Darin Adler  <darin@apple.com>
 
         Reviewed by Mitz.
index fc5387f8e5160370725492c39904bf152ba1a51e..53e0c9ec3a7711f2e7609df1af81969c90cfbbc8 100644 (file)
@@ -216,6 +216,14 @@ HTMLFormElement* HTMLGenericFormElement::virtualForm() const
     return m_form;
 }
 
+void HTMLGenericFormElement::removeFromForm()
+{
+    if (!m_form)
+        return;
+    m_form->removeFormElement(this);
+    m_form = 0;
+}
+
 HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
     : HTMLGenericFormElement(tagName, doc, f)
 {
index f85cdcb6663810754169da7c5f588207179d9d9a..66d343132d9da572b4c7f2c83f07dcb200a6f1ae 100644 (file)
@@ -92,6 +92,9 @@ public:
 
     void formDestroyed() { m_form = 0; }
 
+protected:
+    void removeFromForm();
+
 private:
     virtual HTMLFormElement* virtualForm() const;
 
index 13834fa91638d1ad0f0c55b3da00a62ca1263623..dca77aa1a02c10cbe511c767df219e7546c6d802 100644 (file)
@@ -144,8 +144,12 @@ HTMLInputElement::~HTMLInputElement()
         document()->unregisterForCacheCallbacks(this);
 
     document()->checkedRadioButtons().removeButton(this);
-    
+
     delete m_imageLoader;
+
+    // Need to remove this from the form while it is still an HTMLInputElement,
+    // so can't wait for the base class's destructor to do it.
+    removeFromForm();
 }
 
 const AtomicString& HTMLInputElement::name() const