Bug 914029 - Fix Assertion failure. r=smaug
authorMina Almasry <almasry.mina@hotmail.com>
Wed, 16 Oct 2013 12:43:37 -0400
changeset 165204 bf072b9171725d2ddc5b535c42a56f007db383c7
parent 165203 fbbdf3bb140c507af0f6a1bfcedd99c7f39dc712
child 165205 31121f69414d6a5d79c94e21c653018538089213
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs914029
milestone27.0a1
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 914029 - Fix Assertion failure. r=smaug
content/html/content/src/HTMLFieldSetElement.cpp
content/html/content/test/mochitest.ini
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/mochitest.ini
+++ b/content/html/content/test/mochitest.ini
@@ -393,16 +393,17 @@ support-files =
 [test_img_attributes_reflection.html]
 [test_li_attributes_reflection.html]
 [test_link_attributes_reflection.html]
 [test_map_attributes_reflection.html]
 [test_meta_attributes_reflection.html]
 [test_mod_attributes_reflection.html]
 [test_mozaudiochannel.html]
 [test_named_options.html]
+[test_nested_invalid_fieldsets.html]
 [test_object_attributes_reflection.html]
 [test_object_plugin_nav.html]
 [test_ol_attributes_reflection.html]
 [test_param_attributes_reflection.html]
 [test_q_attributes_reflection.html]
 [test_restore_from_parser_fragment.html]
 [test_rowscollection.html]
 [test_srcdoc-2.html]
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>