[Forms] label.form attribute doesn't work
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 13:05:35 +0000 (13:05 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 13:05:35 +0000 (13:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=80499

Patch by Yoshifumi Inoue <yosin@chromium.org> on 2012-03-16
Reviewed by Kent Tamura.

Source/WebCore:

This patch changes implementation of label.form of IDL attribute to
compute it to the form element specified by the "form" HTML attribute
or form ancestor when the "form" HTML attribute isn't in HTML.

This patch introduces new function FormAssociatedElement::findAssociatedForm
for sharing code among FormAssociateElement::insertedIntoTree, resetFormOwner
and HTMLLabelElement::form.

No new tests. Update existing tests.

* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::findAssociatedForm): Added.
(WebCore):
(WebCore::FormAssociatedElement::insertedIntoTree):
(WebCore::FormAssociatedElement::resetFormOwner):
* html/FormAssociatedElement.h:
(FormAssociatedElement):
* html/HTMLLabelElement.cpp: Remove unused include files
(WebCore::HTMLLabelElement::form): Added.

LayoutTests:

This patch updates test cases and expectation for functional
"form" attribute of the "label" element.

* fast/forms/form-attribute-expected.txt:
* fast/forms/form-attribute-nonexistence-form-id-expected.txt:
* fast/forms/form-attribute-nonexistence-form-id.html:
* fast/forms/form-attribute.html:

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

LayoutTests/ChangeLog
LayoutTests/fast/forms/form-attribute-expected.txt
LayoutTests/fast/forms/form-attribute-nonexistence-form-id-expected.txt
LayoutTests/fast/forms/form-attribute-nonexistence-form-id.html
LayoutTests/fast/forms/form-attribute.html
Source/WebCore/ChangeLog
Source/WebCore/html/FormAssociatedElement.cpp
Source/WebCore/html/FormAssociatedElement.h
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLLabelElement.h

index da7a3ded7b4d45494f3f7208d5773894b77bf261..ffa64012832563cb13648520b9578f706bac77e2 100644 (file)
@@ -1,3 +1,18 @@
+2012-03-16  Yoshifumi Inoue  <yosin@chromium.org>
+
+        [Forms] label.form attribute doesn't work
+        https://bugs.webkit.org/show_bug.cgi?id=80499
+
+        Reviewed by Kent Tamura.
+
+        This patch updates test cases and expectation for functional 
+        "form" attribute of the "label" element.
+
+        * fast/forms/form-attribute-expected.txt:
+        * fast/forms/form-attribute-nonexistence-form-id-expected.txt:
+        * fast/forms/form-attribute-nonexistence-form-id.html:
+        * fast/forms/form-attribute.html:
+
 2012-03-16  Kihong Kwon  <kihong.kwon@samsung.com>
 
         Support for Battery Status API.
index 0392e1b53cf04ecd309a0b7a07dabbd51bf9822a..b1020892719135687eda49f311aef35b155475be 100644 (file)
@@ -4,12 +4,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 - Checks the existence of the form attribute for each form-associated elements.
-FIXME: <label> doesn't support the form attribute for now.
 PASS document.getElementsByTagName("button")[0].form is owner
 PASS document.getElementsByTagName("fieldset")[0].form is owner
 PASS document.getElementsByTagName("input")[0].form is owner
 PASS document.getElementsByTagName("keygen")[0].form is owner
-FAIL document.getElementsByTagName("label")[0].form should be [object HTMLFormElement]. Was null.
+PASS document.getElementsByTagName("label")[0].form is owner
 PASS document.getElementsByTagName("object")[0].form is owner
 PASS document.getElementsByTagName("output")[0].form is owner
 PASS document.getElementsByTagName("progress")[0].form is owner
@@ -18,21 +17,30 @@ PASS document.getElementsByTagName("textarea")[0].form is owner
 
 - Ensures that the form attribute points the form owner even if the element is within another form element.
 PASS inputElement.form is owner
+PASS labelElement.form is owner
 
 - Ensures that the form attribute of all form-associated element with or witout form attribute points the form owner.
 PASS inputElement1.form is owner
 PASS inputElement2.form is owner
 PASS inputElement3.form is owner
+PASS labelElement1.form is owner
+PASS labelElement2.form is owner
+PASS labelElement3.form is owner
 
 - Ensures that the form attribute points the form owner even if the form element is nested another form element.
 NOTE: It seems that nesting form elements is not allowed so we ensure each form-associated elements associate with the outmost form element.
 PASS inputElement1.form is owner
 PASS inputElement2.form is owner
 PASS inputElement3.form is owner
+PASS labelElement1.form is owner
+PASS labelElement2.form is owner
+PASS labelElement3.form is owner
 
 - Ensures whether the form owner is set correctly when the value of form attribute of a form-associated element changed.
 PASS inputElement.form is form1
 PASS inputElement.form is form2
+PASS labelElement.form is form1
+PASS labelElement.form is form2
 PASS objectElement.form is form1
 PASS objectElement.form is form2
 
@@ -40,6 +48,9 @@ PASS objectElement.form is form2
 PASS inputElement.form is null
 PASS inputElement.form is owner
 PASS inputElement.form is null
+PASS labelElement.form is null
+PASS labelElement.form is owner
+PASS labelElement.form is null
 PASS objectElement.form is null
 PASS objectElement.form is owner
 PASS objectElement.form is null
@@ -48,8 +59,11 @@ PASS objectElement.form is null
 PASS owner.name is "firstOwner"
 PASS owner.name is "secondOwner"
 PASS inputElement.form is owner
+PASS labelElement.form is owner
 PASS inputElement.form is null
+PASS labelElement.form is null
 PASS inputElement.form is owner
+PASS labelElement.form is owner
 PASS successfullyParsed is true
 
 TEST COMPLETE
index a5b5cdfe02d406cbf295b59d7773c291fcd8f010..64bfd35cebb3eab6adc6e50c93904ceea9261389 100644 (file)
@@ -1,10 +1,13 @@
-This page ensures that <input from="X"> don't associate with any form elements when there is no <form id="X">.
+This page ensures that <input from="X"> and <label from="X"> don't associate with any form elements when there is no <form id="X">.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS elementShouldHaveForm.form is form
-PASS elementShouldNotHaveForm.form is null
+label1 label2
+PASS inputShouldHaveForm.form is form
+PASS inputShouldNotHaveForm.form is null
+PASS labelShouldHaveForm.form is form
+PASS labelShouldNotHaveForm.form is null
 PASS successfullyParsed is true
 
 TEST COMPLETE
index d582b9da6b9d8b65ca940455ff8f6bcb6af6ea30..a13ca8338a68accef1fafa15dbf7a70ab8a2d64f 100644 (file)
@@ -8,16 +8,22 @@
 <form id="form">
     <input type="hidden" id="input1" value="value1">
     <input type="hidden" id="input2" value="value2" form="X">
+    <label id="label1">label1</label>
+    <label id="label2" form="X">label2</label>
 </form>
 <div id="console"></div>
 <script>
-description('This page ensures that &lt;input from="X"&gt; don\'t associate with any form elements when there is no &lt;form id="X"&gt;.');
+description('This page ensures that &lt;input from="X"&gt; and &lt;label from="X"&gt; don\'t associate with any form elements when there is no &lt;form id="X"&gt;.');
 
 var form = document.getElementById('form');
-var elementShouldHaveForm = document.getElementById('input1');
-var elementShouldNotHaveForm = document.getElementById('input2');
-shouldBe('elementShouldHaveForm.form', 'form');
-shouldBeNull('elementShouldNotHaveForm.form');
+var inputShouldHaveForm = document.getElementById('input1');
+var inputShouldNotHaveForm = document.getElementById('input2');
+var labelShouldHaveForm = document.getElementById('label1');
+var labelShouldNotHaveForm = document.getElementById('label2');
+shouldBe('inputShouldHaveForm.form', 'form');
+shouldBeNull('inputShouldNotHaveForm.form');
+shouldBe('labelShouldHaveForm.form', 'form');
+shouldBeNull('labelShouldNotHaveForm.form');
 </script>
 <script src="../../fast/js/resources/js-test-post.js"></script>
 </body>
index 14218f143eafd1dc011a8b008782dd1e32fb8264..7902b0f9a823d799eeefc313aeadbd3eaa98be2e 100644 (file)
@@ -13,7 +13,6 @@ var container = document.createElement('div');
 document.body.appendChild(container);
 
 debug('- Checks the existence of the form attribute for each form-associated elements.');
-debug('FIXME: &lt;label&gt; doesn\'t support the form attribute for now.');
 container.innerHTML = '<form id=owner></form>' +
     '<button name=victim form=owner />' +
     '<fieldset name=victim form=owner />' +
@@ -43,10 +42,14 @@ debug('- Ensures that the form attribute points the form owner even if the eleme
 container.innerHTML = '<form id=owner></form>' +
     '<form id=shouldNotBeOwner>' +
     '    <input id=inputElement name=victim form=owner />' +
+    '    <label id=labelElement name=victim form=owner />' +
     '</form>';
 owner = document.getElementById('owner');
 var inputElement = document.getElementById('inputElement');
+var labelElement = document.getElementById('labelElement');
 shouldBe('inputElement.form', 'owner');
+shouldBe('labelElement.form', 'owner');
+
 
 debug('');
 debug('- Ensures that the form attribute of all form-associated element with or witout form attribute points the form owner.');
@@ -54,14 +57,23 @@ container.innerHTML = '<form id=owner>' +
     '    <input id=inputElement1 name=victim />' +
     '    <input id=inputElement2 name=victim form=owner />' +
     '    <input id=inputElement3 name=victim />' +
+    '    <label id=labelElement1 name=victim />' +
+    '    <label id=labelElement2 name=victim form=owner />' +
+    '    <label id=labelElement3 name=victim />' +
     '</form>';
 owner = document.getElementById('owner');
 var inputElement1 = document.getElementById('inputElement1');
 var inputElement2 = document.getElementById('inputElement2');
 var inputElement3 = document.getElementById('inputElement3');
+var labelElement1 = document.getElementById('labelElement1');
+var labelElement2 = document.getElementById('labelElement2');
+var labelElement3 = document.getElementById('labelElement3');
 shouldBe('inputElement1.form', 'owner');
 shouldBe('inputElement2.form', 'owner');
 shouldBe('inputElement3.form', 'owner');
+shouldBe('labelElement1.form', 'owner');
+shouldBe('labelElement2.form', 'owner');
+shouldBe('labelElement3.form', 'owner');
 
 debug('');
 debug('- Ensures that the form attribute points the form owner even if the form element is nested another form element.');
@@ -71,21 +83,31 @@ container.innerHTML = '<form id=owner>' +
     '        <input id=inputElement1 name=victim form=owner />' +
     '        <input id=inputElement2 name=victim />' +
     '        <input id=inputElement3 name=victim form=owner />' +
+    '        <label id=labelElement1 name=victim form=owner />' +
+    '        <label id=labelElement2 name=victim />' +
+    '        <label id=labelElement3 name=victim form=owner />' +
     '    </form>' +
     '</form>';
 owner = document.getElementById('owner');
 inputElement1 = document.getElementById('inputElement1');
 inputElement2 = document.getElementById('inputElement2');
 inputElement3 = document.getElementById('inputElement3');
+labelElement1 = document.getElementById('labelElement1');
+labelElement2 = document.getElementById('labelElement2');
+labelElement3 = document.getElementById('labelElement3');
 shouldBe('inputElement1.form', 'owner');
 shouldBe('inputElement2.form', 'owner');
 shouldBe('inputElement3.form', 'owner');
+shouldBe('labelElement1.form', 'owner');
+shouldBe('labelElement2.form', 'owner');
+shouldBe('labelElement3.form', 'owner');
 
 debug('');
 debug('- Ensures whether the form owner is set correctly when the value of form attribute of a form-associated element changed.');
 container.innerHTML = '<form id=form1></form>' +
     '<form id=form2></form>' +
     '<input id=inputElement name=victim form=form1 />' +
+    '<label id=labelElement name=victim form=form1 />' +
     '<object id=objectElement name=victim form=form1></object>';
 var form1 = document.getElementById('form1');
 var form2 = document.getElementById('form2');
@@ -94,6 +116,12 @@ shouldBe('inputElement.form', 'form1');
 inputElement.attributes['form'].value = 'form2';
 shouldBe('inputElement.form', 'form2');
 
+// HTMLabelElement has its own implementation of formAttr processing and so needs its own test.
+labelElement = document.getElementById('labelElement');
+shouldBe('labelElement.form', 'form1');
+labelElement.attributes['form'].value = 'form2';
+shouldBe('labelElement.form', 'form2');
+
 // HTMLObjectElement has its own implementation of formAttr processing and so needs its own test.
 objectElement = document.getElementById('objectElement');
 shouldBe('objectElement.form', 'form1');
@@ -104,6 +132,7 @@ debug('');
 debug('- Ensures whether the form owner is set correctly when the value of form attribute is added/removed.');
 container.innerHTML = '<form id=owner name=firstOwner></form>' +
     '<input id=inputElement name=victim />' +
+    '<label id=labelElement name=victim />' +
     '<object id=objectElement name=victim></object>';
 owner = document.getElementById('owner');
 inputElement = document.getElementById('inputElement');
@@ -114,6 +143,14 @@ shouldBe('inputElement.form', 'owner');
 inputElement.removeAttribute('form');
 shouldBe('inputElement.form', 'null');
 
+// HTMLLabelElement has its own implementation of formAttr processing and so needs its own test.
+labelElement = document.getElementById('labelElement');
+shouldBe('labelElement.form', 'null');
+labelElement.setAttribute('form', 'owner');
+shouldBe('labelElement.form', 'owner');
+labelElement.removeAttribute('form');
+shouldBe('labelElement.form', 'null');
+
 // HTMLObjectElement has its own implementation of formAttr processing and so needs its own test.
 objectElement = document.getElementById('objectElement');
 shouldBe('objectElement.form', 'null');
@@ -126,18 +163,23 @@ debug('');
 debug('- Ensures whether the form owner is set correctly when the form owner is added/removed.');
 container.innerHTML = '<form id=owner name=firstOwner></form>' +
     '<form id=owner name=secondOwner></form>' +
-    '<input id=inputElement name=victim form=owner />';
+    '<input id=inputElement name=victim form=owner />' +
+    '<label id=labelElement name=victim form=owner />';
 owner = document.getElementById('owner');
 shouldBeEqualToString('owner.name', 'firstOwner');
 inputElement = document.getElementById('inputElement');
+labelElement = document.getElementById('labelElement');
 container.removeChild(owner);
 owner = document.getElementById('owner');
 shouldBeEqualToString('owner.name', 'secondOwner');
 shouldBe('inputElement.form', 'owner');
+shouldBe('labelElement.form', 'owner');
 container.removeChild(owner);
 shouldBe('inputElement.form', 'null');
+shouldBe('labelElement.form', 'null');
 container.appendChild(owner);
 shouldBe('inputElement.form', 'owner');
+shouldBe('labelElement.form', 'owner');
 </script>
 <script src="../../fast/js/resources/js-test-post.js"></script>
 </body>
index 39f457bbb0fae00da425ea1163ff519f1816b559..6568e875c3c47dd0803656240ae7abc46b06e9e2 100644 (file)
@@ -1,3 +1,30 @@
+2012-03-16  Yoshifumi Inoue  <yosin@chromium.org>
+
+        [Forms] label.form attribute doesn't work
+        https://bugs.webkit.org/show_bug.cgi?id=80499
+
+        Reviewed by Kent Tamura.
+
+        This patch changes implementation of label.form of IDL attribute to
+        compute it to the form element specified by the "form" HTML attribute
+        or form ancestor when the "form" HTML attribute isn't in HTML.
+
+        This patch introduces new function FormAssociatedElement::findAssociatedForm
+        for sharing code among FormAssociateElement::insertedIntoTree, resetFormOwner
+        and HTMLLabelElement::form.
+
+        No new tests. Update existing tests.
+
+        * html/FormAssociatedElement.cpp:
+        (WebCore::FormAssociatedElement::findAssociatedForm): Added.
+        (WebCore):
+        (WebCore::FormAssociatedElement::insertedIntoTree):
+        (WebCore::FormAssociatedElement::resetFormOwner):
+        * html/FormAssociatedElement.h:
+        (FormAssociatedElement):
+        * html/HTMLLabelElement.cpp: Remove unused include files
+        (WebCore::HTMLLabelElement::form): Added.
+
 2012-03-16  Kenneth Rohde Christiansen  <kenneth@webkit.org>
 
         Use the normalize method of FloatPoint instead of normalizing manually
index e7ebebe72c276c60299fe27af0d4e63da28d864c..86b2b648acef56e0825ccc4f1dfafecad6c50efd 100644 (file)
@@ -74,6 +74,27 @@ void FormAssociatedElement::removedFromDocument()
         element->document()->unregisterFormElementWithFormAttribute(this);
 }
 
+HTMLFormElement* FormAssociatedElement::findAssociatedForm(const HTMLElement* element, HTMLFormElement* currentAssociatedForm)
+{
+    const AtomicString& formId(element->fastGetAttribute(formAttr));
+    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
+        // the value of form attribute, so we put the result of
+        // treeScope()->getElementById() over the given element.
+        HTMLFormElement* newForm = 0;
+        Element* newFormCandidate = element->treeScope()->getElementById(formId);
+        if (newFormCandidate && newFormCandidate->hasTagName(formTag))
+            newForm = static_cast<HTMLFormElement*>(newFormCandidate);
+        return newForm;
+    }
+
+    if (!currentAssociatedForm)
+        return element->findFormAncestor();
+
+    return currentAssociatedForm;
+}
+
 void FormAssociatedElement::insertedIntoTree()
 {
     resetFormOwner();
@@ -130,24 +151,7 @@ void FormAssociatedElement::formWillBeDestroyed()
 
 void FormAssociatedElement::resetFormOwner()
 {
-    HTMLElement* element = toHTMLElement(this);
-    const AtomicString& formId(element->fastGetAttribute(formAttr));
-    if (m_form) {
-        if (formId.isNull())
-            return;
-    }
-    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
-        // the value of form attribute, so we put the result of
-        // treeScope()->getElementById() over the given element.
-        Element* firstElement = element->treeScope()->getElementById(formId);
-        if (firstElement && firstElement->hasTagName(formTag))
-            newForm = static_cast<HTMLFormElement*>(firstElement);
-    } else
-        newForm = element->findFormAncestor();
-    setForm(newForm);
+    setForm(findAssociatedForm(toHTMLElement(this), m_form));
 }
 
 void FormAssociatedElement::formAttributeChanged()
index b336f373c166220feaf0fad6425a4136d6968fab..b2a35e9c8ae9fcfbdc4d36360af39965702321de 100644 (file)
@@ -41,6 +41,7 @@ public:
     void ref() { refFormAssociatedElement(); }
     void deref() { derefFormAssociatedElement(); }
 
+    static HTMLFormElement* findAssociatedForm(const HTMLElement*, HTMLFormElement*);
     HTMLFormElement* form() const { return m_form; }
     ValidityState* validity();
 
index d88e7373dd2c0a806a763ce977b667ae5766ca97..c1021b3587db88ba677f2da6a1cf6644a89f4f02 100644 (file)
@@ -28,7 +28,7 @@
 #include "Document.h"
 #include "Event.h"
 #include "EventNames.h"
-#include "LabelableElement.h"
+#include "FormAssociatedElement.h"
 #include "HTMLNames.h"
 
 namespace WebCore {
@@ -87,6 +87,11 @@ LabelableElement* HTMLLabelElement::control()
     return nodeAsLabelableElement(treeScope()->getElementById(controlId));
 }
 
+HTMLFormElement* HTMLLabelElement::form() const
+{
+    return FormAssociatedElement::findAssociatedForm(this, 0);
+}
+
 void HTMLLabelElement::setActive(bool down, bool pause)
 {
     if (down == active())
index 1b77aa2d56392cda2e984cc1bd0e865c9600926b..a821b25077a19ec4d58824456d2205b72c34df2b 100644 (file)
@@ -34,6 +34,7 @@ public:
     static PassRefPtr<HTMLLabelElement> create(const QualifiedName&, Document*);
 
     LabelableElement* control();
+    HTMLFormElement* form() const;
 
 private:
     HTMLLabelElement(const QualifiedName&, Document*);