Bug 914029 - Fix Assertion failure. r=smaug, a=lsblakk
authorMina Almasry <almasry.mina@hotmail.com>
Wed, 16 Oct 2013 12:43:37 -0400
changeset 160884 a466c52b48050397bec96079ed1e6a9909935e79
parent 160883 e5d6daa4aa4c301bc783b24ada918fc5a1bf043e
child 160885 77d48a04eef0b7c9b3b7b7b338a0619b70649b0c
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, lsblakk
bugs914029
milestone26.0a2
Bug 914029 - Fix Assertion failure. r=smaug, a=lsblakk
content/html/content/src/HTMLFieldSetElement.cpp
content/html/content/test/Makefile.in
content/html/content/test/test_nested_invalid_fieldsets.html
--- a/content/html/content/src/HTMLFieldSetElement.cpp
+++ b/content/html/content/src/HTMLFieldSetElement.cpp
@@ -212,35 +212,104 @@ HTMLFieldSetElement::RemoveChildAt(uint3
   }
 }
 
 void
 HTMLFieldSetElement::AddElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.AppendElement(aElement);
 
+  // If the element that we are adding aElement is a fieldset, then all the
+  // invalid elements in aElement are also invalid elements of this.
+  HTMLFieldSetElement* fieldSet = FromContent(aElement);
+  if (fieldSet) {
+    if (fieldSet->mInvalidElementsCount > 0) {
+      // The order we call UpdateValidity and adjust mInvalidElementsCount is
+      // important. We need to first call UpdateValidity in case
+      // mInvalidElementsCount was 0 before the call and will be incremented to
+      // 1 and so we need to change state to invalid. After that is done, we
+      // are free to increment mInvalidElementsCount to the correct amount.
+      UpdateValidity(false);
+      mInvalidElementsCount += fieldSet->mInvalidElementsCount - 1;
+    }
+    return;
+  }
+
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
       cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
     UpdateValidity(false);
   }
+
+#if DEBUG
+  int32_t debugInvalidElementsCount = 0;
+  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
+    HTMLFieldSetElement* fieldSet = FromContent(mDependentElements[i]);
+    if (fieldSet) {
+      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
+      continue;
+    }
+    nsCOMPtr<nsIConstraintValidation>
+      cvElmt = do_QueryObject(mDependentElements[i]);
+    if (cvElmt &&
+        cvElmt->IsCandidateForConstraintValidation() &&
+        !(cvElmt->IsValid())) {
+      debugInvalidElementsCount += 1;
+    }
+  }
+  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
+#endif
 }
 
 void
 HTMLFieldSetElement::RemoveElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.RemoveElement(aElement);
 
+  // If the element that we are removing aElement is a fieldset, then all the
+  // invalid elements in aElement are also removed from this.
+  HTMLFieldSetElement* fieldSet = FromContent(aElement);
+  if (fieldSet) {
+    if (fieldSet->mInvalidElementsCount > 0) {
+      // The order we update mInvalidElementsCount and call UpdateValidity is
+      // important. We need to first decrement mInvalidElementsCount and then
+      // call UpdateValidity, in case mInvalidElementsCount hits 0 in the call
+      // of UpdateValidity and we have to change state to valid.
+      mInvalidElementsCount -= fieldSet->mInvalidElementsCount - 1;
+      UpdateValidity(true);
+    }
+    return;
+  }
+
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
       cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
     UpdateValidity(true);
   }
+
+#if DEBUG
+  int32_t debugInvalidElementsCount = 0;
+  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
+    HTMLFieldSetElement* fieldSet = FromContent(mDependentElements[i]);
+    if (fieldSet) {
+      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
+      continue;
+    }
+    nsCOMPtr<nsIConstraintValidation>
+      cvElmt = do_QueryObject(mDependentElements[i]);
+    if (cvElmt &&
+        cvElmt->IsCandidateForConstraintValidation() &&
+        !(cvElmt->IsValid())) {
+      debugInvalidElementsCount += 1;
+    }
+  }
+  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
+#endif
 }
 
 void
 HTMLFieldSetElement::NotifyElementsForFirstLegendChange(bool aNotify)
 {
   /**
    * NOTE: this could be optimized if only call when the fieldset is currently
    * disabled.
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -385,16 +385,17 @@ MOCHITEST_FILES = \
 		test_track_disabled.html \
 		test_srcdoc.html \
 		file_srcdoc.html \
 		test_srcdoc-2.html \
 		file_srcdoc-2.html \
 		test_bug893537.html \
 		file_bug893537.html \
 		test_input_files_not_nsIFile.html \
+		test_nested_invalid_fieldsets.html \
 		$(NULL)
 
 MOCHITEST_CHROME_FILES = \
 		test_allowMedia.html \
 		$(NULL)
 
 MOCHITEST_BROWSER_FILES = \
 		browser_bug649778.js \
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_nested_invalid_fieldsets.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=914029
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 914029</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 914029 **/
+
+  var innerFieldset = document.createElement("fieldset");
+  var outerFieldset = document.createElement("fieldset");
+  var textarea = document.createElement("textarea");
+  textarea.setAttribute("required", "");
+  innerFieldset.appendChild(textarea);
+  outerFieldset.appendChild(innerFieldset);
+  SpecialPowers.forceGC();
+  ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+           " work correctly.");
+  var innerFieldset = document.createElement("fieldset");
+  var outerFieldset = document.createElement("fieldset");
+  var textarea = document.createElement("textarea");
+  var textarea2 = document.createElement("textarea");
+  textarea.setAttribute("required", "");
+  innerFieldset.appendChild(textarea);
+  innerFieldset.appendChild(textarea2);
+  outerFieldset.appendChild(innerFieldset);
+  SpecialPowers.forceGC();
+  ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+           " work correctly.");
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=914029">Mozilla Bug 914029</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>