Diff
Modified: trunk/LayoutTests/ChangeLog (104667 => 104668)
--- trunk/LayoutTests/ChangeLog 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/LayoutTests/ChangeLog 2012-01-11 05:03:23 UTC (rev 104668)
@@ -1,3 +1,13 @@
+2012-01-04 Kent Tamura <tk...@chromium.org>
+
+ A radio button not in a Document should not join a radio button group
+ https://bugs.webkit.org/show_bug.cgi?id=45719
+
+ Reviewed by Darin Adler.
+
+ * fast/forms/radio/radio-group-expected.txt: Added.
+ * fast/forms/radio/radio-group.html: Added.
+
2012-01-10 João Paulo Rechi Vita <jprv...@openbossa.org>
[Qt] Unskiping more passing tests
Added: trunk/LayoutTests/fast/forms/radio/radio-group-expected.txt (0 => 104668)
--- trunk/LayoutTests/fast/forms/radio/radio-group-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/forms/radio/radio-group-expected.txt 2012-01-11 05:03:23 UTC (rev 104668)
@@ -0,0 +1,63 @@
+Various tests about radio button group.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Changing the name attribute of a radio button:
+PASS $("radio1-1").checked is true
+PASS $("radio1-2").checked is true
+PASS $("radio1-1").checked is false
+PASS $("radio1-2").checked is true
+
+Changing the type of an input element to radio:
+PASS $("radio1-1").checked is true
+PASS $("radio1-1").checked is false
+PASS $("text1-2").checked is true
+
+Moving a checked radio button to another form:
+PASS $("outside").checked is true
+PASS $("inside").checked is true
+PASS $("inside2").checked is true
+PASS $("outside").checked is true
+PASS $("inside").checked is false
+PASS $("inside2").checked is true
+When a radio in a form is removed, it should not affect Document-level groups:
+PASS $("outside").checked is true
+
+Removing an ancestor owner form:
+PASS $("radio0-1").checked is true
+
+Changing form attribute
+PASS $("radio1-1").checked is true
+PASS $("radio1-2").checked is false
+PASS $("radio1-3").checked is true
+Removing a non-ancestor owner form:
+PASS $("radio1-3").checked is true
+PASS $("radio1-4").checked is true
+(The following test depends on gc(). It might fail on a real browser.)
+PASS $("radio1-1").checked is false
+PASS $("radio1-3").checked is true
+
+Adding a radio button to an orphan tree:
+PASS orphanDiv.getElementsByTagName("input")[0].checked is true
+PASS orphanDiv.getElementsByTagName("input")[1].checked is true
+Adding the orphan tree to a document:
+PASS orphanDiv.getElementsByTagName("input")[0].checked is false
+PASS orphanDiv.getElementsByTagName("input")[1].checked is true
+Parsing an orphan form:
+PASS orphanDiv.getElementsByTagName("input")[0].checked is true
+PASS orphanDiv.getElementsByTagName("input")[1].checked is true
+
+Moving a radio button to another Document:
+PASS doc.getElementById("radio4-2").checked is false
+PASS doc.getElementById("radio4-1").checked is true
+PASS doc.getElementById("radio4-1").checked is true
+
+Cloning a radio button:
+PASS original.checked is true
+PASS clonedRadio.checked is true
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Property changes on: trunk/LayoutTests/fast/forms/radio/radio-group-expected.txt
___________________________________________________________________
Added: svn:eol-style
Added: trunk/LayoutTests/fast/forms/radio/radio-group.html (0 => 104668)
--- trunk/LayoutTests/fast/forms/radio/radio-group.html (rev 0)
+++ trunk/LayoutTests/fast/forms/radio/radio-group.html 2012-01-11 05:03:23 UTC (rev 104668)
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+
+<div id="parent"></div>
+
+<script>
+description('Various tests about radio button group.');
+
+const Checked = true;
+const Unchecked = false;
+
+function createRadio(name, checked, id) {
+ var input = document.createElement('input');
+ input.type = 'radio';
+ input.name = name;
+ input.checked = !!checked;
+ input.id = id;
+ return input;
+}
+
+function $(id) {
+ return document.getElementById(id);
+}
+
+var parent = $('parent');
+
+debug('Changing the name attribute of a radio button:');
+parent.innerHTML = '<form>' +
+ '<input type=radio name=name1 checked id=radio1-1>' +
+ '<input type=radio name=name2 checked id=radio1-2>' +
+ '</form>';
+shouldBeTrue('$("radio1-1").checked');
+shouldBeTrue('$("radio1-2").checked');
+$('radio1-2').name = 'name1';
+shouldBeFalse('$("radio1-1").checked');
+shouldBeTrue('$("radio1-2").checked');
+
+debug('');
+debug('Changing the type of an input element to radio:');
+parent.innerHTML = '<form>' +
+ '<input type=radio name=name1 checked id=radio1-1>' +
+ '<input type=text name=name1 checked id=text1-2>' +
+ '</form>';
+shouldBeTrue('$("radio1-1").checked');
+$('text1-2').type = 'radio';
+shouldBeFalse('$("radio1-1").checked');
+shouldBeTrue('$("text1-2").checked');
+
+debug('');
+debug('Moving a checked radio button to another form:');
+parent.innerHTML = '<input type="radio" name="name1" checked id="outside">' +
+ '<form id="form1">' +
+ '<input type="radio" name="name1" checked id="inside">' +
+ '</form>' +
+ '<form id="form2">' +
+ '<input type="radio" name="name1" checked id="inside2">' +
+ '</form>'
+shouldBeTrue('$("outside").checked');
+shouldBeTrue('$("inside").checked');
+shouldBeTrue('$("inside2").checked');
+$('form1').appendChild($('inside2'));
+shouldBeTrue('$("outside").checked');
+shouldBeFalse('$("inside").checked');
+shouldBeTrue('$("inside2").checked');
+debug('When a radio in a form is removed, it should not affect Document-level groups:');
+parent.removeChild($('form1'));
+shouldBeTrue('$("outside").checked');
+
+debug('');
+debug('Removing an ancestor owner form:');
+parent.innerHTML = '<input type=radio name=name0 checked id=radio0-1>' +
+ '<form id=form1><input type=radio name=name0 checked id=radio0-2></form>';
+parent.removeChild($('form1'));
+gc();
+shouldBeTrue('$("radio0-1").checked');
+
+debug('');
+debug('Changing form attribute');
+parent.innerHTML = '<input type=radio name=name1 checked id=radio1-1>' +
+ '<form id=form1><input type=radio name=name1 checked id=radio1-2></form>' +
+ '<form id=form2><input type=radio name=name1 checked id=radio1-3></form>';
+$('radio1-3').setAttribute('form', 'form1');
+shouldBeTrue('$("radio1-1").checked');
+shouldBeFalse('$("radio1-2").checked');
+shouldBeTrue('$("radio1-3").checked');
+
+debug('Removing a non-ancestor owner form:');
+$('form2').appendChild(createRadio('name1', Checked, 'radio1-4'));
+shouldBeTrue('$("radio1-3").checked');
+// If there is no elements with ID specified by form= attribute, the form
+// control is not associated to any forms.
+parent.removeChild($('form1'));
+// FIXME: We need to call gc() twice on Apple Mac.
+gc();
+gc();
+shouldBeTrue('$("radio1-4").checked');
+debug('(The following test depends on gc(). It might fail on a real browser.)');
+shouldBeFalse('$("radio1-1").checked');
+shouldBeTrue('$("radio1-3").checked');
+
+debug('');
+debug('Adding a radio button to an orphan tree:');
+var orphanDiv = document.createElement('div');
+orphanDiv.appendChild(createRadio('name2', Checked, ''));
+orphanDiv.appendChild(createRadio('name2', Checked, ''));
+shouldBeTrue('orphanDiv.getElementsByTagName("input")[0].checked');
+shouldBeTrue('orphanDiv.getElementsByTagName("input")[1].checked');
+debug('Adding the orphan tree to a document:');
+document.body.appendChild(orphanDiv);
+shouldBeFalse('orphanDiv.getElementsByTagName("input")[0].checked');
+shouldBeTrue('orphanDiv.getElementsByTagName("input")[1].checked');
+
+debug('Parsing an orphan form:');
+document.body.removeChild(orphanDiv);
+orphanDiv.innerHTML = '<form><input type=radio name=name3 checked><input type=radio name=name3 checked></form>';
+shouldBeTrue('orphanDiv.getElementsByTagName("input")[0].checked');
+shouldBeTrue('orphanDiv.getElementsByTagName("input")[1].checked');
+
+debug('');
+debug('Moving a radio button to another Document:');
+parent.innerHTML = '<input type=radio name=name4 checked id=radio4-1>';
+var doc = document.implementation.createHTMLDocument();
+doc.body.innerHTML = '<input type=radio name=name4 checked id=radio4-2>';
+doc.body.appendChild(doc.adoptNode($('radio4-1')));
+shouldBeFalse('doc.getElementById("radio4-2").checked');
+shouldBeTrue('doc.getElementById("radio4-1").checked');
+parent.appendChild(createRadio('name4', Checked, ''));
+shouldBeTrue('doc.getElementById("radio4-1").checked');
+
+debug('');
+debug('Cloning a radio button:');
+var original = createRadio('name5', Checked, '');
+parent.innerHTML = '';
+parent.appendChild(original);
+var clonedRadio = original.cloneNode(true);
+shouldBeTrue('original.checked');
+shouldBeTrue('clonedRadio.checked');
+
+parent.innerHTML = '';
+debug('');
+</script>
+
+<script src=""
+</body>
Property changes on: trunk/LayoutTests/fast/forms/radio/radio-group.html
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/Source/WebCore/ChangeLog (104667 => 104668)
--- trunk/Source/WebCore/ChangeLog 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/ChangeLog 2012-01-11 05:03:23 UTC (rev 104668)
@@ -1,3 +1,86 @@
+2012-01-04 Kent Tamura <tk...@chromium.org>
+
+ A radio button not in a document should not join a radio button group
+ https://bugs.webkit.org/show_bug.cgi?id=45719
+
+ Reviewed by Darin Adler.
+
+ As per the standard and other browser behaviors, we should not add a
+ radio button not in a document to a radio button group.
+
+ So, CheckedRadioButton member functions should be called in
+ insertedIntoDocument() and removedFromDocument(), and they should do
+ nothing if the specified radio button is not in a document.
+
+ This change also fixes a bug that form owner change by 'form' attribute
+ didn't update radio button groups correctly.
+
+ Test: fast/forms/radio/radio-group.html
+
+ * dom/CheckedRadioButtons.cpp:
+ (WebCore::shouldMakeRadioGroup): A helper function to check <input> state.
+ (WebCore::CheckedRadioButtons::addButton):
+ - Change the argument type: HTMLFormControlElement* -> HTMLInputElement*.
+ - Use shouldMakeRadioGroup().
+ (WebCore::CheckedRadioButtons::removeButton): ditto.
+ * dom/CheckedRadioButtons.h:
+ Change the argument types of addButton() and removeButton():
+ HTMLFormControlElement* -> HTMLInputElement*.
+ * html/FormAssociatedElement.cpp:
+ Do not update m_form except in setForm() and formWillBeDestroyed().
+ This helps us to call registerFormElement() and removeFromElement()
+ correctly, and call willChangeForm()/didChangeForm() hooks correctly.
+ (WebCore::FormAssociatedElement::FormAssociatedElement):
+ (WebCore::FormAssociatedElement::~FormAssociatedElement):
+ (WebCore::FormAssociatedElement::insertedIntoTree):
+ (WebCore::FormAssociatedElement::removedFromTree):
+ (WebCore::FormAssociatedElement::setForm):
+ (WebCore::FormAssociatedElement::willChangeForm):
+ This virtual function is called before the owner form is updated.
+ (WebCore::FormAssociatedElement::didChangeForm):
+ This virtual function is called after the owner form was updated.
+ (WebCore::FormAssociatedElement::formWillBeDestroyed):
+ - Renamaed from formDestroyed()
+ - Add calls to willChangeForm() and didChangeForm().
+ (WebCore::FormAssociatedElement::resetFormOwner): Use setForm().
+ (WebCore::FormAssociatedElement::formAttributeChanged): ditto.
+ * html/FormAssociatedElement.h:
+ * html/HTMLFormControlElement.cpp:
+ (WebCore::HTMLFormControlElement::HTMLFormControlElement): Use setForm().
+ (WebCore::HTMLFormControlElement::~HTMLFormControlElement):
+ removeFormElement() is not needed. ~FormAssociatedElement() treats it.
+ (WebCore::HTMLFormControlElement::parseMappedAttribute):
+ No need to handle CheckedRadioButtons here. It is handled by HTMLInputElement.
+ (WebCore::HTMLFormControlElement::insertedIntoTree): ditto.
+ * html/HTMLFormElement.cpp:
+ (WebCore::HTMLFormElement::~HTMLFormElement):
+ Rename formDestroyed() with willDestroyForm().
+ (WebCore::HTMLFormElement::registerFormElement):
+ We don't need to handle radio button groups here.
+ (WebCore::HTMLFormElement::removeFormElement): ditto.
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::~HTMLInputElement):
+ Calls setForm(0) so that it calls correct virtual functions of
+ HTMLInputElement.
+ (WebCore::HTMLInputElement::updateCheckedRadioButtons):
+ Checking attached() was wrong.
+ (WebCore::HTMLInputElement::willChangeForm):
+ Remove this radio button from a radio button group for the old form.
+ (WebCore::HTMLInputElement::didChangeForm):
+ Add this radio button to a radio button group for the new form.
+ (WebCore::HTMLInputElement::insertedIntoDocument):
+ Add CheckedRadioButtons::addButton() call.
+ (WebCore::HTMLInputElement::removedFromDocument):
+ Add CheckedRadioButtons::removeButton() call.
+ (WebCore::HTMLInputElement::didMoveToNewDocument):
+ We don't need to handle CheckedRadioButton() here because
+ removedFromDocument() handles it.
+ * html/HTMLInputElement.h:
+ * html/HTMLObjectElement.cpp:
+ (WebCore::HTMLObjectElement::HTMLObjectElement): Use setForm().
+ (WebCore::HTMLObjectElement::~HTMLObjectElement):
+ removeFormElement() is not needed. ~FormAssociatedElement() treats it.
+
2012-01-10 Kentaro Hara <hara...@chromium.org>
Remove redundant code from DOMWindowSQLDatabase.cpp
Modified: trunk/Source/WebCore/dom/CheckedRadioButtons.cpp (104667 => 104668)
--- trunk/Source/WebCore/dom/CheckedRadioButtons.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/dom/CheckedRadioButtons.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -25,34 +25,32 @@
namespace WebCore {
-void CheckedRadioButtons::addButton(HTMLFormControlElement* element)
+static inline bool shouldMakeRadioGroup(HTMLInputElement* element)
{
- // We only want to add radio buttons.
- if (!element->isRadioButton())
- return;
+ return element->isRadioButton() && !element->name().isEmpty() && element->inDocument();
+}
- // Without a name, there is no group.
- if (element->name().isEmpty())
+void CheckedRadioButtons::addButton(HTMLInputElement* element)
+{
+ if (!shouldMakeRadioGroup(element))
return;
- HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
-
// We only track checked buttons.
- if (!inputElement->checked())
+ if (!element->checked())
return;
if (!m_nameToCheckedRadioButtonMap)
m_nameToCheckedRadioButtonMap = adoptPtr(new NameToInputMap);
- pair<NameToInputMap::iterator, bool> result = m_nameToCheckedRadioButtonMap->add(element->name().impl(), inputElement);
+ pair<NameToInputMap::iterator, bool> result = m_nameToCheckedRadioButtonMap->add(element->name().impl(), element);
if (result.second)
return;
HTMLInputElement* oldCheckedButton = result.first->second;
- if (oldCheckedButton == inputElement)
+ if (oldCheckedButton == element)
return;
- result.first->second = inputElement;
+ result.first->second = element;
oldCheckedButton->setChecked(false);
}
@@ -66,7 +64,7 @@
return m_nameToCheckedRadioButtonMap->get(name.impl());
}
-void CheckedRadioButtons::removeButton(HTMLFormControlElement* element)
+void CheckedRadioButtons::removeButton(HTMLInputElement* element)
{
if (element->name().isEmpty() || !m_nameToCheckedRadioButtonMap)
return;
@@ -77,9 +75,7 @@
if (it == m_nameToCheckedRadioButtonMap->end() || it->second != element)
return;
- HTMLInputElement* inputElement = element->toInputElement();
- ASSERT_UNUSED(inputElement, inputElement);
- ASSERT(inputElement->shouldAppearChecked());
+ ASSERT(element->shouldAppearChecked());
ASSERT(element->isRadioButton());
m_nameToCheckedRadioButtonMap->remove(it);
Modified: trunk/Source/WebCore/dom/CheckedRadioButtons.h (104667 => 104668)
--- trunk/Source/WebCore/dom/CheckedRadioButtons.h 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/dom/CheckedRadioButtons.h 2012-01-11 05:03:23 UTC (rev 104668)
@@ -27,13 +27,12 @@
namespace WebCore {
-class HTMLFormControlElement;
class HTMLInputElement;
class CheckedRadioButtons {
public:
- void addButton(HTMLFormControlElement*);
- void removeButton(HTMLFormControlElement*);
+ void addButton(HTMLInputElement*);
+ void removeButton(HTMLInputElement*);
HTMLInputElement* checkedButtonForGroup(const AtomicString& groupName) const;
private:
Modified: trunk/Source/WebCore/html/FormAssociatedElement.cpp (104667 => 104668)
--- trunk/Source/WebCore/html/FormAssociatedElement.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/FormAssociatedElement.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -35,13 +35,14 @@
using namespace HTMLNames;
-FormAssociatedElement::FormAssociatedElement(HTMLFormElement* form)
- : m_form(form)
+FormAssociatedElement::FormAssociatedElement()
+ : m_form(0)
{
}
FormAssociatedElement::~FormAssociatedElement()
{
+ setForm(0);
}
ValidityState* FormAssociatedElement::validity()
@@ -76,19 +77,13 @@
void FormAssociatedElement::insertedIntoTree()
{
HTMLElement* element = toHTMLElement(this);
- if (element->fastHasAttribute(formAttr)) {
- // Resets the form owner at first to make sure the element don't
- // associate any form elements when there is no element which has
- // the given ID.
- if (m_form) {
- m_form->removeFormElement(this);
- m_form = 0;
- }
- Element* formElement = element->treeScope()->getElementById(element->fastGetAttribute(formAttr));
- if (formElement && formElement->hasTagName(formTag)) {
- m_form = static_cast<HTMLFormElement*>(formElement);
- m_form->registerFormElement(this);
- }
+ const AtomicString& formId = element->fastGetAttribute(formAttr);
+ if (!formId.isNull()) {
+ HTMLFormElement* newForm = 0;
+ Element* newFormCandidate = element->treeScope()->getElementById(formId);
+ if (newFormCandidate && newFormCandidate->hasTagName(formTag))
+ newForm = static_cast<HTMLFormElement*>(newFormCandidate);
+ setForm(newForm);
return;
}
if (!m_form) {
@@ -96,9 +91,7 @@
// _javascript_ and inserted inside a form. In the case of the parser
// setting a form, we will already have a non-null value for m_form,
// and so we don't need to do anything.
- m_form = element->findFormAncestor();
- if (m_form)
- m_form->registerFormElement(this);
+ setForm(element->findFormAncestor());
}
}
@@ -117,15 +110,38 @@
// If the form and element are both in the same tree, preserve the connection to the form.
// Otherwise, null out our form and remove ourselves from the form's list of elements.
if (m_form && findRoot(element) != findRoot(m_form))
- removeFromForm();
+ setForm(0);
}
-void FormAssociatedElement::removeFromForm()
+void FormAssociatedElement::setForm(HTMLFormElement* newForm)
{
+ if (m_form == newForm)
+ return;
+ willChangeForm();
+ if (m_form)
+ m_form->removeFormElement(this);
+ m_form = newForm;
+ if (m_form)
+ m_form->registerFormElement(this);
+ didChangeForm();
+}
+
+void FormAssociatedElement::willChangeForm()
+{
+}
+
+void FormAssociatedElement::didChangeForm()
+{
+}
+
+void FormAssociatedElement::formWillBeDestroyed()
+{
+ ASSERT(m_form);
if (!m_form)
return;
- m_form->removeFormElement(this);
+ willChangeForm();
m_form = 0;
+ didChangeForm();
}
void FormAssociatedElement::resetFormOwner()
@@ -135,9 +151,8 @@
if (m_form) {
if (formId.isNull())
return;
- m_form->removeFormElement(this);
}
- m_form = 0;
+ HTMLFormElement* newForm = 0;
if (!formId.isNull() && element->inDocument()) {
// The HTML5 spec says that the element should be associated with
// the first element in the document to have an ID that equal to
@@ -145,11 +160,10 @@
// treeScope()->getElementById() over the given element.
Element* firstElement = element->treeScope()->getElementById(formId);
if (firstElement && firstElement->hasTagName(formTag))
- m_form = static_cast<HTMLFormElement*>(firstElement);
+ newForm = static_cast<HTMLFormElement*>(firstElement);
} else
- m_form = element->findFormAncestor();
- if (m_form)
- m_form->registerFormElement(this);
+ newForm = element->findFormAncestor();
+ setForm(newForm);
}
void FormAssociatedElement::formAttributeChanged()
@@ -157,11 +171,7 @@
HTMLElement* element = toHTMLElement(this);
if (!element->fastHasAttribute(formAttr)) {
// The form attribute removed. We need to reset form owner here.
- if (m_form)
- m_form->removeFormElement(this);
- m_form = element->findFormAncestor();
- if (m_form)
- form()->registerFormElement(this);
+ setForm(element->findFormAncestor());
element->document()->unregisterFormElementWithFormAttribute(this);
} else
resetFormOwner();
Modified: trunk/Source/WebCore/html/FormAssociatedElement.h (104667 => 104668)
--- trunk/Source/WebCore/html/FormAssociatedElement.h 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/FormAssociatedElement.h 2012-01-11 05:03:23 UTC (rev 104668)
@@ -53,12 +53,12 @@
// Return true for a successful control (see HTML4-17.13.2).
virtual bool appendFormData(FormDataList&, bool) { return false; }
- virtual void formDestroyed() { m_form = 0; }
+ void formWillBeDestroyed();
void resetFormOwner();
protected:
- FormAssociatedElement(HTMLFormElement*);
+ FormAssociatedElement();
void insertedIntoTree();
void removedFromTree();
@@ -66,10 +66,15 @@
void removedFromDocument();
void didMoveToNewDocument(Document* oldDocument);
- void setForm(HTMLFormElement* form) { m_form = form; }
- void removeFromForm();
+ void setForm(HTMLFormElement*);
void formAttributeChanged();
+ // If you add an override of willChangeForm() or didChangeForm() to a class
+ // derived from this one, you will need to add a call to setForm(0) to the
+ // destructor of that class.
+ virtual void willChangeForm();
+ virtual void didChangeForm();
+
private:
virtual const AtomicString& formControlName() const = 0;
Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (104667 => 104668)
--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -50,7 +50,6 @@
HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
: HTMLElement(tagName, document)
- , FormAssociatedElement(form)
, m_disabled(false)
, m_readOnly(false)
, m_required(false)
@@ -61,18 +60,12 @@
, m_wasChangedSinceLastFormControlChangeEvent(false)
, m_hasAutofocused(false)
{
- if (!this->form())
- setForm(findFormAncestor());
- if (this->form())
- this->form()->registerFormElement(this);
-
+ setForm(form ? form : findFormAncestor());
setHasCustomWillOrDidRecalcStyle();
}
HTMLFormControlElement::~HTMLFormControlElement()
{
- if (form())
- form()->removeFormElement(this);
}
void HTMLFormControlElement::detach()
@@ -108,11 +101,9 @@
void HTMLFormControlElement::parseMappedAttribute(Attribute* attr)
{
- if (attr->name() == formAttr) {
+ if (attr->name() == formAttr)
formAttributeChanged();
- if (!form())
- document()->checkedRadioButtons().addButton(this);
- } else if (attr->name() == disabledAttr) {
+ else if (attr->name() == disabledAttr) {
bool oldDisabled = m_disabled;
m_disabled = !attr->isNull();
if (oldDisabled != m_disabled) {
@@ -205,9 +196,6 @@
void HTMLFormControlElement::insertedIntoTree(bool deep)
{
FormAssociatedElement::insertedIntoTree();
- if (!form())
- document()->checkedRadioButtons().addButton(this);
-
HTMLElement::insertedIntoTree(deep);
}
Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (104667 => 104668)
--- trunk/Source/WebCore/html/HTMLFormElement.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -95,7 +95,7 @@
document()->unregisterForPageCacheSuspensionCallbacks(this);
for (unsigned i = 0; i < m_associatedElements.size(); ++i)
- m_associatedElements[i]->formDestroyed();
+ m_associatedElements[i]->formWillBeDestroyed();
for (unsigned i = 0; i < m_imageElements.size(); ++i)
m_imageElements[i]->m_form = 0;
}
@@ -456,18 +456,11 @@
void HTMLFormElement::registerFormElement(FormAssociatedElement* e)
{
- if (e->isFormControlElement()) {
- HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(e);
- document()->checkedRadioButtons().removeButton(element);
- m_checkedRadioButtons.addButton(element);
- }
m_associatedElements.insert(formElementIndex(e), e);
}
void HTMLFormElement::removeFormElement(FormAssociatedElement* e)
{
- if (e->isFormControlElement())
- m_checkedRadioButtons.removeButton(static_cast<HTMLFormControlElement*>(e));
unsigned index;
for (index = 0; index < m_associatedElements.size(); ++index) {
if (m_associatedElements[index] == e)
Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (104667 => 104668)
--- trunk/Source/WebCore/html/HTMLInputElement.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -116,11 +116,9 @@
if (needsSuspensionCallback())
document()->unregisterForPageCacheSuspensionCallbacks(this);
- document()->checkedRadioButtons().removeButton(this);
-
- // 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();
+ // Need to remove form association while this is still an HTMLInputElement
+ // so that virtual functions are called correctly.
+ setForm(0);
}
const AtomicString& HTMLInputElement::formControlName() const
@@ -179,8 +177,7 @@
void HTMLInputElement::updateCheckedRadioButtons()
{
- if (attached() && checked())
- checkedRadioButtons().addButton(this);
+ checkedRadioButtons().addButton(this);
if (form()) {
const Vector<FormAssociatedElement*>& controls = form()->associatedElements();
@@ -1502,6 +1499,32 @@
reset();
}
+void HTMLInputElement::willChangeForm()
+{
+ checkedRadioButtons().removeButton(this);
+ HTMLTextFormControlElement::willChangeForm();
+}
+
+void HTMLInputElement::didChangeForm()
+{
+ HTMLTextFormControlElement::didChangeForm();
+ checkedRadioButtons().addButton(this);
+}
+
+void HTMLInputElement::insertedIntoDocument()
+{
+ HTMLTextFormControlElement::insertedIntoDocument();
+ ASSERT(inDocument());
+ checkedRadioButtons().addButton(this);
+}
+
+void HTMLInputElement::removedFromDocument()
+{
+ ASSERT(inDocument());
+ checkedRadioButtons().removeButton(this);
+ HTMLTextFormControlElement::removedFromDocument();
+}
+
void HTMLInputElement::didMoveToNewDocument(Document* oldDocument)
{
m_inputType->willMoveToNewOwnerDocument();
Modified: trunk/Source/WebCore/html/HTMLInputElement.h (104667 => 104668)
--- trunk/Source/WebCore/html/HTMLInputElement.h 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/HTMLInputElement.h 2012-01-11 05:03:23 UTC (rev 104668)
@@ -249,6 +249,10 @@
enum AutoCompleteSetting { Uninitialized, On, Off };
enum AnyStepHandling { RejectAny, AnyIsDefaultStep };
+ virtual void willChangeForm() OVERRIDE;
+ virtual void didChangeForm() OVERRIDE;
+ virtual void insertedIntoDocument() OVERRIDE;
+ virtual void removedFromDocument() OVERRIDE;
virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE;
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
Modified: trunk/Source/WebCore/html/HTMLObjectElement.cpp (104667 => 104668)
--- trunk/Source/WebCore/html/HTMLObjectElement.cpp 2012-01-11 05:02:48 UTC (rev 104667)
+++ trunk/Source/WebCore/html/HTMLObjectElement.cpp 2012-01-11 05:03:23 UTC (rev 104668)
@@ -55,21 +55,15 @@
inline HTMLObjectElement::HTMLObjectElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)
: HTMLPlugInImageElement(tagName, document, createdByParser, ShouldNotPreferPlugInsForImages)
- , FormAssociatedElement(form)
, m_docNamedItem(true)
, m_useFallbackContent(false)
{
ASSERT(hasTagName(objectTag));
- if (!this->form())
- setForm(findFormAncestor());
- if (this->form())
- this->form()->registerFormElement(this);
+ setForm(form ? form : findFormAncestor());
}
inline HTMLObjectElement::~HTMLObjectElement()
{
- if (form())
- form()->removeFormElement(this);
}
PassRefPtr<HTMLObjectElement> HTMLObjectElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form, bool createdByParser)