Title: [236778] trunk
Revision
236778
Author
[email protected]
Date
2018-10-02 17:26:41 -0700 (Tue, 02 Oct 2018)

Log Message

fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection
https://bugs.webkit.org/show_bug.cgi?id=190218

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

Rebaseline existing WPT test now that it is passing.

* web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement-expected.txt:

Source/WebCore:

fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection:
- https://github.com/whatwg/html/commit/8beedf0c2ffd38853caddec67490288f47afc8eb

Gecko has always behaved this way. Blink aligned with Gecko and the HTML specification in December 2016:
- https://bugs.chromium.org/p/chromium/issues/detail?id=665291

This simplifies our HTMLFieldSetElement code a lot.

Test: fast/forms/fieldset/fieldset-elements-htmlcollection.html

* html/CollectionType.h:
* html/GenericCachedHTMLCollection.cpp:
(WebCore::GenericCachedHTMLCollection<traversalType>::elementMatches const):
* html/HTMLCollection.cpp:
(WebCore::HTMLCollection::rootTypeFromCollectionType):
(WebCore::invalidationTypeExcludingIdAndNameAttributes):
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::elements):
* html/HTMLFieldSetElement.h:
* html/HTMLFieldSetElement.idl:
* html/HTMLFormControlsCollection.cpp:
(WebCore::HTMLFormControlsCollection::HTMLFormControlsCollection):
(WebCore:: const):
(WebCore::HTMLFormControlsCollection::copyFormControlElementsVector const):
(WebCore::HTMLFormControlsCollection::ownerNode const):
(WebCore::HTMLFormControlsCollection::updateNamedElementCache const):
* html/HTMLFormControlsCollection.h:

LayoutTests:

Update existing tests to reflect behavior change, after checking that our behavior is consistent
with Gecko and Blink on these tests.

* fast/forms/fieldset/fieldset-elements-expected.txt:
* fast/forms/fieldset/fieldset-elements-htmlcollection-expected.txt: Added.
* fast/forms/fieldset/fieldset-elements-htmlcollection.html: Added.
* fast/forms/fieldset/fieldset-elements.html:
* fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt: Removed.
* fast/forms/fieldset/fieldset-form-collection-radionode-list.html: Removed.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (236777 => 236778)


--- trunk/LayoutTests/ChangeLog	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/ChangeLog	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,3 +1,20 @@
+2018-10-02  Chris Dumez  <[email protected]>
+
+        fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection
+        https://bugs.webkit.org/show_bug.cgi?id=190218
+
+        Reviewed by Alex Christensen.
+
+        Update existing tests to reflect behavior change, after checking that our behavior is consistent
+        with Gecko and Blink on these tests.
+
+        * fast/forms/fieldset/fieldset-elements-expected.txt:
+        * fast/forms/fieldset/fieldset-elements-htmlcollection-expected.txt: Added.
+        * fast/forms/fieldset/fieldset-elements-htmlcollection.html: Added.
+        * fast/forms/fieldset/fieldset-elements.html:
+        * fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt: Removed.
+        * fast/forms/fieldset/fieldset-form-collection-radionode-list.html: Removed.
+
 2018-10-02  Devin Rousso  <[email protected]>
 
         Web Inspector: prevent layer events from firing until the layer information is re-requested

Modified: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt (236777 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt	2018-10-03 00:26:41 UTC (rev 236778)
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS owner.elements.length is 23
+PASS owner.elements.length is 24
 PASS owner.elements[0].id is 'button1'
 PASS owner.elements[1].id is 'fieldset1'
 PASS owner.elements[2].id is 'inputhidden'
@@ -20,29 +20,30 @@
 PASS owner.elements[13].id is 'inputradio'
 PASS owner.elements[14].id is 'inputfile'
 PASS owner.elements[15].id is 'inputsubmit'
-PASS owner.elements[16].id is 'inputreset'
-PASS owner.elements[17].id is 'inputbutton'
-PASS owner.elements[18].id is 'keygen1'
-PASS owner.elements[19].id is 'object1'
-PASS owner.elements[20].id is 'output1'
-PASS owner.elements[21].id is 'select1'
-PASS owner.elements[22].id is 'textarea1'
+PASS owner.elements[16].id is 'inputimage'
+PASS owner.elements[17].id is 'inputreset'
+PASS owner.elements[18].id is 'inputbutton'
+PASS owner.elements[19].id is 'keygen1'
+PASS owner.elements[20].id is 'object1'
+PASS owner.elements[21].id is 'output1'
+PASS owner.elements[22].id is 'select1'
+PASS owner.elements[23].id is 'textarea1'
 
 Check elements array is updated after adding a new element
-PASS owner.appendChild(newElement); owner.elements.length is 24
+PASS owner.appendChild(newElement); owner.elements.length is 25
 
 Check elements array is updated after remove an element
-PASS owner.removeChild(newElement); owner.elements.length is 23
+PASS owner.removeChild(newElement); owner.elements.length is 24
 
 Check owner.elements is updated properly
-PASS document.getElementById("inputfile").type="image"; owner.elements.length is 22
+PASS document.getElementById("inputfile").type="image"; owner.elements.length is 24
 
 Check owner.elements is updated properly after removing from parent
 PASS form.appendChild(newElement); form.elements.length is 1
 PASS form.removeChild(newElement); form.elements.length is 0
-PASS owner.elements.length is 22
-PASS owner.appendChild(newElement); owner.elements.length is 23
-PASS owner.removeChild(newElement); owner.elements.length is 22
+PASS owner.elements.length is 24
+PASS owner.appendChild(newElement); owner.elements.length is 25
+PASS owner.removeChild(newElement); owner.elements.length is 24
 PASS successfullyParsed is true
 
 TEST COMPLETE

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection-expected.txt (0 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection-expected.txt	2018-10-03 00:26:41 UTC (rev 236778)
@@ -0,0 +1,17 @@
+This test that fieldset.elements attribute returns an HTMLCollection and not an HTMLFormControlsCollection.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+ 
+                                        
+
+PASS elementsList instanceof HTMLCollection is true
+PASS elementsList instanceof HTMLFormControlsCollection is false
+PASS elementsList.length is 24
+PASS inputcommonElement instanceof RadioNodeList is false
+PASS inputcommonElement instanceof HTMLInputElement is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection.html (0 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-htmlcollection.html	2018-10-03 00:26:41 UTC (rev 236778)
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<p id="description"></p>
+<div id="divId">
+<form>
+<fieldset id="fs">
+    <button id=button1></button>
+    <fieldset id=fieldset1><legend id=legend1></legend></fieldset>
+    <input id=inputhidden type=hidden>
+    <input id=commoninput type=text>
+    <input id=inputcommon type=search value=searching>
+    <input id=inputurl type=url>
+    <input id=commoninput type=email>
+    <input id=inputpassword type=password>
+    <input id=inputdate type=date>
+    <input id=numberId name=inputcommon type=number value=123>
+    <input id=inputrange type=range>
+    <input id=inputcolor type=color>
+    <input id=inputcheckbox type=checkbox>
+    <input id=inputcommon type=radio value="inputRadioValue">
+    <input id=inputfile type=file>
+    <input id=inputsubmit type=submit>
+    <input id=inputcommon type=image>
+    <input id=commoninput type=reset>
+    <input id=inputcommon type=button value=buttonValue>
+    <keygen id=keygen1></keygen>
+    <label id=label1></label>
+    <meter id=meter1></meter>
+    <object id=object1></object>
+    <output id=output1></output>
+    <progress id=progress1></progress>
+    <select id=select1>
+        <optgroup id=optgroup1>group1</optgroup>
+        <option id=option1>option1</option>
+    </select>
+    <textarea id=textarea1></textarea>
+</fieldset>
+</form>
+</div>
+<div id="console"></div>
+<script>
+description("This test that fieldset.elements attribute returns an HTMLCollection and not an HTMLFormControlsCollection.");
+debug("");
+var owner = document.getElementById('fs');
+
+var elementsList = owner.elements;
+shouldBeTrue('elementsList instanceof HTMLCollection');
+shouldBeFalse('elementsList instanceof HTMLFormControlsCollection');
+
+shouldBe('elementsList.length', '24');
+
+var inputcommonElement = elementsList.namedItem("inputcommon");
+shouldBeFalse('inputcommonElement instanceof RadioNodeList');
+shouldBeTrue('inputcommonElement instanceof HTMLInputElement');
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html (236777 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html	2018-10-03 00:26:41 UTC (rev 236778)
@@ -46,7 +46,7 @@
 
 var owner = document.getElementById('fs');
 
-shouldBe('owner.elements.length', '23');
+shouldBe('owner.elements.length', '24');
 shouldBe('owner.elements[0].id', "'button1'");
 shouldBe('owner.elements[1].id', "'fieldset1'");
 shouldBe('owner.elements[2].id', "'inputhidden'");
@@ -63,13 +63,14 @@
 shouldBe('owner.elements[13].id', "'inputradio'");
 shouldBe('owner.elements[14].id', "'inputfile'");
 shouldBe('owner.elements[15].id', "'inputsubmit'");
-shouldBe('owner.elements[16].id', "'inputreset'");
-shouldBe('owner.elements[17].id', "'inputbutton'");
-shouldBe('owner.elements[18].id', "'keygen1'");
-shouldBe('owner.elements[19].id', "'object1'");
-shouldBe('owner.elements[20].id', "'output1'");
-shouldBe('owner.elements[21].id', "'select1'");
-shouldBe('owner.elements[22].id', "'textarea1'");
+shouldBe('owner.elements[16].id', "'inputimage'");
+shouldBe('owner.elements[17].id', "'inputreset'");
+shouldBe('owner.elements[18].id', "'inputbutton'");
+shouldBe('owner.elements[19].id', "'keygen1'");
+shouldBe('owner.elements[20].id', "'object1'");
+shouldBe('owner.elements[21].id', "'output1'");
+shouldBe('owner.elements[22].id', "'select1'");
+shouldBe('owner.elements[23].id', "'textarea1'");
 
 var newElement = document.createElement("input");
 newElement.setAttribute("type", "text");
@@ -78,15 +79,15 @@
 
 debug("");
 debug("Check elements array is updated after adding a new element");
-shouldBe('owner.appendChild(newElement); owner.elements.length', '24');
+shouldBe('owner.appendChild(newElement); owner.elements.length', '25');
 
 debug("");
 debug("Check elements array is updated after remove an element");
-shouldBe('owner.removeChild(newElement); owner.elements.length', '23');
+shouldBe('owner.removeChild(newElement); owner.elements.length', '24');
 
 debug("");
 debug("Check owner.elements is updated properly");
-shouldBe('document.getElementById("inputfile").type="image"; owner.elements.length', '22');
+shouldBe('document.getElementById("inputfile").type="image"; owner.elements.length', '24');
 
 debug("");
 debug("Check owner.elements is updated properly after removing from parent");
@@ -94,9 +95,9 @@
 var form = document.getElementById("formElement");
 shouldBe('form.appendChild(newElement); form.elements.length', '1');
 shouldBe('form.removeChild(newElement); form.elements.length', '0');
-shouldBe('owner.elements.length', '22');
-shouldBe('owner.appendChild(newElement); owner.elements.length', '23');
-shouldBe('owner.removeChild(newElement); owner.elements.length', '22');
+shouldBe('owner.elements.length', '24');
+shouldBe('owner.appendChild(newElement); owner.elements.length', '25');
+shouldBe('owner.removeChild(newElement); owner.elements.length', '24');
 
 container.parentNode.removeChild(container);
 </script>

Deleted: trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt (236777 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,53 +0,0 @@
-This test is for RadioNodeList specified at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#radionodelist
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-
-PASS owner.elements.length is 23
-PASS radioNodeList.length is 4
-PASS radioNodeList[0].value is 'searching'
-PASS radioNodeList[1].value is '123'
-PASS radioNodeList[2].value is 'inputRadioValue'
-PASS radioNodeList[3].value is 'buttonValue'
-
-Changing the input value to check RadioNodeList is live view of FormCollection
-PASS radioNodeList[1].value is '456'
-
-Checking value IDL attribute on the RadioNodeList
-PASS radioNodeList.value is ""
-PASS radioNodeList.value = "inputRadioValue"; radioNodeList[2].checked is true
-PASS Object.prototype.toString.call(radioNodeList[2]) is '[object HTMLInputElement]'
-PASS radioNodeList[2].type is 'radio'
-PASS radioNodeList.value is ""
-PASS radioNodeList[2].checked = true; radioNodeList.value is 'inputRadioValue'
-
-Check RadioNodeList is updated after adding a new element
-PASS owner.appendChild(newElement); radioNodeList.length is 5
-PASS owner.elements.length is 24
-PASS radioNodeList[4].value is 'new element'
-
-Check RadioNodeList is updated after remove an element
-PASS owner.removeChild(newElement); radioNodeList.length is 4
-PASS radioNodeList[3].value is 'buttonValue'
-
-Check RadioNodeList is updated after change in id, type and checked state of an element
-PASS radioNodeList.length is 4
-After changing the id
-PASS radioNodeList.length is 3
-PASS elementsList[13].checked = false; radioNodeList.value is ""
-PASS elementsList[13].checked = true; radioNodeList.value is 'inputRadioValue'
-PASS elementsList[13].type = "date"; radioNodeList.value is ''
-
-Check second RadioNodeList is also created properly
-PASS radioNodeList2.length is 3
-PASS radioNodeList2[0].type is 'text'
-PASS radioNodeList2[1].type is 'email'
-PASS radioNodeList2[2].type is 'reset'
-After changing the id
-PASS radioNodeList2.length is 2
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-

Deleted: trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html (236777 => 236778)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,120 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-<script src=""
-<p id="description"></p>
-<div id="divId">
-<form>
-<fieldset id="fs">
-    <button id=button1></button>
-    <fieldset id=fieldset1><legend id=legend1></legend></fieldset>
-    <input id=inputhidden type=hidden>
-    <input id=commoninput type=text>
-    <input id=inputcommon type=search value=searching>
-    <input id=inputurl type=url>
-    <input id=commoninput type=email>
-    <input id=inputpassword type=password>
-    <input id=inputdate type=date>
-    <input id=numberId name=inputcommon type=number value=123>
-    <input id=inputrange type=range>
-    <input id=inputcolor type=color>
-    <input id=inputcheckbox type=checkbox>
-    <input id=inputcommon type=radio value="inputRadioValue">
-    <input id=inputfile type=file>
-    <input id=inputsubmit type=submit>
-    <input id=inputcommon type=image>
-    <input id=commoninput type=reset>
-    <input id=inputcommon type=button value=buttonValue>
-    <keygen id=keygen1></keygen>
-    <label id=label1></label>
-    <meter id=meter1></meter>
-    <object id=object1></object>
-    <output id=output1></output>
-    <progress id=progress1></progress>
-    <select id=select1>
-        <optgroup id=optgroup1>group1</optgroup>
-        <option id=option1>option1</option>
-    </select>
-    <textarea id=textarea1></textarea>
-</fieldset>
-</form>
-</div>
-<div id="console"></div>
-<script>
-description("This test is for RadioNodeList specified at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#radionodelist ");
-debug("");
-var owner = document.getElementById('fs');
-
-shouldBe('owner.elements.length', '23');
-
-var elementsList = owner.elements;
-var radioNodeList = elementsList.namedItem("inputcommon");
-shouldBe('radioNodeList.length', '4');
-
-shouldBe('radioNodeList[0].value', "'searching'");
-shouldBe('radioNodeList[1].value', "'123'");
-shouldBe('radioNodeList[2].value', "'inputRadioValue'");
-shouldBe('radioNodeList[3].value', "'buttonValue'");
-
-debug("");
-debug("Changing the input value to check RadioNodeList is live view of FormCollection");
-document.getElementById("numberId").value = 456;
-shouldBe('radioNodeList[1].value', "'456'");
-
-debug("");
-debug("Checking value IDL attribute on the RadioNodeList");
-shouldBe('radioNodeList.value', '""');
-shouldBe('radioNodeList.value = "inputRadioValue"; radioNodeList[2].checked', 'true');
-shouldBe('Object.prototype.toString.call(radioNodeList[2])', "'[object HTMLInputElement]'");
-shouldBe('radioNodeList[2].type', "'radio'");
-
-radioNodeList[2].checked = false;
-shouldBe('radioNodeList.value', '""');
-shouldBe('radioNodeList[2].checked = true; radioNodeList.value', "'inputRadioValue'");
-
-var newElement = document.createElement("input");
-newElement.setAttribute("type", "text");
-newElement.setAttribute("value", "new element");
-newElement.setAttribute("id", "inputcommon");
-
-debug("");
-debug("Check RadioNodeList is updated after adding a new element");
-shouldBe('owner.appendChild(newElement); radioNodeList.length', '5');
-shouldBe('owner.elements.length', '24');
-shouldBe('radioNodeList[4].value', "'new element'");
-
-debug("");
-debug("Check RadioNodeList is updated after remove an element");
-shouldBe('owner.removeChild(newElement); radioNodeList.length', '4');
-shouldBe('radioNodeList[3].value', "'buttonValue'");
-
-debug("");
-debug("Check RadioNodeList is updated after change in id, type and checked state of an element");
-shouldBe('radioNodeList.length', '4');
-debug("After changing the id");
-radioNodeList[3].id = "changedName";
-shouldBe('radioNodeList.length', '3');
-
-shouldBe('elementsList[13].checked = false; radioNodeList.value', '""');
-shouldBe('elementsList[13].checked = true; radioNodeList.value', "'inputRadioValue'");
-shouldBe('elementsList[13].type = "date"; radioNodeList.value', "''");
-
-debug("");
-debug("Check second RadioNodeList is also created properly");
-var radioNodeList2 = elementsList.namedItem("commoninput");
-shouldBe('radioNodeList2.length', '3');
-
-shouldBe('radioNodeList2[0].type', "'text'");
-shouldBe('radioNodeList2[1].type', "'email'");
-shouldBe('radioNodeList2[2].type', "'reset'");
-radioNodeList2[2].id = "idChanged";
-debug("After changing the id");
-shouldBe('radioNodeList2.length', '2');
-debug("");
-
-var container = document.getElementById("divId");
-container.parentNode.removeChild(container);
-</script>
-<script src=""
-</body>
-</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (236777 => 236778)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,5 +1,16 @@
 2018-10-02  Chris Dumez  <[email protected]>
 
+        fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection
+        https://bugs.webkit.org/show_bug.cgi?id=190218
+
+        Reviewed by Alex Christensen.
+
+        Rebaseline existing WPT test now that it is passing.
+
+        * web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement-expected.txt:
+
+2018-10-02  Chris Dumez  <[email protected]>
+
         Refresh imported/w3c/web-platform-tests/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh
         https://bugs.webkit.org/show_bug.cgi?id=190212
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement-expected.txt (236777 => 236778)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement-expected.txt	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement-expected.txt	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,10 +1,6 @@
 
 PASS The type attribute must return 'fieldset' 
 PASS The form attribute must return the fieldset's form owner 
-FAIL The elements must return an HTMLCollection object assert_equals: The elements attribute should be an HTMLCollection object expected function "function HTMLCollection() {
-    [native code]
-}" but got function "function HTMLFormControlsCollection() {
-    [native code]
-}"
+PASS The elements must return an HTMLCollection object 
 PASS The controls must root at the fieldset element 
 

Modified: trunk/Source/WebCore/ChangeLog (236777 => 236778)


--- trunk/Source/WebCore/ChangeLog	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/ChangeLog	2018-10-03 00:26:41 UTC (rev 236778)
@@ -1,3 +1,38 @@
+2018-10-02  Chris Dumez  <[email protected]>
+
+        fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection
+        https://bugs.webkit.org/show_bug.cgi?id=190218
+
+        Reviewed by Alex Christensen.
+
+        fieldset.elements should return an HTMLCollection instead of an HTMLFormControlsCollection:
+        - https://github.com/whatwg/html/commit/8beedf0c2ffd38853caddec67490288f47afc8eb
+
+        Gecko has always behaved this way. Blink aligned with Gecko and the HTML specification in December 2016:
+        - https://bugs.chromium.org/p/chromium/issues/detail?id=665291
+
+        This simplifies our HTMLFieldSetElement code a lot.
+
+        Test: fast/forms/fieldset/fieldset-elements-htmlcollection.html
+
+        * html/CollectionType.h:
+        * html/GenericCachedHTMLCollection.cpp:
+        (WebCore::GenericCachedHTMLCollection<traversalType>::elementMatches const):
+        * html/HTMLCollection.cpp:
+        (WebCore::HTMLCollection::rootTypeFromCollectionType):
+        (WebCore::invalidationTypeExcludingIdAndNameAttributes):
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::elements):
+        * html/HTMLFieldSetElement.h:
+        * html/HTMLFieldSetElement.idl:
+        * html/HTMLFormControlsCollection.cpp:
+        (WebCore::HTMLFormControlsCollection::HTMLFormControlsCollection):
+        (WebCore:: const):
+        (WebCore::HTMLFormControlsCollection::copyFormControlElementsVector const):
+        (WebCore::HTMLFormControlsCollection::ownerNode const):
+        (WebCore::HTMLFormControlsCollection::updateNamedElementCache const):
+        * html/HTMLFormControlsCollection.h:
+
 2018-10-02  Devin Rousso  <[email protected]>
 
         Web Inspector: prevent layer events from firing until the layer information is re-requested

Modified: trunk/Source/WebCore/html/CollectionType.h (236777 => 236778)


--- trunk/Source/WebCore/html/CollectionType.h	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/CollectionType.h	2018-10-03 00:26:41 UTC (rev 236778)
@@ -52,6 +52,7 @@
     DataListOptions,
     MapAreas,
     FormControls,
+    FieldSetElements,
     ByClass,
     ByTag,
     ByHTMLTag,

Modified: trunk/Source/WebCore/html/GenericCachedHTMLCollection.cpp (236777 => 236778)


--- trunk/Source/WebCore/html/GenericCachedHTMLCollection.cpp	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/GenericCachedHTMLCollection.cpp	2018-10-03 00:26:41 UTC (rev 236778)
@@ -27,6 +27,7 @@
 #include "GenericCachedHTMLCollection.h"
 
 #include "HTMLAppletElement.h"
+#include "HTMLFieldSetElement.h"
 #include "HTMLNames.h"
 #include "HTMLObjectElement.h"
 #include "HTMLOptionElement.h"
@@ -72,6 +73,8 @@
         return (element.hasTagName(aTag) || element.hasTagName(areaTag)) && element.hasAttributeWithoutSynchronization(hrefAttr);
     case DocAnchors:
         return element.hasTagName(aTag) && element.hasAttributeWithoutSynchronization(nameAttr);
+    case FieldSetElements:
+        return is<HTMLObjectElement>(element) || is<HTMLFormControlElement>(element);
     case ByClass:
     case ByTag:
     case ByHTMLTag:

Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLCollection.cpp	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp	2018-10-03 00:26:41 UTC (rev 236778)
@@ -51,6 +51,7 @@
     case ByClass:
     case ByTag:
     case ByHTMLTag:
+    case FieldSetElements:
     case NodeChildren:
     case TableTBodies:
     case TSectionRows:
@@ -100,6 +101,7 @@
     case DocumentNamedItems:
     case DocumentAllNamedItems:
         return InvalidateOnIdNameAttrChange;
+    case FieldSetElements:
     case FormControls:
         return InvalidateForFormControls;
     }

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.cpp (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2018-10-03 00:26:41 UTC (rev 236778)
@@ -26,6 +26,7 @@
 #include "HTMLFieldSetElement.h"
 
 #include "ElementIterator.h"
+#include "GenericCachedHTMLCollection.h"
 #include "HTMLFormControlsCollection.h"
 #include "HTMLLegendElement.h"
 #include "HTMLNames.h"
@@ -167,60 +168,11 @@
     return const_cast<HTMLLegendElement*>(childrenOfType<HTMLLegendElement>(*this).first());
 }
 
-Ref<HTMLFormControlsCollection> HTMLFieldSetElement::elements()
+Ref<HTMLCollection> HTMLFieldSetElement::elements()
 {
-    return ensureRareData().ensureNodeLists().addCachedCollection<HTMLFormControlsCollection>(*this, FormControls);
+    return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<FieldSetElements>::traversalType>>(*this, FieldSetElements);
 }
 
-Ref<HTMLCollection> HTMLFieldSetElement::elementsForNativeBindings()
-{
-    return elements();
-}
-
-void HTMLFieldSetElement::updateAssociatedElements() const
-{
-    uint64_t documentVersion = document().domTreeVersion();
-    if (m_documentVersion == documentVersion)
-        return;
-
-    m_documentVersion = documentVersion;
-
-    m_associatedElements.clear();
-
-    for (auto& element : descendantsOfType<HTMLElement>(const_cast<HTMLFieldSetElement&>(*this))) {
-        if (is<HTMLObjectElement>(element))
-            m_associatedElements.append(&downcast<HTMLObjectElement>(element));
-        else if (is<HTMLFormControlElement>(element))
-            m_associatedElements.append(&downcast<HTMLFormControlElement>(element));
-    }
-}
-
-Vector<Ref<FormAssociatedElement>> HTMLFieldSetElement::copyAssociatedElementsVector() const
-{
-    updateAssociatedElements();
-    return WTF::map(m_associatedElements, [] (auto* rawElement) {
-        return Ref<FormAssociatedElement>(*rawElement);
-    });
-}
-
-const Vector<FormAssociatedElement*>& HTMLFieldSetElement::unsafeAssociatedElements() const
-{
-    ASSERT(!ScriptDisallowedScope::InMainThread::isScriptAllowed());
-    updateAssociatedElements();
-    return m_associatedElements;
-}
-
-unsigned HTMLFieldSetElement::length() const
-{
-    ScriptDisallowedScope::InMainThread scriptDisallowedScope;
-    unsigned length = 0;
-    for (auto* element : unsafeAssociatedElements()) {
-        if (element->isEnumeratable())
-            ++length;
-    }
-    return length;
-}
-
 void HTMLFieldSetElement::addInvalidDescendant(const HTMLFormControlElement& invalidFormControlElement)
 {
     ASSERT_WITH_MESSAGE(!is<HTMLFieldSetElement>(invalidFormControlElement), "FieldSet are never candidates for constraint validation.");

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.h (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.h	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.h	2018-10-03 00:26:41 UTC (rev 236778)
@@ -38,13 +38,8 @@
 
     HTMLLegendElement* legend() const;
 
-    Ref<HTMLFormControlsCollection> elements();
-    Ref<HTMLCollection> elementsForNativeBindings();
+    Ref<HTMLCollection> elements();
 
-    const Vector<FormAssociatedElement*>& unsafeAssociatedElements() const;
-    Vector<Ref<FormAssociatedElement>> copyAssociatedElementsVector() const;
-    unsigned length() const;
-
     void addInvalidDescendant(const HTMLFormControlElement&);
     void removeInvalidDescendant(const HTMLFormControlElement&);
 
@@ -65,11 +60,6 @@
     bool matchesValidPseudoClass() const final;
     bool matchesInvalidPseudoClass() const final;
 
-    void updateAssociatedElements() const;
-
-    mutable Vector<FormAssociatedElement*> m_associatedElements;
-    // When the DOM tree is modified, we have to refresh the m_associatedElements array.
-    mutable uint64_t m_documentVersion { 0 };
     HashSet<const HTMLFormControlElement*> m_invalidDescendants;
     bool m_hasDisabledAttribute { false };
 };

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.idl (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.idl	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.idl	2018-10-03 00:26:41 UTC (rev 236778)
@@ -24,7 +24,7 @@
 
     readonly attribute DOMString type;
 
-    readonly attribute HTMLFormControlsCollection elements;
+    readonly attribute HTMLCollection elements;
 
     readonly attribute boolean         willValidate;
     readonly attribute ValidityState   validity;

Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp	2018-10-03 00:26:41 UTC (rev 236778)
@@ -23,7 +23,6 @@
 #include "config.h"
 #include "HTMLFormControlsCollection.h"
 
-#include "HTMLFieldSetElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLImageElement.h"
 #include "HTMLNames.h"
@@ -41,7 +40,7 @@
     , m_cachedElement(nullptr)
     , m_cachedElementOffsetInArray(0)
 {
-    ASSERT(is<HTMLFormElement>(ownerNode) || is<HTMLFieldSetElement>(ownerNode));
+    ASSERT(is<HTMLFormElement>(ownerNode));
 }
 
 Ref<HTMLFormControlsCollection> HTMLFormControlsCollection::create(ContainerNode& ownerNode, CollectionType)
@@ -65,24 +64,17 @@
 
 const Vector<FormAssociatedElement*>& HTMLFormControlsCollection::unsafeFormControlElements() const
 {
-    ASSERT(is<HTMLFormElement>(ownerNode()) || is<HTMLFieldSetElement>(ownerNode()));
-    if (is<HTMLFormElement>(ownerNode()))
-        return downcast<HTMLFormElement>(ownerNode()).unsafeAssociatedElements();
-    return downcast<HTMLFieldSetElement>(ownerNode()).unsafeAssociatedElements();
+    return ownerNode().unsafeAssociatedElements();
 }
 
 Vector<Ref<FormAssociatedElement>> HTMLFormControlsCollection::copyFormControlElementsVector() const
 {
-    ASSERT(is<HTMLFormElement>(ownerNode()) || is<HTMLFieldSetElement>(ownerNode()));
-    if (is<HTMLFormElement>(ownerNode()))
-        return downcast<HTMLFormElement>(ownerNode()).copyAssociatedElementsVector();
-    return downcast<HTMLFieldSetElement>(ownerNode()).copyAssociatedElementsVector();
+    return ownerNode().copyAssociatedElementsVector();
 }
 
 const Vector<HTMLImageElement*>& HTMLFormControlsCollection::formImageElements() const
 {
-    ASSERT(is<HTMLFormElement>(ownerNode()));
-    return downcast<HTMLFormElement>(ownerNode()).imageElements();
+    return ownerNode().imageElements();
 }
 
 static unsigned findFormAssociatedElement(const Vector<FormAssociatedElement*>& elements, const Element& element)
@@ -118,6 +110,11 @@
     return nullptr;
 }
 
+HTMLFormElement& HTMLFormControlsCollection::ownerNode() const
+{
+    return downcast<HTMLFormElement>(CachedHTMLCollection<HTMLFormControlsCollection, CollectionTypeTraits<FormControls>::traversalType>::ownerNode());
+}
+
 void HTMLFormControlsCollection::updateNamedElementCache() const
 {
     if (hasNamedElementCache())
@@ -125,7 +122,6 @@
 
     auto cache = std::make_unique<CollectionNamedElementCache>();
 
-    bool ownerIsFormElement = is<HTMLFormElement>(ownerNode());
     HashSet<AtomicStringImpl*> foundInputElements;
 
     ScriptDisallowedScope::InMainThread scriptDisallowedScope;
@@ -136,27 +132,24 @@
             const AtomicString& id = element.getIdAttribute();
             if (!id.isEmpty()) {
                 cache->appendToIdCache(id, element);
-                if (ownerIsFormElement)
-                    foundInputElements.add(id.impl());
+                foundInputElements.add(id.impl());
             }
             const AtomicString& name = element.getNameAttribute();
             if (!name.isEmpty() && id != name) {
                 cache->appendToNameCache(name, element);
-                if (ownerIsFormElement)
-                    foundInputElements.add(name.impl());
+                foundInputElements.add(name.impl());
             }
         }
     }
-    if (ownerIsFormElement) {
-        for (auto* elementPtr : formImageElements()) {
-            HTMLImageElement& element = *elementPtr;
-            const AtomicString& id = element.getIdAttribute();
-            if (!id.isEmpty() && !foundInputElements.contains(id.impl()))
-                cache->appendToIdCache(id, element);
-            const AtomicString& name = element.getNameAttribute();
-            if (!name.isEmpty() && id != name && !foundInputElements.contains(name.impl()))
-                cache->appendToNameCache(name, element);
-        }
+
+    for (auto* elementPtr : formImageElements()) {
+        HTMLImageElement& element = *elementPtr;
+        const AtomicString& id = element.getIdAttribute();
+        if (!id.isEmpty() && !foundInputElements.contains(id.impl()))
+            cache->appendToIdCache(id, element);
+        const AtomicString& name = element.getNameAttribute();
+        if (!name.isEmpty() && id != name && !foundInputElements.contains(name.impl()))
+            cache->appendToNameCache(name, element);
     }
 
     setNamedItemCache(WTFMove(cache));

Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.h (236777 => 236778)


--- trunk/Source/WebCore/html/HTMLFormControlsCollection.h	2018-10-03 00:25:10 UTC (rev 236777)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.h	2018-10-03 00:26:41 UTC (rev 236778)
@@ -23,7 +23,7 @@
 #pragma once
 
 #include "CachedHTMLCollection.h"
-#include "HTMLElement.h"
+#include "HTMLFormElement.h"
 #include "RadioNodeList.h"
 
 namespace WebCore {
@@ -42,6 +42,8 @@
     HTMLElement* item(unsigned offset) const override;
     std::optional<Variant<RefPtr<RadioNodeList>, RefPtr<Element>>> namedItemOrItems(const String&) const;
 
+    HTMLFormElement& ownerNode() const;
+
     // For CachedHTMLCollection.
     HTMLElement* customElementAfter(Element*) const;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to