REGRESSION(r116487?): HTMLFormElement::elements['name'] is empty if the form is detac...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Jun 2012 03:50:03 +0000 (03:50 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Jun 2012 03:50:03 +0000 (03:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=88632

Patch by Rakesh KN <rakesh.kn@motorola.com> on 2012-06-08
Reviewed by Ryosuke Niwa.

Source/WebCore:

Update root node of RadioNodeList when the form element is detached from dom tree.

Test: fast/forms/radionodelist-whose-form-element-detached-from-domtree.html

* dom/Node.cpp:
(WebCore::Node::resetCachedRadioNodeListRootNode):
New function to update the root node of RadioNodeLists to form element from document.
* dom/Node.h: Ditto.
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::removedFrom):
On detach, we update the root node of all RadioNodeLists of this form element.
* html/RadioNodeList.cpp:
(WebCore::RadioNodeList::setRootElement):
Setter for updating root node.
* html/RadioNodeList.h:
(RadioNodeList): Ditto.

LayoutTests:

* fast/forms/radionodelist-whose-form-element-detached-from-domtree-expected.txt: Added.
* fast/forms/radionodelist-whose-form-element-detached-from-domtree.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/html/HTMLFormElement.cpp
Source/WebCore/html/RadioNodeList.cpp
Source/WebCore/html/RadioNodeList.h

index 8fcdbf7..5f786af 100644 (file)
@@ -1,3 +1,13 @@
+2012-06-08  Rakesh KN  <rakesh.kn@motorola.com>
+
+        REGRESSION(r116487?): HTMLFormElement::elements['name'] is empty if the form is detached from the document tree
+        https://bugs.webkit.org/show_bug.cgi?id=88632
+
+        Reviewed by Ryosuke Niwa.
+
+        * fast/forms/radionodelist-whose-form-element-detached-from-domtree-expected.txt: Added.
+        * fast/forms/radionodelist-whose-form-element-detached-from-domtree.html: Added.
+
 2012-06-08  Ryosuke Niwa  <rniwa@webkit.org>
 
         Remove all uses of FAIL test expectation from Chromium test expectations.
diff --git a/LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree-expected.txt b/LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree-expected.txt
new file mode 100644 (file)
index 0000000..3ad454c
--- /dev/null
@@ -0,0 +1,45 @@
+RadioNodeList should be rooted at form itself if detached from dom tree
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+form in dom tree
+PASS radioNodeList1.length is 3
+PASS radioNodeList2.length is 3
+PASS radioNodeList1[0].value is 'value1'
+PASS radioNodeList1[1].value is 'value2'
+PASS radioNodeList1[2].value is 'value3'
+PASS radioNodeList2[0].value is 'value4'
+PASS radioNodeList2[1].value is 'value5'
+PASS radioNodeList2[2].value is 'value6'
+Check RadioNodeList.value
+PASS radioNodeList1.value is ""
+PASS radioNodeList2.value is ""
+PASS radioNodeList1[2].checked = true; radioNodeList1.value is 'value3'
+
+form detached from dom tree
+PASS radioNodeList1.length is 3
+PASS radioNodeList2.length is 3
+PASS radioNodeList1[0].value is 'value1'
+PASS radioNodeList1[1].value is 'value2'
+PASS radioNodeList1[2].value is 'value3'
+PASS radioNodeList2[0].value is 'value4'
+PASS radioNodeList2[1].value is 'value5'
+PASS radioNodeList2[2].value is 'value6'
+Check RadioNodeList.value
+PASS radioNodeList1[2].checked = true; radioNodeList1.value is 'value3'
+
+form again added to dom tree
+PASS radioNodeList1.length is 3
+PASS radioNodeList2.length is 3
+PASS radioNodeList1[0].value is 'value1'
+PASS radioNodeList1[1].value is 'value2'
+PASS radioNodeList1[2].value is 'value3'
+PASS radioNodeList2[0].value is 'value4'
+PASS radioNodeList2[1].value is 'value5'
+PASS radioNodeList2[2].value is 'value6'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree.html b/LayoutTests/fast/forms/radionodelist-whose-form-element-detached-from-domtree.html
new file mode 100644 (file)
index 0000000..2000979
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<form id="testform">
+    Radio button array:
+    <input type="radio" name="type1" value="value1">
+    <input type="radio" name="type1" value="value2">
+    <input type="radio" name="type1" value="value3">
+    <input type="radio" name="type2" value="value4">
+    <input type="radio" name="type2" value="value5">
+    <input type="radio" name="type2" value="value6">
+    <br>
+    Single checkbox:
+    <input type="checkbox" name="chkbox" value="chkboxvalue">
+    <br>
+</form>
+<div id="console"></div>
+<script>
+
+description("RadioNodeList should be rooted at form itself if detached from dom tree");
+debug("");
+var owner = document.getElementById('testform');
+var radioNodeList1 = owner.elements['type1'];
+var radioNodeList2 = owner.elements['type2'];
+
+function testRadioNodeList() {
+    shouldBe('radioNodeList1.length', '3');
+    shouldBe('radioNodeList2.length', '3');
+
+    shouldBe('radioNodeList1[0].value', "'value1'");
+    shouldBe('radioNodeList1[1].value', "'value2'");
+    shouldBe('radioNodeList1[2].value', "'value3'");
+    shouldBe('radioNodeList2[0].value', "'value4'");
+    shouldBe('radioNodeList2[1].value', "'value5'");
+    shouldBe('radioNodeList2[2].value', "'value6'");
+}
+debug("form in dom tree");
+testRadioNodeList();
+
+debug("Check RadioNodeList.value");
+shouldBe('radioNodeList1.value', '""');
+shouldBe('radioNodeList2.value', '""');
+shouldBe('radioNodeList1[2].checked = true; radioNodeList1.value', "'value3'");
+
+owner.parentNode.removeChild(owner);
+
+debug("");
+debug("form detached from dom tree");
+testRadioNodeList();
+
+debug("Check RadioNodeList.value");
+shouldBe('radioNodeList1[2].checked = true; radioNodeList1.value', "'value3'");
+
+document.body.appendChild(owner);
+debug("");
+debug("form again added to dom tree");
+testRadioNodeList();
+
+owner.parentNode.removeChild(owner);
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 6066d07..afeb735 100644 (file)
@@ -1,3 +1,27 @@
+2012-06-08  Rakesh KN  <rakesh.kn@motorola.com>
+
+        REGRESSION(r116487?): HTMLFormElement::elements['name'] is empty if the form is detached from the document tree
+        https://bugs.webkit.org/show_bug.cgi?id=88632
+
+        Reviewed by Ryosuke Niwa.
+
+        Update root node of RadioNodeList when the form element is detached from dom tree.
+
+        Test: fast/forms/radionodelist-whose-form-element-detached-from-domtree.html
+
+        * dom/Node.cpp:
+        (WebCore::Node::resetCachedRadioNodeListRootNode):
+        New function to update the root node of RadioNodeLists to form element from document.
+        * dom/Node.h: Ditto.
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::removedFrom):
+        On detach, we update the root node of all RadioNodeLists of this form element.
+        * html/RadioNodeList.cpp:
+        (WebCore::RadioNodeList::setRootElement):
+        Setter for updating root node.
+        * html/RadioNodeList.h:
+        (RadioNodeList): Ditto.
+
 2012-06-08  David Reveman  <reveman@chromium.org>
 
         [Chromium] Compositor doesn't support translucent root layers.
index 86cc2b7..f8753e9 100644 (file)
@@ -2930,6 +2930,17 @@ void Node::removeCachedRadioNodeList(RadioNodeList* list, const AtomicString& na
     data->m_radioNodeListCache.remove(name);
 }
 
+void Node::resetCachedRadioNodeListRootNode()
+{
+    ASSERT(hasTagName(formTag));
+    if (!hasRareData() || !rareData()->nodeLists())
+        return;
+
+    NodeListsNodeData::RadioNodeListCache cache = rareData()->nodeLists()->m_radioNodeListCache;
+    for (NodeListsNodeData::RadioNodeListCache::iterator it = cache.begin(); it != cache.end(); ++it)
+        it->second->setRootElement(toElement(this));
+}
+
 } // namespace WebCore
 
 #ifndef NDEBUG
index e3c7ade..b7b9e41 100644 (file)
@@ -578,6 +578,7 @@ public:
 
     PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
     void removeCachedRadioNodeList(RadioNodeList*, const AtomicString&);
+    void resetCachedRadioNodeListRootNode();
 
     PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
     PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
index 719b46e..1b1f08b 100644 (file)
@@ -165,6 +165,8 @@ void HTMLFormElement::removedFrom(ContainerNode* insertionPoint)
     HTMLElement::removedFrom(insertionPoint);
     if (insertionPoint->inDocument() && hasID())
         document()->formController()->resetFormElementsOwner();
+    if (!inDocument())
+        resetCachedRadioNodeListRootNode();
 }
 
 void HTMLFormElement::handleLocalEvents(Event* event)
index 40929bc..901e6a8 100644 (file)
@@ -112,5 +112,9 @@ bool RadioNodeList::nodeMatches(Element* testElement) const
     return checkElementMatchesRadioNodeListFilter(testElement);
 }
 
+void RadioNodeList::setRootElement(Element* baseElement)
+{
+    m_node = baseElement->toNode();
+}
 } // namspace
 
index 7782e48..1833cc0 100644 (file)
@@ -45,6 +45,7 @@ public:
 
     String value() const;
     void setValue(const String&);
+    void setRootElement(Element* baseElement);
 
 protected:
     virtual bool nodeMatches(Element*) const;