Bug 595449 - Implement elements IDL attribute for HTMLFieldsetElement. r+a=jst
authorMounir Lamouri <mounir.lamouri@gmail.com>
Wed, 15 Sep 2010 09:55:48 +0200
changeset 53885 275d86ec7eee508569f6885453bdad000b348551
parent 53884 82373b028ee02b096739017e0b24e476e5e71ad7
child 53886 3077db085f3c2de161206c88f02ff459efd64cf3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs595449
milestone2.0b7pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 595449 - Implement elements IDL attribute for HTMLFieldsetElement. r+a=jst
content/html/content/src/nsHTMLFieldSetElement.cpp
content/html/content/test/Makefile.in
content/html/content/test/test_bug595449.html
dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -70,16 +70,27 @@ public:
   NS_DECL_NSIDOMHTMLFIELDSETELEMENT
 
   // nsIFormControl
   NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_FIELDSET; }
   NS_IMETHOD Reset();
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
   virtual nsXPCClassInfo* GetClassInfo();
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLFieldSetElement,
+                                           nsGenericHTMLFormElement)
+private:
+
+  // This function is used to generate the nsContentList (listed form elements).
+  static PRBool MatchListedElements(nsIContent* aContent, PRInt32 aNamespaceID,
+                                    nsIAtom* aAtom, void* aData);
+
+  // listed form controls elements.
+  nsRefPtr<nsContentList> mElements;
 };
 
 // construction, destruction
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet)
 
 
@@ -91,16 +102,26 @@ nsHTMLFieldSetElement::nsHTMLFieldSetEle
 }
 
 nsHTMLFieldSetElement::~nsHTMLFieldSetElement()
 {
 }
 
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHTMLFieldSetElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElements)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLFieldSetElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFieldSetElement,
+                                                  nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mElements, nsIDOMNodeList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_ADDREF_INHERITED(nsHTMLFieldSetElement, nsGenericElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFieldSetElement, nsGenericElement)
 
 DOMCI_NODE_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
 
 // QueryInterface implementation for nsHTMLFieldSetElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLFieldSetElement)
   NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLFieldSetElement,
@@ -128,16 +149,37 @@ nsHTMLFieldSetElement::GetForm(nsIDOMHTM
 
 NS_IMETHODIMP
 nsHTMLFieldSetElement::GetType(nsAString& aType)
 {
   aType.AssignLiteral("fieldset");
   return NS_OK;
 }
 
+/* static */
+PRBool
+nsHTMLFieldSetElement::MatchListedElements(nsIContent* aContent, PRInt32 aNamespaceID,
+                                           nsIAtom* aAtom, void* aData)
+{
+  nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aContent);
+  return formControl && formControl->GetType() != NS_FORM_LABEL;
+}
+
+NS_IMETHODIMP
+nsHTMLFieldSetElement::GetElements(nsIDOMHTMLCollection** aElements)
+{
+  if (!mElements) {
+    mElements = new nsContentList(this, MatchListedElements, nsnull, nsnull, PR_TRUE);
+  }
+
+  NS_ADDREF(*aElements = mElements);
+
+  return NS_OK;
+}
+
 // nsIFormControl
 
 nsresult
 nsHTMLFieldSetElement::Reset()
 {
   return NS_OK;
 }
 
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -222,12 +222,13 @@ include $(topsrcdir)/config/rules.mk
 		test_bug556013.html \
 		test_bug590363.html \
 		test_bug557628-1.html \
 		test_bug557628-2.html \
 		test_bug592802.html \
 		test_bug589696.html \
 		test_bug595429.html \
 		test_bug595447.html \
+		test_bug595449.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug595449.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=595449
+-->
+<head>
+  <title>Test for Bug 595449</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595449">Mozilla Bug 595449</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 595449 **/
+
+var fieldset = document.createElement("fieldset");
+
+ok("elements" in fieldset,
+   "fieldset element should have an 'elements' IDL attribute");
+
+ok(fieldset.elements instanceof HTMLCollection,
+   "fieldset.elements should be an instance of HTMLCollection");
+
+var catched = false;
+try {
+  ok(fieldset.elements instanceof HTMLFormControlsCollection,
+     "fieldset.elements should be an instance of HTMLFormControlsCollection");
+} catch(e) {
+  catched = true;
+}
+todo(!catched, "HTMLFormControlsCollection should be defined");
+
+is(fieldset.elements.length, 0, "Nothing should be in fieldset.elements");
+
+var oldElements = fieldset.elements;
+
+is(fieldset.elements, oldElements,
+   "fieldset.elements should always return the same object");
+
+var tmpElement = document.createElement("input");
+
+fieldset.appendChild(tmpElement);
+
+is(fieldset.elements.length, 1,
+   "fieldset.elements should now contain one element");
+
+is(fieldset.elements[0], tmpElement,
+   "fieldset.elements[0] should be the input element");
+
+tmpElement.name = "foo";
+is(fieldset.elements.foo, tmpElement,
+   "we should be able to access to an element using it's name as a property on .elements");
+
+is(fieldset.elements, oldElements,
+   "fieldset.elements should always return the same object");
+
+fieldset.removeChild(tmpElement);
+
+var testData = [
+  [ "<input>", 1 , [ HTMLInputElement ] ],
+  [ "<button></button>", 1, [ HTMLButtonElement ] ],
+  [ "<button><input></button>", 2, [ HTMLButtonElement, HTMLInputElement ] ],
+  [ "<object>", 1, [ HTMLObjectElement ] ],
+  [ "<output></output>", 1, [ HTMLOutputElement ] ],
+  [ "<select></select>", 1, [ HTMLSelectElement ] ],
+  [ "<select><option>foo</option></select>", 1, [ HTMLSelectElement ] ],
+  [ "<select><option>foo</option><input></select>", 2, [ HTMLSelectElement, HTMLInputElement ] ],
+  [ "<textarea></textarea>", 1, [ HTMLTextAreaElement ] ],
+  [ "<label>foo</label>", 0 ],
+  [ "<progress>", 0 ],
+  [ "<meter>", 0 ],
+  [ "<keygen>", 1, [ HTMLSelectElement ] ],
+  [ "<legend></legend>", 0 ],
+  [ "<legend><input></legend>", 1, [ HTMLInputElement ] ],
+  [ "<legend><input></legend><legend><input></legend>", 2, [ HTMLInputElement, HTMLInputElement ] ],
+  [ "<legend><input></legend><input>", 2, [ HTMLInputElement, HTMLInputElement ] ],
+  [ "<fieldset></fieldset>", 1, [ HTMLFieldSetElement ] ],
+  [ "<fieldset><input></fieldset>", 2, [ HTMLFieldSetElement, HTMLInputElement ] ],
+  [ "<fieldset><fieldset><input></fieldset></fieldset>", 3, [ HTMLFieldSetElement, HTMLFieldSetElement, HTMLInputElement ] ],
+  [ "<button></button><fieldset></fieldset><input><keygen><object><output></output><select></select><textarea></textarea>", 8, [ HTMLButtonElement, HTMLFieldSetElement, HTMLInputElement, HTMLSelectElement, HTMLObjectElement, HTMLOutputElement, HTMLSelectElement, HTMLTextAreaElement ] ],
+];
+
+for each(var data in testData) {
+  fieldset.innerHTML = data[0];
+  is(fieldset.elements.length, data[1],
+     "fieldset.elements should contain " + data[1] + " elements");
+
+  for (var i=0; i<data[1]; ++i) {
+    ok(fieldset.elements[i] instanceof data[2][i],
+       "fieldset.elements[" + i + "] should be instance of " + data[2][i])
+  }
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLFieldSetElement.idl
@@ -44,24 +44,26 @@
  * [X]HTML fieldset element.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  */
 
 interface nsIDOMValidityState;
 
-[scriptable, uuid(8e89ae21-c666-4027-a1c7-bbc8f3d0a37a)]
+[scriptable, uuid(b38efb33-ec68-487a-bf9b-2920425fa408)]
 interface nsIDOMHTMLFieldSetElement : nsIDOMHTMLElement
 {
   readonly attribute nsIDOMHTMLFormElement  form;
            attribute DOMString              name;
 
   readonly attribute DOMString              type;
 
+  readonly attribute nsIDOMHTMLCollection   elements;
+
   // The following lines are parte of the constraint validation API, see:
   // http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
   readonly attribute boolean               willValidate;
   readonly attribute nsIDOMValidityState   validity;
   readonly attribute DOMString             validationMessage;
   boolean checkValidity();
   void setCustomValidity(in DOMString error);
 };