Bug 932755 - Add support for input/textarea minLength and tooShort. r=mrbkap
authorThomas Wisniewski <wisniewskit@gmail.com>
Wed, 17 Aug 2016 00:11:24 -0400
changeset 353516 f4d0e045901e5ef4698a0635723f2ca2d488ec57
parent 353341 73a588493cbeef5fac53a63420ad82c5fac52185
child 353517 7497dca8bbb5a00ee46bf65da8884b0af8a2f26b
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs932755
milestone51.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 932755 - Add support for input/textarea minLength and tooShort. r=mrbkap
accessible/tests/mochitest/states/test_inputs.html
dom/base/nsGkAtomList.h
dom/base/nsTreeSanitizer.cpp
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLTextAreaElement.cpp
dom/html/HTMLTextAreaElement.h
dom/html/ValidityState.cpp
dom/html/ValidityState.h
dom/html/nsIConstraintValidation.cpp
dom/html/nsIConstraintValidation.h
dom/html/test/forms/mochitest.ini
dom/html/test/forms/test_maxlength_attribute.html
dom/html/test/forms/test_minlength_attribute.html
dom/html/test/test_bug536891.html
dom/html/test/test_bug558788-2.html
dom/html/test/test_bug613019.html
dom/interfaces/html/nsIDOMHTMLInputElement.idl
dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl
dom/interfaces/html/nsIDOMValidityState.idl
dom/locales/en-US/chrome/dom/dom.properties
dom/tests/mochitest/ajax/jquery/test/index.html
dom/tests/mochitest/ajax/jquery/test/unit/core.js
dom/tests/mochitest/ajax/prototype/test/unit/dom_test.js
dom/webidl/HTMLInputElement.webidl
dom/webidl/HTMLTextAreaElement.webidl
dom/webidl/ValidityState.webidl
layout/base/tests/input-invalid-ref.html
layout/base/tests/input-maxlength-invalid-change.html
layout/base/tests/input-maxlength-ui-invalid-change.html
layout/base/tests/input-maxlength-ui-valid-change.html
layout/base/tests/input-maxlength-valid-before-change.html
layout/base/tests/input-maxlength-valid-change.html
layout/base/tests/input-minlength-invalid-change.html
layout/base/tests/input-minlength-ui-invalid-change.html
layout/base/tests/input-minlength-ui-valid-change.html
layout/base/tests/input-minlength-valid-before-change.html
layout/base/tests/input-minlength-valid-change.html
layout/base/tests/input-ui-valid-ref.html
layout/base/tests/input-valid-ref.html
layout/base/tests/mochitest.ini
layout/base/tests/test_reftests_with_caret.html
layout/base/tests/textarea-invalid-ref.html
layout/base/tests/textarea-maxlength-invalid-change.html
layout/base/tests/textarea-maxlength-ui-invalid-change.html
layout/base/tests/textarea-maxlength-ui-valid-change.html
layout/base/tests/textarea-maxlength-valid-before-change.html
layout/base/tests/textarea-maxlength-valid-change.html
layout/base/tests/textarea-minlength-invalid-change.html
layout/base/tests/textarea-minlength-ui-invalid-change.html
layout/base/tests/textarea-minlength-ui-valid-change.html
layout/base/tests/textarea-minlength-valid-before-change.html
layout/base/tests/textarea-minlength-valid-change.html
layout/base/tests/textarea-valid-ref.html
layout/reftests/css-invalid/input/input-maxlength-invalid.html
layout/reftests/css-invalid/input/input-maxlength-valid.html
layout/reftests/css-invalid/input/reftest.list
layout/reftests/css-invalid/textarea/reftest.list
layout/reftests/css-invalid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-invalid/textarea/textarea-maxlength-valid.html
layout/reftests/css-ui-invalid/input/input-maxlength-invalid-changed.html
layout/reftests/css-ui-invalid/input/input-maxlength-invalid-default.html
layout/reftests/css-ui-invalid/input/input-maxlength-valid.html
layout/reftests/css-ui-invalid/input/reftest.list
layout/reftests/css-ui-invalid/textarea/reftest.list
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-default-value-invalid.html
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-ui-invalid/textarea/textarea-maxlength-valid.html
layout/reftests/css-ui-valid/input/input-maxlength-invalid.html
layout/reftests/css-ui-valid/input/input-maxlength-valid-changed.html
layout/reftests/css-ui-valid/input/input-maxlength-valid.html
layout/reftests/css-ui-valid/input/reftest.list
layout/reftests/css-ui-valid/textarea/reftest.list
layout/reftests/css-ui-valid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid-changed.html
layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid.html
layout/reftests/css-valid/input/input-maxlength-invalid.html
layout/reftests/css-valid/input/input-maxlength-valid.html
layout/reftests/css-valid/input/reftest.list
layout/reftests/css-valid/textarea/reftest.list
layout/reftests/css-valid/textarea/textarea-maxlength-invalid.html
layout/reftests/css-valid/textarea/textarea-maxlength-valid.html
testing/web-platform/meta/html/dom/interfaces.html.ini
testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-tooShort.html.ini
testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -2,16 +2,18 @@
 <html>
 <head>
   <title>HTML input states</title>
   <link rel="stylesheet" type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
@@ -68,45 +70,56 @@
     ////////////////////////////////////////////////////////////////////////////
     // inherited from file control
     var fileBrowseButton = getAccessible("file").firstChild;
     testStates(fileBrowseButton, STATE_UNAVAILABLE | STATE_REQUIRED);
     // No states on the label.
 
     ////////////////////////////////////////////////////////////////////////////
     // 'invalid' state
-
-    // XXX: maxlength doesn't make the element invalid until bug 613016 and
-    // bug 613019 are fixed. Commenting out related lines and adding a todo to
-    // make sure it will be uncommented as soon as possible.
-    var todoInput = document.createElement("input");
-    todoInput.maxLength = '2';
-    todoInput.value = 'foo';
-    todo(!todoInput.validity.valid,
-         "input should be invalid because of maxlength");
-
-    // invalid/valid state
-    //var invalid = ["maxlength","pattern","email","url"];
-    //document.getElementById("maxlength").value = "i am too long";
     var invalid = ["pattern","email","url"];
     for (i in invalid) {
       testStates(invalid[i], STATE_INVALID);
       testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
     }
 
-    // invalid/valid state
-    //var invalid = ["maxlength","pattern","email","url"];
-    //document.getElementById("maxlength").value = "i am too long";
-    var invalid = ["pattern","email","url"];
-    for (i in invalid) {
-      testStates(invalid[i], STATE_INVALID);
-      testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
+    ////////////////////////////////////////////////////////////////////////////
+    // not 'invalid' state
+    // (per spec, min/maxlength are always valid until interactively edited)
+    var validInput = document.createElement("input");
+    validInput.maxLength = '0';
+    validInput.value = 'a';
+    ok(validInput.validity.valid,
+       "input should be valid despite maxlength (no interactive edits)");
+
+    var validInput2 = document.createElement("input");
+    validInput2.minLength = '1';
+    validInput2.value = '';
+    ok(validInput2.validity.valid,
+       "input should be valid despite minlength (no interactive edits)");
+
+    var valid = ["minlength","maxlength"];
+    for (i in valid) {
+      testStates(valid[i], 0, 0, STATE_INVALID);
+      testStates(valid[i] + "2", 0, 0, STATE_INVALID);
     }
 
     ////////////////////////////////////////////////////////////////////////////
+    // 'invalid' state
+    // (per spec, min/maxlength validity is affected by interactive edits)
+    var mininp = document.getElementById("minlength");
+    mininp.focus();
+    synthesizeKey("VK_BACK_SPACE", {});
+    ok(!mininp.validity.valid,
+       "input should be invalid after interactive edits");
+    testStates(mininp, STATE_INVALID);
+    // inputs currently cannot be made longer than maxlength interactively,
+    // so we're not testing that case.
+
+    ////////////////////////////////////////////////////////////////////////////
     // autocomplete states
     testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-formoff", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-list2", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-tel", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     testStates("autocomplete-email", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
@@ -209,28 +222,20 @@
     <input id="f_input">
     <input id="f_input_disabled" disabled>
   </fieldset>
 
   <!-- inherited from input@type="file" -->
   <input id="file" type="file" required disabled>
 
   <!-- invalid/valid -->
-  <input id="maxlength" maxlength="1">
+  <input id="maxlength" maxlength="1" value="f">
   <input id="maxlength2" maxlength="100" value="foo">
-  <input id="pattern" pattern="bar" value="foo">
-  <input id="pattern2" pattern="bar" value="bar">
-  <input id="email" type="email" value="foo">
-  <input id="email2" type="email" value="foo@bar.com">
-  <input id="url" type="url" value="foo">
-  <input id="url2" type="url" value="http://mozilla.org/">
-
-  <!-- invalid/valid -->
-  <input id="maxlength" maxlength="1">
-  <input id="maxlength2" maxlength="100" value="foo">
+  <input id="minlength" minlength="2" value="fo">
+  <input id="minlength2" minlength="1" value="foo">
   <input id="pattern" pattern="bar" value="foo">
   <input id="pattern2" pattern="bar" value="bar">
   <input id="email" type="email" value="foo">
   <input id="email2" type="email" value="foo@bar.com">
   <input id="url" type="url" value="foo">
   <input id="url2" type="url" value="http://mozilla.org/">
 
   <!-- autocomplete -->
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -602,16 +602,17 @@ GK_ATOM(referrer, "referrer")
 GK_ATOM(referrerpolicy, "referrerpolicy")
 GK_ATOM(headerReferrerPolicy, "referrer-policy")
 GK_ATOM(meter, "meter")
 GK_ATOM(method, "method")
 GK_ATOM(middle, "middle")
 GK_ATOM(min, "min")
 GK_ATOM(minheight, "minheight")
 GK_ATOM(minimum_scale, "minimum-scale")
+GK_ATOM(minlength, "minlength")
 GK_ATOM(minpos, "minpos")
 GK_ATOM(minusSign, "minus-sign")
 GK_ATOM(minwidth, "minwidth")
 GK_ATOM(_mixed, "mixed")
 GK_ATOM(messagemanagergroup, "messagemanagergroup")
 GK_ATOM(mod, "mod")
 GK_ATOM(mode, "mode")
 GK_ATOM(modifiers, "modifiers")
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -198,16 +198,17 @@ nsIAtom** const kAttributesHTML[] = {
   &nsGkAtoms::longdesc,
   &nsGkAtoms::loop,
   &nsGkAtoms::low,
   &nsGkAtoms::max,
   &nsGkAtoms::maxlength,
   &nsGkAtoms::media,
   &nsGkAtoms::method,
   &nsGkAtoms::min,
+  &nsGkAtoms::minlength,
   &nsGkAtoms::multiple,
   &nsGkAtoms::muted,
   &nsGkAtoms::name,
   &nsGkAtoms::nohref,
   &nsGkAtoms::novalidate,
   &nsGkAtoms::nowrap,
   &nsGkAtoms::open,
   &nsGkAtoms::optimum,
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1462,18 +1462,20 @@ HTMLInputElement::AfterSetAttr(int32_t a
     if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
         aName == nsGkAtoms::readonly) {
       UpdateValueMissingValidityState();
 
       // This *has* to be called *after* validity has changed.
       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
         UpdateBarredFromConstraintValidation();
       }
-    } else if (MaxLengthApplies() && aName == nsGkAtoms::maxlength) {
+    } else if (MinOrMaxLengthApplies() && aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
+    } else if (MinOrMaxLengthApplies() && aName == nsGkAtoms::minlength) {
+      UpdateTooShortValidityState();
     } else if (aName == nsGkAtoms::pattern && !mParserCreating) {
       UpdatePatternMismatchValidityState();
     } else if (aName == nsGkAtoms::multiple) {
       UpdateTypeMismatchValidityState();
     } else if (aName == nsGkAtoms::max) {
       UpdateHasRange();
       if (mType == NS_FORM_INPUT_RANGE) {
         // The value may need to change when @max changes since the value may
@@ -1584,16 +1586,17 @@ NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALI
 NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(HTMLInputElement, FormMethod, formmethod,
                                                  "", kFormDefaultMethod->tag)
 NS_IMPL_BOOL_ATTR(HTMLInputElement, FormNoValidate, formnovalidate)
 NS_IMPL_STRING_ATTR(HTMLInputElement, FormTarget, formtarget)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, InputMode, inputmode,
                                 kInputDefaultInputmode->tag)
 NS_IMPL_BOOL_ATTR(HTMLInputElement, Multiple, multiple)
 NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLInputElement, MaxLength, maxlength)
+NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLInputElement, MinLength, minlength)
 NS_IMPL_STRING_ATTR(HTMLInputElement, Name, name)
 NS_IMPL_BOOL_ATTR(HTMLInputElement, ReadOnly, readonly)
 NS_IMPL_BOOL_ATTR(HTMLInputElement, Required, required)
 NS_IMPL_URI_ATTR(HTMLInputElement, Src, src)
 NS_IMPL_STRING_ATTR(HTMLInputElement, Step, step)
 NS_IMPL_STRING_ATTR(HTMLInputElement, UseMap, usemap)
 //NS_IMPL_STRING_ATTR(HTMLInputElement, Value, value)
 NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLInputElement, Size, size, DEFAULT_COLS)
@@ -5328,16 +5331,19 @@ HTMLInputElement::ParseAttribute(int32_t
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::height) {
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::maxlength) {
       return aResult.ParseNonNegativeIntValue(aValue);
     }
+    if (aAttribute == nsGkAtoms::minlength) {
+      return aResult.ParseNonNegativeIntValue(aValue);
+    }
     if (aAttribute == nsGkAtoms::size) {
       return aResult.ParsePositiveIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::border) {
       return aResult.ParseIntWithBounds(aValue, 0);
     }
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
@@ -7000,17 +7006,17 @@ HTMLInputElement::SetCustomValidity(cons
   return NS_OK;
 }
 
 bool
 HTMLInputElement::IsTooLong()
 {
   if (!mValueChanged ||
       !mLastValueChangeWasInteractive ||
-      !MaxLengthApplies() ||
+      !MinOrMaxLengthApplies() ||
       !HasAttr(kNameSpaceID_None, nsGkAtoms::maxlength)) {
     return false;
   }
 
   int32_t maxLength = MaxLength();
 
   // Maxlength of -1 means parsing error.
   if (maxLength == -1) {
@@ -7019,16 +7025,39 @@ HTMLInputElement::IsTooLong()
 
   int32_t textLength = -1;
   GetTextLength(&textLength);
 
   return textLength > maxLength;
 }
 
 bool
+HTMLInputElement::IsTooShort()
+{
+  if (!mValueChanged ||
+      !mLastValueChangeWasInteractive ||
+      !MinOrMaxLengthApplies() ||
+      !HasAttr(kNameSpaceID_None, nsGkAtoms::minlength)) {
+    return false;
+  }
+
+  int32_t minLength = MinLength();
+
+  // Minlength of -1 means parsing error.
+  if (minLength == -1) {
+    return false;
+  }
+
+  int32_t textLength = -1;
+  GetTextLength(&textLength);
+
+  return textLength && textLength < minLength;
+}
+
+bool
 HTMLInputElement::IsValueMissing() const
 {
   // Should use UpdateValueMissingValidityStateForRadio() for type radio.
   MOZ_ASSERT(mType != NS_FORM_INPUT_RADIO);
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) ||
       !DoesRequiredApply()) {
     return false;
@@ -7280,16 +7309,22 @@ HTMLInputElement::HasBadInput() const
 
 void
 HTMLInputElement::UpdateTooLongValidityState()
 {
   SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
 }
 
 void
+HTMLInputElement::UpdateTooShortValidityState()
+{
+  SetValidityState(VALIDITY_STATE_TOO_SHORT, IsTooShort());
+}
+
+void
 HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
 {
   bool notify = !mParserCreating;
   nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
 
   aIgnoreSelf = aIgnoreSelf || !IsMutable();
 
   // If there is no selection, that might mean the radio is not in a group.
@@ -7379,16 +7414,17 @@ HTMLInputElement::UpdateBadInputValidity
   SetValidityState(VALIDITY_STATE_BAD_INPUT, HasBadInput());
 }
 
 void
 HTMLInputElement::UpdateAllValidityStates(bool aNotify)
 {
   bool validBefore = IsValid();
   UpdateTooLongValidityState();
+  UpdateTooShortValidityState();
   UpdateValueMissingValidityState();
   UpdateTypeMismatchValidityState();
   UpdatePatternMismatchValidityState();
   UpdateRangeOverflowValidityState();
   UpdateRangeUnderflowValidityState();
   UpdateStepMismatchValidityState();
   UpdateBadInputValidityState();
 
@@ -7437,16 +7473,36 @@ HTMLInputElement::GetValidationMessage(n
 
       const char16_t* params[] = { strMaxLength.get(), strTextLength.get() };
       rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                  "FormValidationTextTooLong",
                                                  params, message);
       aValidationMessage = message;
       break;
     }
+    case VALIDITY_STATE_TOO_SHORT:
+    {
+      nsXPIDLString message;
+      int32_t minLength = MinLength();
+      int32_t textLength = -1;
+      nsAutoString strMinLength;
+      nsAutoString strTextLength;
+
+      GetTextLength(&textLength);
+
+      strMinLength.AppendInt(minLength);
+      strTextLength.AppendInt(textLength);
+
+      const char16_t* params[] = { strMinLength.get(), strTextLength.get() };
+      rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
+                                                 "FormValidationTextTooShort",
+                                                 params, message);
+      aValidationMessage = message;
+      break;
+    }
     case VALIDITY_STATE_VALUE_MISSING:
     {
       nsXPIDLString message;
       nsAutoCString key;
       switch (mType)
       {
         case NS_FORM_INPUT_FILE:
           key.AssignLiteral("FormValidationFileMissing");
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -301,24 +301,26 @@ public:
   nsTextEditorState::SelectionProperties& GetSelectionProperties()
   {
     MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
     return mSelectionProperties;
   }
 
   // nsIConstraintValidation
   bool     IsTooLong();
+  bool     IsTooShort();
   bool     IsValueMissing() const;
   bool     HasTypeMismatch() const;
   bool     HasPatternMismatch() const;
   bool     IsRangeOverflow() const;
   bool     IsRangeUnderflow() const;
   bool     HasStepMismatch(bool aUseZeroIfValueNaN = false) const;
   bool     HasBadInput() const;
   void     UpdateTooLongValidityState();
+  void     UpdateTooShortValidityState();
   void     UpdateValueMissingValidityState();
   void     UpdateTypeMismatchValidityState();
   void     UpdatePatternMismatchValidityState();
   void     UpdateRangeOverflowValidityState();
   void     UpdateRangeUnderflowValidityState();
   void     UpdateStepMismatchValidityState();
   void     UpdateBadInputValidityState();
   void     UpdateAllValidityStates(bool aNotify);
@@ -529,24 +531,41 @@ public:
 
   int32_t MaxLength() const
   {
     return GetIntAttr(nsGkAtoms::maxlength, -1);
   }
 
   void SetMaxLength(int32_t aValue, ErrorResult& aRv)
   {
-    if (aValue < 0) {
+    int32_t minLength = MinLength();
+    if (aValue < 0 || (minLength >= 0 && aValue < minLength)) {
       aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
       return;
     }
 
     SetHTMLIntAttr(nsGkAtoms::maxlength, aValue, aRv);
   }
 
+  int32_t MinLength() const
+  {
+    return GetIntAttr(nsGkAtoms::minlength, -1);
+  }
+
+  void SetMinLength(int32_t aValue, ErrorResult& aRv)
+  {
+    int32_t maxLength = MaxLength();
+    if (aValue < 0 || (maxLength >= 0 && aValue > maxLength)) {
+      aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+      return;
+    }
+
+    SetHTMLIntAttr(nsGkAtoms::minlength, aValue, aRv);
+  }
+
   // XPCOM GetMin() is OK
   void SetMin(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::min, aValue, aRv);
   }
 
   bool Multiple() const
   {
@@ -1044,19 +1063,19 @@ protected:
   }
 
   /**
    * Returns if autocomplete attribute applies for the current type.
    */
   bool DoesAutocompleteApply() const;
 
   /**
-   * Returns if the maxlength attribute applies for the current type.
+   * Returns if the minlength or maxlength attributes apply for the current type.
    */
-  bool MaxLengthApplies() const { return IsSingleLineTextControl(false, mType); }
+  bool MinOrMaxLengthApplies() const { return IsSingleLineTextControl(false, mType); }
 
   void FreeData();
   nsTextEditorState *GetEditorState() const;
 
   /**
    * Manages the internal data storage across type changes.
    */
   void HandleTypeChange(uint8_t aNewType);
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -188,16 +188,17 @@ HTMLTextAreaElement::IsHTMLFocusable(boo
   *aIsFocusable = !IsDisabled();
   return false;
 }
 
 NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Autofocus, autofocus)
 NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLTextAreaElement, Cols, cols, DEFAULT_COLS)
 NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Disabled, disabled)
 NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLTextAreaElement, MaxLength, maxlength)
+NS_IMPL_NON_NEGATIVE_INT_ATTR(HTMLTextAreaElement, MinLength, minlength)
 NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Name, name)
 NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, ReadOnly, readonly)
 NS_IMPL_BOOL_ATTR(HTMLTextAreaElement, Required, required)
 NS_IMPL_UINT_ATTR_NON_ZERO_DEFAULT_VALUE(HTMLTextAreaElement, Rows, rows, DEFAULT_ROWS_TEXTAREA)
 NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Wrap, wrap)
 NS_IMPL_STRING_ATTR(HTMLTextAreaElement, Placeholder, placeholder)
   
 int32_t
@@ -393,17 +394,18 @@ HTMLTextAreaElement::SetDefaultValue(con
 
 bool
 HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::maxlength) {
+    if (aAttribute == nsGkAtoms::maxlength ||
+        aAttribute == nsGkAtoms::minlength) {
       return aResult.ParseNonNegativeIntValue(aValue);
     } else if (aAttribute == nsGkAtoms::cols ||
                aAttribute == nsGkAtoms::rows) {
       return aResult.ParsePositiveIntValue(aValue);
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
@@ -1312,16 +1314,18 @@ HTMLTextAreaElement::AfterSetAttr(int32_
       UpdateValueMissingValidityState();
 
       // This *has* to be called *after* validity has changed.
       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
         UpdateBarredFromConstraintValidation();
       }
     } else if (aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
+    } else if (aName == nsGkAtoms::minlength) {
+      UpdateTooShortValidityState();
     }
 
     UpdateState(aNotify);
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
                                                          aNotify);
   }
@@ -1386,32 +1390,61 @@ HTMLTextAreaElement::IsTooLong()
 
   int32_t textLength = -1;
   GetTextLength(&textLength);
 
   return textLength > maxLength;
 }
 
 bool
+HTMLTextAreaElement::IsTooShort()
+{
+  if (!mValueChanged ||
+      !mLastValueChangeWasInteractive ||
+      !HasAttr(kNameSpaceID_None, nsGkAtoms::minlength)) {
+    return false;
+  }
+
+  int32_t minLength = -1;
+  GetMinLength(&minLength);
+
+  // Minlength of -1 means parsing error.
+  if (minLength == -1) {
+    return false;
+  }
+
+  int32_t textLength = -1;
+  GetTextLength(&textLength);
+
+  return textLength && textLength < minLength;
+}
+
+bool
 HTMLTextAreaElement::IsValueMissing() const
 {
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::required) || !IsMutable()) {
     return false;
   }
 
   return IsValueEmpty();
 }
 
 void
 HTMLTextAreaElement::UpdateTooLongValidityState()
 {
   SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
 }
 
 void
+HTMLTextAreaElement::UpdateTooShortValidityState()
+{
+  SetValidityState(VALIDITY_STATE_TOO_SHORT, IsTooShort());
+}
+
+void
 HTMLTextAreaElement::UpdateValueMissingValidityState()
 {
   SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
 }
 
 void
 HTMLTextAreaElement::UpdateBarredFromConstraintValidation()
 {
@@ -1444,16 +1477,37 @@ HTMLTextAreaElement::GetValidationMessag
 
         const char16_t* params[] = { strMaxLength.get(), strTextLength.get() };
         rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                    "FormValidationTextTooLong",
                                                    params, message);
         aValidationMessage = message;
       }
       break;
+    case VALIDITY_STATE_TOO_SHORT:
+      {
+        nsXPIDLString message;
+        int32_t minLength = -1;
+        int32_t textLength = -1;
+        nsAutoString strMinLength;
+        nsAutoString strTextLength;
+
+        GetMinLength(&minLength);
+        GetTextLength(&textLength);
+
+        strMinLength.AppendInt(minLength);
+        strTextLength.AppendInt(textLength);
+
+        const char16_t* params[] = { strMinLength.get(), strTextLength.get() };
+        rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
+                                                   "FormValidationTextTooShort",
+                                                   params, message);
+        aValidationMessage = message;
+      }
+      break;
     case VALIDITY_STATE_VALUE_MISSING:
       {
         nsXPIDLString message;
         rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                                 "FormValidationValueMissing",
                                                 message);
         aValidationMessage = message;
       }
@@ -1552,16 +1606,17 @@ HTMLTextAreaElement::InitializeKeyboardE
 NS_IMETHODIMP_(void)
 HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
 {
   mLastValueChangeWasInteractive = aWasInteractiveUserChange;
 
   // Update the validity state
   bool validBefore = IsValid();
   UpdateTooLongValidityState();
+  UpdateTooShortValidityState();
   UpdateValueMissingValidityState();
 
   if (validBefore != IsValid()) {
     UpdateState(aNotify);
   }
 }
 
 NS_IMETHODIMP_(bool)
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -150,18 +150,20 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement,
                                            nsGenericHTMLFormElementWithState)
 
   // nsIConstraintValidation
   bool     IsTooLong();
+  bool     IsTooShort();
   bool     IsValueMissing() const;
   void     UpdateTooLongValidityState();
+  void     UpdateTooShortValidityState();
   void     UpdateValueMissingValidityState();
   void     UpdateBarredFromConstraintValidation();
   nsresult GetValidationMessage(nsAString& aValidationMessage,
                                 ValidityStateType aType) override;
 
   // Web IDL binding methods
   bool Autofocus()
   {
@@ -194,22 +196,36 @@ public:
   // nsGenericHTMLFormElementWithState::GetForm is fine
   using nsGenericHTMLFormElementWithState::GetForm;
   int32_t MaxLength()
   {
     return GetIntAttr(nsGkAtoms::maxlength, -1);
   }
   void SetMaxLength(int32_t aMaxLength, ErrorResult& aError)
   {
-    if (aMaxLength < 0) {
+    int32_t minLength = MinLength();
+    if (aMaxLength < 0 || (minLength >= 0 && aMaxLength < minLength)) {
       aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     } else {
       SetHTMLIntAttr(nsGkAtoms::maxlength, aMaxLength, aError);
     }
   }
+  int32_t MinLength()
+  {
+    return GetIntAttr(nsGkAtoms::minlength, -1);
+  }
+  void SetMinLength(int32_t aMinLength, ErrorResult& aError)
+  {
+    int32_t maxLength = MaxLength();
+    if (aMinLength < 0 || (maxLength >= 0 && aMinLength > maxLength)) {
+      aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    } else {
+      SetHTMLIntAttr(nsGkAtoms::minlength, aMinLength, aError);
+    }
+  }
   // XPCOM GetName is fine
   void SetName(const nsAString& aName, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aError);
   }
   // XPCOM GetPlaceholder is fine
   void SetPlaceholder(const nsAString& aPlaceholder, ErrorResult& aError)
   {
--- a/dom/html/ValidityState.cpp
+++ b/dom/html/ValidityState.cpp
@@ -51,16 +51,23 @@ ValidityState::GetPatternMismatch(bool* 
 NS_IMETHODIMP
 ValidityState::GetTooLong(bool* aTooLong)
 {
   *aTooLong = TooLong();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+ValidityState::GetTooShort(bool* aTooShort)
+{
+  *aTooShort = TooShort();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 ValidityState::GetRangeUnderflow(bool* aRangeUnderflow)
 {
   *aRangeUnderflow = RangeUnderflow();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetRangeOverflow(bool* aRangeOverflow)
--- a/dom/html/ValidityState.h
+++ b/dom/html/ValidityState.h
@@ -45,16 +45,20 @@ public:
   bool PatternMismatch() const
   {
     return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
   }
   bool TooLong() const
   {
     return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
   }
+  bool TooShort() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_SHORT);
+  }
   bool RangeUnderflow() const
   {
     return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
   }
   bool RangeOverflow() const
   {
     return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
   }
--- a/dom/html/nsIConstraintValidation.cpp
+++ b/dom/html/nsIConstraintValidation.cpp
@@ -74,16 +74,18 @@ nsIConstraintValidation::GetValidationMe
       }
     } else if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR)) {
       aValidationMessage.Assign(mCustomValidity);
       if (aValidationMessage.Length() > sContentSpecifiedMaxLengthMessage) {
         aValidationMessage.Truncate(sContentSpecifiedMaxLengthMessage);
       }
     } else if (GetValidityState(VALIDITY_STATE_TOO_LONG)) {
       GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_LONG);
+    } else if (GetValidityState(VALIDITY_STATE_TOO_SHORT)) {
+      GetValidationMessage(aValidationMessage, VALIDITY_STATE_TOO_SHORT);
     } else if (GetValidityState(VALIDITY_STATE_VALUE_MISSING)) {
       GetValidationMessage(aValidationMessage, VALIDITY_STATE_VALUE_MISSING);
     } else if (GetValidityState(VALIDITY_STATE_TYPE_MISMATCH)) {
       GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH);
     } else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) {
       GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
     } else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW)) {
       GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_OVERFLOW);
--- a/dom/html/nsIConstraintValidation.h
+++ b/dom/html/nsIConstraintValidation.h
@@ -50,17 +50,17 @@ public:
   NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage);
 
   enum ValidityStateType
   {
     VALIDITY_STATE_VALUE_MISSING    = 0x1 <<  0,
     VALIDITY_STATE_TYPE_MISMATCH    = 0x1 <<  1,
     VALIDITY_STATE_PATTERN_MISMATCH = 0x1 <<  2,
     VALIDITY_STATE_TOO_LONG         = 0x1 <<  3,
-  //VALIDITY_STATE_TOO_SHORT        = 0x1 <<  4,
+    VALIDITY_STATE_TOO_SHORT        = 0x1 <<  4,
     VALIDITY_STATE_RANGE_UNDERFLOW  = 0x1 <<  5,
     VALIDITY_STATE_RANGE_OVERFLOW   = 0x1 <<  6,
     VALIDITY_STATE_STEP_MISMATCH    = 0x1 <<  7,
     VALIDITY_STATE_BAD_INPUT        = 0x1 <<  8,
     VALIDITY_STATE_CUSTOM_ERROR     = 0x1 <<  9,
   };
 
   void SetValidityState(ValidityStateType aState,
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -68,16 +68,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = buildapp == 'mulet'
 [test_input_untrusted_key_events.html]
 [test_input_url.html]
 [test_interactive_content_in_label.html]
 [test_label_control_attribute.html]
 [test_label_input_controls.html]
 [test_max_attribute.html]
 [test_maxlength_attribute.html]
+[test_minlength_attribute.html]
 [test_meter_element.html]
 [test_meter_pseudo-classes.html]
 [test_min_attribute.html]
 [test_mozistextfield.html]
 [test_novalidate_attribute.html]
 [test_option_disabled.html]
 [test_option_index_attribute.html]
 [test_option_text.html]
@@ -100,9 +101,9 @@ skip-if = android_version == '18' || os 
 [test_stepup_stepdown.html]
 [test_textarea_attributes_reflection.html]
 [test_validation.html]
 skip-if = buildapp == 'b2g' # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
 [test_valueAsDate_pref.html]
 [test_valueasdate_attribute.html]
 [test_valueasnumber_attribute.html]
 [test_validation_not_in_doc.html]
-[test_reportValidation_preventDefault.html]
\ No newline at end of file
+[test_reportValidation_preventDefault.html]
--- a/dom/html/test/forms/test_maxlength_attribute.html
+++ b/dom/html/test/forms/test_maxlength_attribute.html
@@ -1,27 +1,28 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=345624
 -->
 <head>
   <title>Test for Bug 345624</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style>
     input, textarea { background-color: rgb(0,0,0) !important; }
     :-moz-any(input,textarea):valid   { background-color: rgb(0,255,0) !important; }
     :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
   </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
 <p id="display"></p>
-<div id="content" style="display: none">
+<div id="content">
   <input id='i'>
   <textarea id='t'></textarea>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 345624 **/
 
@@ -32,44 +33,91 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 function checkTooLongValidity(element)
 {
   element.value = "foo";
   ok(!element.validity.tooLong,
     "Element should not be too long when maxlength is not set");
   is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
      "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
 
-  element.maxLength = 3;
+  element.maxLength = 1;
   ok(!element.validity.tooLong,
-    "Element should not be to long when maxlength = value length");
+    "Element should not be too long unless the user edits it");
   is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
      "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
 
-  element.maxLength = 5;
+  element.focus();
+
+  synthesizeKey("VK_BACK_SPACE", {});
+  is(element.value, "fo", "value should have changed");
+  ok(element.validity.tooLong,
+    "Element should be too long after a user edit that does not make it short enough");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  ok(!element.validity.valid, "Element should be invalid");
+  ok(!element.checkValidity(), "The element should not be valid");
+  is(element.validationMessage,
+          "Please shorten this text to 1 characters or less (you are currently using 2 characters).",
+          "The validation message text is not correct");
+
+  synthesizeKey("VK_BACK_SPACE", {});
+  is(element.value, "f", "value should have changed");
   ok(!element.validity.tooLong,
-    "Element should not be too long when maxlength > value length");
+    "Element should not be too long after a user edit makes it short enough");
   is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
      "rgb(0, 255, 0)", ":valid pseudo-class should apply");
-
   ok(element.validity.valid, "Element should be valid");
 
   element.maxLength = 2;
-  todo(element.validity.tooLong,
-       "Element should be too long when maxlength < value length");
-  todo_is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
-          "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  ok(!element.validity.tooLong,
+    "Element should remain valid if maxlength changes but maxlength > length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+
+  element.maxLength = 1;
+  ok(!element.validity.tooLong,
+    "Element should remain valid if maxlength changes but maxlength = length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
 
-  todo(!element.validity.valid,
-       "Element should not be valid when it is too long");
+  element.maxLength = 0;
+  ok(element.validity.tooLong,
+    "Element should become invalid if maxlength changes and maxlength < length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  ok(!element.validity.valid, "Element should be invalid");
+  ok(!element.checkValidity(), "The element should not be valid");
+  is(element.validationMessage,
+          "Please shorten this text to 0 characters or less (you are currently using 1 characters).",
+          "The validation message text is not correct");
 
-  todo_is(element.validationMessage,
-          "Please shorten this text to 2 characters or less (you are currently using 3 characters).",
-          "The validation message text is not correct");
-  todo(!element.checkValidity(), "The element should not be valid");
+  element.maxLength = 1;
+  ok(!element.validity.tooLong,
+    "Element should become valid if maxlength changes and maxlength = length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.value = "test";
+  ok(!element.validity.tooLong,
+    "Element should stay valid after programmatic edit (even if value is too long)");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
   element.setCustomValidity("custom message");
   is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
      "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
   is(element.validationMessage, "custom message",
     "Custom message should be shown instead of too long one");
 }
 
 checkTooLongValidity(document.getElementById('i'));
new file mode 100644
--- /dev/null
+++ b/dom/html/test/forms/test_minlength_attribute.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345624
+-->
+<head>
+  <title>Test for Bug 345624</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    input, textarea { background-color: rgb(0,0,0) !important; }
+    :-moz-any(input,textarea):valid   { background-color: rgb(0,255,0) !important; }
+    :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
+<p id="display"></p>
+<div id="content">
+  <input id='i'>
+  <textarea id='t'></textarea>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345624 **/
+
+/**
+ * This test is checking only tooShort related features
+ * related to constraint validation.
+ */
+
+function checkTooShortValidity(element)
+{
+  element.value = "foo";
+  ok(!element.validity.tooShort,
+    "Element should not be too short when minlength is not set");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.minLength = 5;
+  ok(!element.validity.tooShort,
+    "Element should not be too short unless the user edits it");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.focus();
+
+  synthesizeKey("o", {});
+  is(element.value, "fooo", "value should have changed");
+  ok(element.validity.tooShort,
+    "Element should be too short after a user edit that does not make it short enough");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  ok(!element.validity.valid, "Element should be invalid");
+  ok(!element.checkValidity(), "The element should not be valid");
+  is(element.validationMessage,
+          "Please use at least 5 characters (you are currently using 4 characters).",
+          "The validation message text is not correct");
+
+  synthesizeKey("o", {});
+  is(element.value, "foooo", "value should have changed");
+  ok(!element.validity.tooShort,
+    "Element should not be too short after a user edit makes it long enough");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+
+  element.minLength = 2;
+  ok(!element.validity.tooShort,
+    "Element should remain valid if minlength changes but minlength < length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+
+  element.minLength = 1;
+  ok(!element.validity.tooShort,
+    "Element should remain valid if minlength changes but minlength = length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.minLength = 6;
+  ok(element.validity.tooShort,
+    "Element should become invalid if minlength changes and minlength > length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  ok(!element.validity.valid, "Element should be invalid");
+  ok(!element.checkValidity(), "The element should not be valid");
+  is(element.validationMessage,
+          "Please use at least 6 characters (you are currently using 5 characters).",
+          "The validation message text is not correct");
+
+  element.minLength = 5;
+  ok(!element.validity.tooShort,
+    "Element should become valid if minlength changes and minlength = length");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.value = "test";
+  ok(!element.validity.tooShort,
+    "Element should stay valid after programmatic edit (even if value is too short)");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+  ok(element.validity.valid, "Element should be valid");
+  ok(element.checkValidity(), "The element should be valid");
+
+  element.setCustomValidity("custom message");
+  is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+     "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+  is(element.validationMessage, "custom message",
+    "Custom message should be shown instead of too short one");
+}
+
+checkTooShortValidity(document.getElementById('i'));
+checkTooShortValidity(document.getElementById('t'));
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/html/test/test_bug536891.html
+++ b/dom/html/test/test_bug536891.html
@@ -7,47 +7,61 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 536891</title>
   <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=536891">Mozilla Bug 536891</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-<textarea id="t" maxlength="-2"></textarea>
-<input id="i" type="text" maxlength="-2">
-<input id="p" type="password" maxlength="-2">
+<textarea id="t" maxlength="-2" minlength="-2"></textarea>
+<input id="i" type="text" maxlength="-2" minlength="-2">
+<input id="p" type="password" maxlength="-2" minlength="-2">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 536891 **/
 
-function checkNegativeMaxLength(element)
+function checkNegativeMinMaxLength(element)
 {
-  /* maxLength is set to -2 initially in the document, see above */
-  is(element.maxLength, -1, "negative maxLength should be considered invalid and represented as -1");
-
-  element.setAttribute('maxLength', -15);
-  is(element.maxLength, -1, "negative maxLength is not processed correctly when set dynamically");
-  is(element.getAttribute('maxLength'), "-15", "maxLength attribute doesn't return the correct value");
+  for(let type of ["min", "max"]) {
+    /* value is set to -2 initially in the document, see above */
+    is(element[type + "Length"], -1, "negative " + type + "Length should be considered invalid and represented as -1");
 
-  element.setAttribute('maxLength', 0);
-  is(element.maxLength, 0, "negative maxLength is not processed correctly");
-  element.setAttribute('maxLength', 2147483647); /* PR_INT32_MAX */
-  is(element.maxLength, 2147483647, "negative maxLength is not processed correctly");
-  element.setAttribute('maxLength', -2147483648); /* PR_INT32_MIN */
-  is(element.maxLength, -1, "negative maxLength is not processed correctly");
-  element.setAttribute('maxLength', 'non-numerical-value');
-  is(element.maxLength, -1, "non-numerical value should be considered invalid and represented as -1");
+    // changing the property to an negative value should throw (see bug 536895).
+    for(let value of [-15, -2147483648]) { // PR_INT32_MIN
+      let threw = false;
+      try {
+        element[type + "Length"] = value;
+      } catch(e) {
+        threw = true;
+      }
+      is(threw, true, "setting " + type + "Length property to " + value + " should throw");
+    }
+    element[type + "Length"] = "non-numerical value";
+    is(element[type + "Length"], 0, "setting " + type + "Length property to a non-numerical value should set it to zero");
+
 
-  /* we do not check when changing the value from the DOM because it is throwing an exception, see bug 536895 */
+    element.setAttribute(type + 'Length', -15);
+    is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly when set dynamically");
+    is(element.getAttribute(type + 'Length'), "-15", type + "Length attribute doesn't return the correct value");
+
+    element.setAttribute(type + 'Length', 0);
+    is(element[type + "Length"], 0, "zero " + type + "Length is not processed correctly");
+    element.setAttribute(type + 'Length', 2147483647); // PR_INT32_MAX 
+    is(element[type + "Length"], 2147483647, "negative " + type + "Length is not processed correctly");
+    element.setAttribute(type + 'Length', -2147483648);  // PR_INT32_MIN
+    is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly");
+    element.setAttribute(type + 'Length', 'non-numerical-value');
+    is(element[type + "Length"], -1, "non-numerical value should be considered invalid and represented as -1");
+  }
 }
 
 /* TODO: correct behavior may be checked for email, telephone, url and search input types */
-checkNegativeMaxLength(document.getElementById('t'));
-checkNegativeMaxLength(document.getElementById('i'));
-checkNegativeMaxLength(document.getElementById('p'));
+checkNegativeMinMaxLength(document.getElementById('t'));
+checkNegativeMinMaxLength(document.getElementById('i'));
+checkNegativeMinMaxLength(document.getElementById('p'));
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/html/test/test_bug558788-2.html
+++ b/dom/html/test/test_bug558788-2.html
@@ -1,70 +1,77 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=558788
 -->
 <head>
   <title>Test for Bug 558788</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=558788">Mozilla Bug 558788</a>
 <p id="display"></p>
-<div id="content" style="display:none;">
+<div id="content">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 558788 **/
 
 var validElementsDescription = [
-  /* element type value required pattern maxlength */
+  /* element type value required pattern maxlength minlength */
   /* <input> */
-  [ "input", null, null, null, null, null ],
+  [ "input", null, null, null, null, null, null ],
   /* <input required value='foo'> */
-  [ "input", null, "foo", true, null, null ],
+  [ "input", null, "foo", true, null, null, null ],
   /* <input type='email'> */
-  [ "input", "email", null, null, null, null ],
+  [ "input", "email", null, null, null, null, null ],
   /* <input type='email' value='foo@mozilla.org'> */
-  [ "input", "email", "foo@mozilla.org", null, null, null ],
+  [ "input", "email", "foo@mozilla.org", null, null, null, null ],
   /* <input type='url'> */
-  [ "input", "url", null, null, null, null ],
+  [ "input", "url", null, null, null, null, null ],
   /* <input type='url' value='http://mozilla.org'> */
-  [ "input", "url", "http://mozilla.org", null, null, null ],
+  [ "input", "url", "http://mozilla.org", null, null, null, null ],
   /* <input pattern='\\d\\d'> */
-  [ "input", null, null, null, "\\d\\d", null ],
+  [ "input", null, null, null, "\\d\\d", null, null ],
   /* <input pattern='\\d\\d' value='42'> */
-  [ "input", null, "42", null, "\\d\\d", null ],
-  /* <input maxlength='3'> */
-  [ "input", null, null, null, null, "3" ],
+  [ "input", null, "42", null, "\\d\\d", null, null ],
+  /* <input maxlength='3'> - still valid until user interaction */
+  [ "input", null, null, null, null, "3", null ],
   /* <input maxlength='3'> */
-  [ "input", null, "foo", null, null, "3" ],
+  [ "input", null, "fooo", null, null, "3", null ],
+  /* <input minlength='3'> - still valid until user interaction */
+  [ "input", null, null, null, null, null, "3" ],
+  /* <input minlength='3'> */
+  [ "input", null, "fo", null, null, null, "3" ],
   /* <textarea></textarea> */
-  [ "textarea", null, null, null, null, null ],
+  [ "textarea", null, null, null, null, null, null ],
   /* <textarea required>foo</textarea> */
-  [ "textarea", null, "foo", true, null, null ],
-  /* <input maxlength='3' value='foo'> */
-  [ "input", null, "foobar", null, null, "3", "foo" ],
+  [ "textarea", null, "foo", true, null, null, null ]
 ];
 
 var invalidElementsDescription = [
-  /* element type value required pattern maxlength valid-value */
+  /* element type value required pattern maxlength minlength valid-value */
   /* <input required> */
-  [ "input", null, null, true, null, null, "foo" ],
+  [ "input", null, null, true, null, null, null, "foo" ],
   /* <input type='email' value='foo'> */
-  [ "input", "email", "foo", null, null, null, "foo@mozilla.org" ],
+  [ "input", "email", "foo", null, null, null, null, "foo@mozilla.org" ],
   /* <input type='url' value='foo'> */
-  [ "input", "url", "foo", null, null, null, "http://mozilla.org" ],
+  [ "input", "url", "foo", null, null, null, null, "http://mozilla.org" ],
   /* <input pattern='\\d\\d' value='foo'> */
-  [ "input", null, "foo", null, "\\d\\d", null, "42" ],
+  [ "input", null, "foo", null, "\\d\\d", null, null, "42" ],
+  /* <input maxlength='3'> - still valid until user interaction */
+  [ "input", null, "foooo", null, null, "3", null, "foo" ],
+  /* <input minlength='3'> - still valid until user interaction */
+  [ "input", null, "foo", null, null, null, "3", "foo" ],
   /* <textarea required></textarea> */
-  [ "textarea", null, null, true, null, null, "foo" ],
+  [ "textarea", null, null, true, null, null, null, "foo" ],
 ];
 
 var validElements = [];
 var invalidElements = [];
 
 function appendElements(aElementsDesc, aElements)
 {
   var content = document.getElementById('content');
@@ -82,16 +89,19 @@ function appendElements(aElementsDesc, a
       e.required = true;
     }
     if (aElementsDesc[i][4]) {
       e.pattern = aElementsDesc[i][4];
     }
     if (aElementsDesc[i][5]) {
       e.maxLength = aElementsDesc[i][5];
     }
+    if (aElementsDesc[i][6]) {
+      e.minLength = aElementsDesc[i][6];
+    }
 
     content.appendChild(e);
 
     // Adding the element to the appropriate list.
     aElements.push(e);
   }
 }
 
@@ -108,32 +118,52 @@ function compareArrayWithSelector(aEleme
 
   var length = aElements.length;
   for (var i=0; i<length; ++i) {
     is(aSelectorElements[i], aElements[i],
        aSelector + " should return the correct elements");
   }
 }
 
+function makeMinMaxLengthElementsActuallyInvalid(aInvalidElements,
+                                                 aInvalidElementsDesc)
+{
+  // min/maxlength elements are not invalid until user edits them
+  var length = aInvalidElementsDesc.length;
+
+  for (var i=0; i<length; ++i) {
+    var e = aInvalidElements[i];
+    if (aInvalidElementsDesc[i][5]) { // maxlength
+      e.focus();
+      synthesizeKey("VK_BACK_SPACE", {});
+    } else if (aInvalidElementsDesc[i][6]) { // minlength
+      e.focus();
+      synthesizeKey("VK_BACK_SPACE", {});
+    }
+  }
+}
+
 function makeInvalidElementsValid(aInvalidElements,
                                   aInvalidElementsDesc,
                                   aValidElements)
 {
   var length = aInvalidElementsDesc.length;
 
   for (var i=0; i<length; ++i) {
     var e = aInvalidElements.shift();
-    e.value = aInvalidElementsDesc[i][6];
+    e.value = aInvalidElementsDesc[i][7];
     aValidElements.push(e);
   }
 }
 
 appendElements(validElementsDescription, validElements);
 appendElements(invalidElementsDescription, invalidElements);
 
+makeMinMaxLengthElementsActuallyInvalid(invalidElements, invalidElementsDescription);
+
 compareArrayWithSelector(validElements, ":valid");
 compareArrayWithSelector(invalidElements, ":invalid");
 
 makeInvalidElementsValid(invalidElements, invalidElementsDescription,
                          validElements);
 
 compareArrayWithSelector(validElements, ":valid");
 compareArrayWithSelector(invalidElements, ":invalid");
--- a/dom/html/test/test_bug613019.html
+++ b/dom/html/test/test_bug613019.html
@@ -9,23 +9,25 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=613019">Mozilla Bug 613019</a>
 <div id="content">
   <input type="text" maxlength="2" style="width:200px" value="Test">
   <textarea maxlength="2" style="width:200px">Test</textarea>
+  <input type="text" minlength="6" style="width:200px" value="Test">
+  <textarea minlength="6" style="width:200px">Test</textarea>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 613019 **/
 
-function testInteractivityOfValidityStates(elem) {
+function testInteractivityOfMaxLength(elem) {
   // verify that user interactivity is necessary for validity state to apply.
   is(elem.value, "Test", "Element has incorrect starting value.");
   is(elem.validity.tooLong, false, "Element should not be tooLong.");
 
   elem.focus();
 
   synthesizeKey("VK_BACK_SPACE", {});
   is(elem.value, "Tes", "Element value was not changed correctly.");
@@ -35,20 +37,42 @@ function testInteractivityOfValidityStat
   is(elem.value, "Te", "Element value was not changed correctly.");
   is(elem.validity.tooLong, false, "Element should no longer be tooLong.");
 
   elem.value = "Test";
   is(elem.validity.tooLong, false,
      "Element should not be tooLong after non-interactive value change.");
 }
 
+function testInteractivityOfMinLength(elem) {
+  // verify that user interactivity is necessary for validity state to apply.
+  is(elem.value, "Test", "Element has incorrect starting value.");
+  is(elem.validity.tooLong, false, "Element should not be tooShort.");
+
+  elem.focus();
+
+  synthesizeKey("e", {});
+  is(elem.value, "Teste", "Element value was not changed correctly.");
+  is(elem.validity.tooShort, true, "Element should still be tooShort.");
+
+  synthesizeKey("d", {});
+  is(elem.value, "Tested", "Element value was not changed correctly.");
+  is(elem.validity.tooShort, false, "Element should no longer be tooShort.");
+
+  elem.value = "Test";
+  is(elem.validity.tooShort, false,
+     "Element should not be tooShort after non-interactive value change.");
+}
+
 function test() {
   window.getSelection().removeAllRanges();
-  testInteractivityOfValidityStates(document.querySelector("input[type=text]"));
-  testInteractivityOfValidityStates(document.querySelector("textarea"));
+  testInteractivityOfMaxLength(document.querySelector("input[type=text][maxlength]"));
+  testInteractivityOfMaxLength(document.querySelector("textarea[maxlength]"));
+  testInteractivityOfMinLength(document.querySelector("input[type=text][minlength]"));
+  testInteractivityOfMinLength(document.querySelector("textarea[minlength]"));
   SimpleTest.finish();
 }
 
 window.onload = function() {
   SimpleTest.waitForExplicitFinish();
   setTimeout(test, 0);
 };
 
--- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl
@@ -44,16 +44,17 @@ interface nsIDOMHTMLInputElement : nsISu
            attribute boolean               indeterminate;
 
            attribute DOMString             inputMode;
 
   readonly attribute nsIDOMHTMLElement     list;
            attribute DOMString             max;
            attribute long                  maxLength;
            attribute DOMString             min;
+           attribute long                  minLength;
 
            attribute boolean               multiple;
            attribute DOMString             name;
 
            attribute DOMString             pattern;
            attribute DOMString             placeholder;
            attribute boolean               readOnly;
            attribute boolean               required;
--- a/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLTextAreaElement.idl
@@ -22,16 +22,17 @@ interface nsIDOMValidityState;
 [uuid(7a4aeb2e-fcf3-443e-b002-ca1c8ea322e9)]
 interface nsIDOMHTMLTextAreaElement : nsISupports
 {
            attribute boolean               autofocus;
            attribute unsigned long         cols;
            attribute boolean               disabled;
   readonly attribute nsIDOMHTMLFormElement form;
            attribute long                  maxLength;
+           attribute long                  minLength;
            attribute DOMString             name;
            attribute DOMString             placeholder;
            attribute boolean               readOnly;
            attribute boolean               required;
            attribute unsigned long         rows;
   /**
    * Reflects the wrap content attribute. Possible values are "soft", "hard" and
    * "off". "soft" is the default.
--- a/dom/interfaces/html/nsIDOMValidityState.idl
+++ b/dom/interfaces/html/nsIDOMValidityState.idl
@@ -15,15 +15,16 @@
 
 [uuid(00bed276-f1f7-492f-a039-dbd9b9efc10b)]
 interface nsIDOMValidityState : nsISupports
 {
   readonly attribute boolean valueMissing;
   readonly attribute boolean typeMismatch;
   readonly attribute boolean patternMismatch;
   readonly attribute boolean tooLong;
+  readonly attribute boolean tooShort;
   readonly attribute boolean rangeUnderflow;
   readonly attribute boolean rangeOverflow;
   readonly attribute boolean stepMismatch;
   readonly attribute boolean badInput;
   readonly attribute boolean customError;
   readonly attribute boolean valid;
 };
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -20,16 +20,17 @@ UnexpectedCanvasVariantStyle=canvas: an 
 EmptyGetElementByIdParam=Empty string passed to getElementById().
 LowMemoryTitle=Warning: Low memory
 LowMemoryMessage=A script on this page has been stopped due to a low memory condition.
 SpeculationFailed=An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
 DocumentWriteIgnored=A call to document.write() from an asynchronously-loaded external script was ignored.
 # LOCALIZATION NOTE (EditorFileDropFailed): Do not translate contenteditable, %S is the error message explaining why the drop failed.
 EditorFileDropFailed=Dropping a file into a contenteditable element failed: %S.
 FormValidationTextTooLong=Please shorten this text to %S characters or less (you are currently using %S characters).
+FormValidationTextTooShort=Please use at least %S characters (you are currently using %S characters).
 FormValidationValueMissing=Please fill out this field.
 FormValidationCheckboxMissing=Please check this box if you want to proceed.
 FormValidationRadioMissing=Please select one of these options.
 FormValidationFileMissing=Please select a file.
 FormValidationSelectMissing=Please select an item in the list.
 FormValidationInvalidEmail=Please enter an email address.
 FormValidationInvalidURL=Please enter a URL.
 FormValidationPatternMismatch=Please match the requested format.
--- a/dom/tests/mochitest/ajax/jquery/test/index.html
+++ b/dom/tests/mochitest/ajax/jquery/test/index.html
@@ -41,32 +41,32 @@
 			<p lang="en" id="en">This is a normal link: <a id="yahoo" href="http://www.yahoo.com/" class="blogTest">Yahoo</a></p>
 			<p id="sap">This link has <code><a href="#2" id="anchor2">class="blog"</a></code>: <a href="http://simon.incutio.com/" class="blog link" id="simon">Simon Willison's Weblog</a></p>
 
 		</div>
 		<p id="first">Try them out:</p>
 		<ul id="firstUL"></ul>
 		<ol id="empty"></ol>
 		<form id="form" action="formaction">
-			<input type="text" name="action" value="Test" id="text1" maxlength="30"/>
+			<input type="text" name="action" value="Test" id="text1" minlength="20" maxlength="30"/>
 			<input type="text" name="text2" value="Test" id="text2" disabled="disabled"/>
 			<input type="radio" name="radio1" id="radio1" value="on"/>
 
 			<input type="radio" name="radio2" id="radio2" checked="checked"/>
 			<input type="checkbox" name="check" id="check1" checked="checked"/>
 			<input type="checkbox" id="check2" value="on"/>
 
 			<input type="hidden" name="hidden" id="hidden1"/>
 			<input type="text" style="display:none;" name="foo[bar]" id="hidden2"/>
 			
 			<input type="text" id="name" name="name" value="name" />
 			
 			<button id="button" name="button">Button</button>
 			
-			<textarea id="area1" maxlength="30">foobar</textarea>
+			<textarea id="area1" minlength="20" maxlength="30">foobar</textarea>
 			
 			<select name="select1" id="select1">
 				<option id="option1a" class="emptyopt" value="">Nothing</option>
 				<option id="option1b" value="1">1</option>
 				<option id="option1c" value="2">2</option>
 				<option id="option1d" value="3">3</option>
 			</select>
 			<select name="select2" id="select2">
--- a/dom/tests/mochitest/ajax/jquery/test/unit/core.js
+++ b/dom/tests/mochitest/ajax/jquery/test/unit/core.js
@@ -315,30 +315,33 @@ test("index(Object)", function() {
 	equals( inputElements.index(document), -1, "Check for not found index" );
 
 	// enabled since [5500]
 	equals( elements.index( elements ), 0, "Pass in a jQuery object" );
 	equals( elements.index( elements.eq(1) ), 1, "Pass in a jQuery object" );
 });
 
 test("attr(String)", function() {
-	expect(26);
+	expect(29);
 	equals( $('#text1').attr('value'), "Test", 'Check for value attribute' );
 	equals( $('#text1').attr('value', "Test2").attr('defaultValue'), "Test", 'Check for defaultValue attribute' );
 	equals( $('#text1').attr('type'), "text", 'Check for type attribute' );
 	equals( $('#radio1').attr('type'), "radio", 'Check for type attribute' );
 	equals( $('#check1').attr('type'), "checkbox", 'Check for type attribute' );
 	equals( $('#simon1').attr('rel'), "bookmark", 'Check for rel attribute' );
 	equals( $('#google').attr('title'), "Google!", 'Check for title attribute' );
 	equals( $('#mark').attr('hreflang'), "en", 'Check for hreflang attribute' );
 	equals( $('#en').attr('lang'), "en", 'Check for lang attribute' );
 	equals( $('#simon').attr('class'), "blog link", 'Check for class attribute' );
 	equals( $('#name').attr('name'), "name", 'Check for name attribute' );
 	equals( $('#text1').attr('name'), "action", 'Check for name attribute' );
 	ok( $('#form').attr('action').indexOf("formaction") >= 0, 'Check for action attribute' );
+	equals( $('#text1').attr('minlength'), '20', 'Check for minlength attribute' );
+	equals( $('#text1').attr('minLength'), '20', 'Check for minLength attribute' );
+	equals( $('#area1').attr('minLength'), '20', 'Check for minLength attribute' );
 	equals( $('#text1').attr('maxlength'), '30', 'Check for maxlength attribute' );
 	equals( $('#text1').attr('maxLength'), '30', 'Check for maxLength attribute' );
 	equals( $('#area1').attr('maxLength'), '30', 'Check for maxLength attribute' );
 	equals( $('#select2').attr('selectedIndex'), 3, 'Check for selectedIndex attribute' );
 	equals( $('#foo').attr('nodeName'), 'DIV', 'Check for nodeName attribute' );
 	equals( $('#foo').attr('tagName'), 'DIV', 'Check for tagName attribute' );
 
 	$('<a id="tAnchor5"></a>').attr('href', '#5').appendTo('#main'); // using innerHTML in IE causes href attribute to be serialized to the full path
@@ -389,17 +392,17 @@ test("attr(Hash)", function() {
 	var pass = true;
 	$("div").attr({foo: 'baz', zoo: 'ping'}).each(function(){
 		if ( this.getAttribute('foo') != "baz" && this.getAttribute('zoo') != "ping" ) pass = false;
 	});
 	ok( pass, "Set Multiple Attributes" );
 });
 
 test("attr(String, Object)", function() {
-	expect(17);
+	expect(19);
 	var div = $("div").attr("foo", "bar");
 		fail = false;
 	for ( var i = 0; i < div.size(); i++ ) {
 		if ( div.get(i).getAttribute('foo') != "bar" ){
 			fail = i;
 			break;
 		}
 	}
@@ -416,16 +419,20 @@ test("attr(String, Object)", function() 
 	$("#text1").attr('readonly', true);
 	equals( document.getElementById('text1').readOnly, true, 'Set readonly attribute' );
 	$("#text1").attr('readonly', false);
 	equals( document.getElementById('text1').readOnly, false, 'Set readonly attribute' );
 	$("#name").attr('maxlength', '5');
 	equals( document.getElementById('name').maxLength, '5', 'Set maxlength attribute' );
 	$("#name").attr('maxLength', '10');
 	equals( document.getElementById('name').maxLength, '10', 'Set maxlength attribute' );
+	$("#name").attr('minlength', '5');
+	equals( document.getElementById('name').minLength, '5', 'Set minlength attribute' );
+	$("#name").attr('minLength', '10');
+	equals( document.getElementById('name').minLength, '10', 'Set minlength attribute' );
 
 	// for #1070
 	$("#name").attr('someAttr', '0');
 	equals( $("#name").attr('someAttr'), '0', 'Set attribute to a string of "0"' );
 	$("#name").attr('someAttr', 0);
 	equals( $("#name").attr('someAttr'), 0, 'Set attribute to the number 0' );
 	$("#name").attr('someAttr', 1);
 	equals( $("#name").attr('someAttr'), 1, 'Set attribute to the number 1' );
--- a/dom/tests/mochitest/ajax/prototype/test/unit/dom_test.js
+++ b/dom/tests/mochitest/ajax/prototype/test/unit/dom_test.js
@@ -980,18 +980,19 @@ new Test.Unit.Runner({
     this.assert( input.          writeAttribute('readonly', 'readonly').hasAttribute('readonly'));
     this.assert( select.         writeAttribute('multiple').            hasAttribute('multiple'));
     this.assert( input.          writeAttribute('disabled').            hasAttribute('disabled'));
     this.assert( checkbox.       writeAttribute('checked').             checked);
     this.assert(!checkedCheckbox.writeAttribute('checked', false).      checked);
   },
 
   testElementWriteAttributeWithIssues: function() {
-    var input = $('write_attribute_input').writeAttribute({maxlength: 90, tabindex: 10}),
+    var input = $('write_attribute_input').writeAttribute({maxlength: 90, minlength:80, tabindex: 10}),
       td = $('write_attribute_td').writeAttribute({valign: 'bottom', colspan: 2, rowspan: 2});
+    this.assertEqual(80, input.readAttribute('minlength'));
     this.assertEqual(90, input.readAttribute('maxlength'));
     this.assertEqual(10, input.readAttribute('tabindex'));
     this.assertEqual(2,  td.readAttribute('colspan'));
     this.assertEqual(2,  td.readAttribute('rowspan'));
     this.assertEqual('bottom', td.readAttribute('valign'));
     
     var p = $('write_attribute_para'), label = $('write_attribute_label');
     this.assertEqual('some-class',     p.    writeAttribute({'class':   'some-class'}).    readAttribute('class'));
@@ -1395,9 +1396,9 @@ function preservingBrowserDimensions(cal
   original.width += 640 - resized.width, original.height += 480 - resized.height;
   
   try {
     window.resizeTo(original.width, original.height);
     callback();
   } finally {
     window.resizeTo(original.width, original.height);
   }
-}
\ No newline at end of file
+}
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -60,16 +60,18 @@ interface HTMLInputElement : HTMLElement
   readonly attribute HTMLElement? list;
   [Pure, SetterThrows]
            attribute DOMString max;
   [Pure, SetterThrows]
            attribute long maxLength;
   [Pure, SetterThrows]
            attribute DOMString min;
   [Pure, SetterThrows]
+           attribute long minLength;
+  [Pure, SetterThrows]
            attribute boolean multiple;
   [Pure, SetterThrows]
            attribute DOMString name;
   [Pure, SetterThrows]
            attribute DOMString pattern;
   [Pure, SetterThrows]
            attribute DOMString placeholder;
   [Pure, SetterThrows]
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -24,16 +24,18 @@ interface HTMLTextAreaElement : HTMLElem
   [SetterThrows, Pure]
            attribute boolean disabled;
   [Pure]
   readonly attribute HTMLFormElement? form;
            // attribute DOMString inputMode;
   [SetterThrows, Pure]
            attribute long maxLength;
   [SetterThrows, Pure]
+           attribute long minLength;
+  [SetterThrows, Pure]
            attribute DOMString name;
   [SetterThrows, Pure]
            attribute DOMString placeholder;
   [SetterThrows, Pure]
            attribute boolean readOnly;
   [SetterThrows, Pure]
            attribute boolean required;
   [SetterThrows, Pure]
--- a/dom/webidl/ValidityState.webidl
+++ b/dom/webidl/ValidityState.webidl
@@ -10,16 +10,17 @@
  * and create derivative works of this document.
  */
 
 interface ValidityState {
   readonly attribute boolean valueMissing;
   readonly attribute boolean typeMismatch;
   readonly attribute boolean patternMismatch;
   readonly attribute boolean tooLong;
+  readonly attribute boolean tooShort;
   readonly attribute boolean rangeUnderflow;
   readonly attribute boolean rangeOverflow;
   readonly attribute boolean stepMismatch;
   readonly attribute boolean badInput;
   readonly attribute boolean customError;
   readonly attribute boolean valid;
 };
 
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-invalid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <input value="foo" style="background-color:red">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-maxlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with maxlength is invalid if the user edits and it's too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" maxlength="2" value="fooo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-maxlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with maxlength is -moz-ui-invalid if the user edits and it's too long -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" maxlength="2" value="fooo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-maxlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with maxlength is -moz-ui-valid if the user edits and it's not too long -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+        input.blur();
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" maxlength="3" value="foooo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-maxlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with maxlength is valid until the user edits it, even if it's too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+  </head>
+  <body onload="document.documentElement.className=''">
+    <input id="input" maxlength="2" value="foo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-maxlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with maxlength is valid if the user edits and it's not too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+        input.blur();
+        input.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" maxlength="3" value="foooo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-minlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with minlength is invalid if the user edits and it's too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('o', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" minlength="4" value="fo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-minlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with minlength is -moz-ui-invalid if the user edits and it's too short -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('o', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" minlength="4" value="fo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-minlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with minlength is -moz-ui-valid if the user edits and it's not too short -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('o', {}); // so that it becomes invalid first
+        input.blur();
+        input.focus();
+        synthesizeKey('o', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" minlength="3" value="f">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-minlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with minlength is valid until the user edits it, even if it's too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+  </head>
+  <body onload="document.documentElement.className=''">
+    <input id="input" minlength="5" value="foo">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-minlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: input with minlength is valid if the user edits and it's not too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var input = document.getElementById('input');
+        input.focus();
+        synthesizeKey('o', {}); // so that it becomes invalid first
+        input.blur();
+        input.focus();
+        synthesizeKey('o', {});
+        input.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <input id="input" minlength="3" value="f">
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-ui-valid-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <input value="foo" style="background-color:green">
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/input-valid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <input value="foo" style="background-color:green">
+  </body>
+</html>
+
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -168,16 +168,40 @@ support-files =
   bug1007065-1.html
   bug1007065-1-ref.html
   bug1007067-1.html
   bug1007067-1-ref.html
   bug1082486-1.html
   bug1082486-1-ref.html
   bug1082486-2.html
   bug1082486-2-ref.html
+  input-maxlength-valid-before-change.html
+  input-maxlength-valid-change.html
+  input-maxlength-invalid-change.html
+  input-minlength-valid-before-change.html
+  input-minlength-valid-change.html
+  input-minlength-invalid-change.html
+  input-maxlength-ui-valid-change.html
+  input-maxlength-ui-invalid-change.html
+  input-minlength-ui-valid-change.html
+  input-minlength-ui-invalid-change.html
+  input-valid-ref.html
+  input-invalid-ref.html
+  textarea-maxlength-valid-before-change.html
+  textarea-maxlength-valid-change.html
+  textarea-maxlength-invalid-change.html
+  textarea-minlength-valid-before-change.html
+  textarea-minlength-valid-change.html
+  textarea-minlength-invalid-change.html
+  textarea-maxlength-ui-valid-change.html
+  textarea-maxlength-ui-invalid-change.html
+  textarea-minlength-ui-valid-change.html
+  textarea-minlength-ui-invalid-change.html
+  textarea-valid-ref.html
+  textarea-invalid-ref.html
 [test_bug514127.html]
 [test_bug518777.html]
 [test_bug548545.xhtml]
 [test_bug558663.html]
 [test_bug559499.html]
 [test_bug569520.html]
 [test_bug582181-1.html]
 [test_bug582181-2.html]
--- a/layout/base/tests/test_reftests_with_caret.html
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -128,16 +128,36 @@ var tests = [
     [ 'bug613433-1.html' , 'bug613433-ref.html' ]   ,
     [ 'bug613433-2.html' , 'bug613433-ref.html' ]   ,
     [ 'bug613433-3.html' , 'bug613433-ref.html' ]   ,
     [ 'bug632215-1.html' , 'bug632215-ref.html'   ] ,
     [ 'bug632215-2.html' , 'bug632215-ref.html'   ] ,
     [ 'bug633044-1.html' , 'bug633044-1-ref.html' ] ,
     [ 'bug634406-1.html' , 'bug634406-1-ref.html' ] ,
     [ 'bug644428-1.html' , 'bug644428-1-ref.html' ] ,
+    [ 'input-maxlength-valid-before-change.html', 'input-valid-ref.html'] ,
+    [ 'input-maxlength-valid-change.html', 'input-valid-ref.html'] ,
+    [ 'input-maxlength-invalid-change.html', 'input-invalid-ref.html'] ,
+    [ 'input-minlength-valid-before-change.html', 'input-valid-ref.html'] ,
+    [ 'input-minlength-valid-change.html', 'input-valid-ref.html'] ,
+    [ 'input-minlength-invalid-change.html', 'input-invalid-ref.html'] ,
+    [ 'input-maxlength-ui-valid-change.html', 'input-valid-ref.html'] ,
+    [ 'input-maxlength-ui-invalid-change.html', 'input-invalid-ref.html'] ,
+    [ 'input-minlength-ui-valid-change.html', 'input-valid-ref.html'] ,
+    [ 'input-minlength-ui-invalid-change.html', 'input-invalid-ref.html'] ,
+    [ 'textarea-maxlength-valid-before-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-maxlength-valid-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-maxlength-invalid-change.html', 'textarea-invalid-ref.html'] ,
+    [ 'textarea-minlength-valid-before-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-minlength-valid-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-minlength-invalid-change.html', 'textarea-invalid-ref.html'] ,
+    [ 'textarea-maxlength-ui-valid-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-maxlength-ui-invalid-change.html', 'textarea-invalid-ref.html'] ,
+    [ 'textarea-minlength-ui-valid-change.html', 'textarea-valid-ref.html'] ,
+    [ 'textarea-minlength-ui-invalid-change.html', 'textarea-invalid-ref.html'] ,
     function() {SpecialPowers.pushPrefEnv({'set': [['bidi.browser.ui', true]]}, nextTest);} ,
     [ 'bug646382-1.html' , 'bug646382-1-ref.html' ] ,
     [ 'bug646382-2.html' , 'bug646382-2-ref.html' ] ,
     [ 'bug664087-1.html' , 'bug664087-1-ref.html' ] ,
     [ 'bug664087-2.html' , 'bug664087-2-ref.html' ] ,
     [ 'bug682712-1.html' , 'bug682712-1-ref.html' ] ,
     function() {SpecialPowers.pushPrefEnv({'clear': [['bidi.browser.ui']]}, nextTest);} ,
     [ 'bug746993-1.html' , 'bug746993-1-ref.html' ] ,
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-invalid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <textarea style="background-color:red">foo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with maxlength is invalid if the user edits and it's too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" maxlength="2">fooo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with maxlength is -moz-ui-invalid if the user edits and it's too long -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" maxlength="2">fooo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with maxlength is -moz-ui-valid if the user edits and it's not too long -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+        textarea.blur();
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" maxlength="3">foooo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with maxlength is valid until the user edits it, even if it's too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+  </head>
+  <body onload="document.documentElement.className=''">
+    <textarea id="textarea" maxlength="2">foo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-maxlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with maxlength is valid if the user edits and it's not too long -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {}); // so that it becomes invalid first
+        textarea.blur();
+        textarea.focus();
+        synthesizeKey('VK_BACK_SPACE', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" maxlength="3">foooo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with minlength is invalid if the user edits and it's too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('o', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" minlength="4">fo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-ui-invalid-change.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with minlength is -moz-ui-invalid if the user edits and it's too short -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { box-shadow:none; background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('o', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" minlength="4">fo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-ui-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with minlength is -moz-ui-valid if the user edits and it's not too short -->
+  <head>
+    <style>
+      :-moz-ui-valid { background-color:green; }
+      :-moz-ui-invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('o', {}); // so that it becomes invalid first
+        textarea.blur();
+        textarea.focus();
+        synthesizeKey('o', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" minlength="3">f</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-valid-before-change.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with minlength is valid until the user edits it, even if it's too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+  </head>
+  <body onload="document.documentElement.className=''">
+    <textarea id="textarea" minlength="5">foo</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-minlength-valid-change.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+  <!-- Test: textarea with minlength is valid if the user edits and it's not too short -->
+  <head>
+    <style>
+      :valid { background-color:green; }
+      :invalid { background-color:red; }
+      * { background-color:white; }
+    </style>
+    <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+    <script>
+      function runTest() {
+        var textarea = document.getElementById('textarea');
+        textarea.focus();
+        synthesizeKey('o', {}); // so that it becomes invalid first
+        textarea.blur();
+        textarea.focus();
+        synthesizeKey('o', {});
+        textarea.blur(); // to hide the caret
+        document.documentElement.className='';
+      }
+    </script>
+  </head>
+  <body onload="runTest()">
+    <textarea id="textarea" minlength="3">f</textarea>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/textarea-valid-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <textarea style="background-color:green">foo</textarea>
+  </body>
+</html>
+
deleted file mode 100644
--- a/layout/reftests/css-invalid/input/input-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if input isn't valid nor barred from constraint validation,
-             it should be affected by :invalid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('i').value='foo'; document.documentElement.className='';">
-    <input class='notinvalid' maxlength="2" id='i'>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-invalid/input/input-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if input is valid and is not barred from constraint validation,
-             it should not be affected by :invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <input class='notinvalid' maxlength="2">
-  </body>
-</html>
-
--- a/layout/reftests/css-invalid/input/reftest.list
+++ b/layout/reftests/css-invalid/input/reftest.list
@@ -1,18 +1,16 @@
 == input-valid.html input-ref.html
 fuzzy(11,4) fuzzy-if(skiaContent,2,10) == input-customerror.html input-ref.html
 skip-if(B2G||Mulet) == input-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == input-dyn-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == input-dyn-not-disabled.html input-ref.html
 == input-readonly.html input-ref.html
 == input-dyn-readonly.html input-ref.html
 == input-dyn-not-readonly.html input-ref.html
-== input-maxlength-valid.html input-ref.html
-== input-maxlength-invalid.html input-withtext-ref.html
 == input-required-valid.html input-withtext-ref.html
 == input-required-invalid.html input-ref.html
 == input-button.html input-button-ref.html
 == input-reset.html input-button-ref.html
 == input-email-invalid.html input-withtext-ref.html
 == input-email-valid.html input-email-ref.html
 == input-url-invalid.html input-withtext-ref.html
 == input-url-valid.html input-url-ref.html
--- a/layout/reftests/css-invalid/textarea/reftest.list
+++ b/layout/reftests/css-invalid/textarea/reftest.list
@@ -1,15 +1,13 @@
 == textarea-valid.html textarea-ref.html
 == textarea-customerror.html textarea-ref.html
 == textarea-disabled.html textarea-ref.html
 == textarea-dyn-disabled.html textarea-ref.html
 == textarea-dyn-not-disabled.html textarea-ref.html
 == textarea-readonly.html textarea-ref.html
 == textarea-dyn-readonly.html textarea-ref.html
 == textarea-dyn-not-readonly.html textarea-ref.html
-== textarea-maxlength-valid.html textarea-ref.html
-== textarea-maxlength-invalid.html textarea-withtext-ref.html
 == textarea-required-valid.html textarea-withtext-ref.html
 == textarea-required-invalid.html textarea-ref.html
 == textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
 == textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
 == textarea-fieldset-legend.html textarea-fieldset-legend-ref.html
deleted file mode 100644
--- a/layout/reftests/css-invalid/textarea/textarea-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if textarea isn't valid nor barred from constraint validation,
-             it should be affected by :invalid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('t').value='foo'; document.documentElement.className='';">
-    <textarea class='notinvalid' maxlength="2" id='t'></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-invalid/textarea/textarea-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if textarea is valid and is not barred from constraint validation,
-             it should not be affected by :invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea class='notinvalid' maxlength="2"></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/input/input-maxlength-invalid-changed.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if input isn't valid nor barred from constraint validation,
-             and its value has changed,
-             it should be affected by :-moz-ui-invalid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('i').value='foo';
-                document.documentElement.className='';">
-    <input class='notinvalid' maxlength="2" id='i'>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/input/input-maxlength-invalid-default.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if input isn't valid nor barred from constraint validation,
-             but its default value hasn't been changed,
-             it should not be affected by :-moz-ui-invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <input class='notinvalid' maxlength="2" value="foo">
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/input/input-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if input is valid and is not barred from constraint validation,
-             it should not be affected by :-moz-ui-invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <input class='notinvalid' maxlength="2">
-  </body>
-</html>
-
--- a/layout/reftests/css-ui-invalid/input/reftest.list
+++ b/layout/reftests/css-ui-invalid/input/reftest.list
@@ -2,19 +2,16 @@
 fuzzy(64,4) == input-customerror.html input-ref.html
 skip-if(B2G||Mulet) fuzzy-if(skiaContent,1,3) == input-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) fuzzy-if(skiaContent,1,3) == input-dyn-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(skiaContent,1,3) == input-dyn-not-disabled.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-readonly-not-changed.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-readonly-changed.html input-ref.html
-fuzzy-if(skiaContent,1,3) == input-maxlength-valid.html input-ref.html
-== input-maxlength-invalid-changed.html input-withtext-ref.html
-== input-maxlength-invalid-default.html input-withtext-ref.html
 == input-required-valid.html input-withtext-ref.html
 fuzzy-if(skiaContent,1,3) == input-required-invalid-default.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-required-invalid-changed.html input-ref.html
 fuzzy-if(skiaContent,2,5) == input-button.html input-button-ref.html
 fuzzy-if(skiaContent,2,5) == input-reset.html input-button-ref.html
 == input-email-invalid-default.html input-withtext-ref.html
 == input-email-invalid-changed.html input-withtext-ref.html
 fuzzy-if(skiaContent,2,5) == input-email-valid.html input-email-ref.html
--- a/layout/reftests/css-ui-invalid/textarea/reftest.list
+++ b/layout/reftests/css-ui-invalid/textarea/reftest.list
@@ -2,17 +2,14 @@
 == textarea-customerror.html textarea-ref.html
 == textarea-disabled.html textarea-ref.html
 == textarea-dyn-disabled.html textarea-ref.html
 == textarea-dyn-not-disabled.html textarea-ref.html
 == textarea-readonly.html textarea-ref.html
 == textarea-dyn-readonly.html textarea-ref.html
 == textarea-dyn-not-readonly-not-changed.html textarea-ref.html
 == textarea-dyn-not-readonly-changed.html textarea-ref.html
-== textarea-maxlength-valid.html textarea-ref.html
-== textarea-maxlength-invalid.html textarea-withtext-ref.html
-== textarea-maxlength-default-value-invalid.html textarea-withtext-ref.html
 == textarea-required-valid.html textarea-withtext-ref.html
 == textarea-required-invalid.html textarea-ref.html
 == textarea-required-invalid-changed.html textarea-ref.html
 == textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
 == textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
 == textarea-novalidate.html textarea-ref.html
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/textarea/textarea-maxlength-default-value-invalid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if textarea has it's default value invalid, it should not be
-             affected by :-moz-ui-invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea class='notinvalid' maxlength="2">foo</textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/textarea/textarea-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if textarea isn't valid nor barred from constraint validation,
-             it should be affected by :-moz-ui-invalid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('t').value='foo'; document.documentElement.className='';">
-    <textarea class='notinvalid' maxlength="2" id='t'></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-invalid/textarea/textarea-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if textarea is valid and is not barred from constraint validation,
-             it should not be affected by :-moz-ui-invalid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea class='notinvalid' maxlength="2"></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/input/input-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if input isn't valid nor barred from constraint validation,
-             it should not be affected by :-moz-ui-valid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('i').value='foo'; document.documentElement.className='';">
-    <input class='valid' maxlength="2" id='i'>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/input/input-maxlength-valid-changed.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class='reftest-wait'>
-  <!-- Test: if input is valid and its value has been changed,
-             it should be affected by :-moz-ui-valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('i').value = '';
-                document.documentElement.className = '';">
-    <input id='i' class='valid' maxlength="2">
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/input/input-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if input is valid but its value hasn't been changed,
-             it should not be affected by :-moz-ui-valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <input class='notvalid' maxlength="2">
-  </body>
-</html>
-
--- a/layout/reftests/css-ui-valid/input/reftest.list
+++ b/layout/reftests/css-ui-valid/input/reftest.list
@@ -3,19 +3,16 @@ fuzzy(11,4) == input-customerror.html in
 fails-if(B2G||Mulet) == input-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(B2G||Mulet) fuzzy-if(skiaContent,1,3) == input-dyn-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(skiaContent,1,3) == input-dyn-not-disabled.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-disabled-changed.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-readonly-changed.html input-ref.html
-fuzzy-if(skiaContent,1,3) == input-maxlength-valid.html input-ref.html
-fuzzy-if(skiaContent,1,3) == input-maxlength-valid-changed.html input-ref.html
-== input-maxlength-invalid.html input-withtext-ref.html
 == input-required-valid.html input-withtext-ref.html
 == input-required-valid-changed.html input-withtext-ref.html
 fuzzy-if(skiaContent,1,3) == input-required-invalid.html input-ref.html
 == input-button.html input-button-ref.html
 == input-reset.html input-button-ref.html
 == input-email-invalid.html input-withtext-ref.html
 == input-email-valid.html input-email-ref.html
 == input-email-valid-changed.html input-email-ref.html
--- a/layout/reftests/css-ui-valid/textarea/reftest.list
+++ b/layout/reftests/css-ui-valid/textarea/reftest.list
@@ -3,18 +3,15 @@
 == textarea-disabled.html textarea-ref.html
 == textarea-dyn-disabled.html textarea-ref.html
 == textarea-dyn-not-disabled.html textarea-ref.html
 == textarea-dyn-not-disabled-changed.html textarea-ref.html
 == textarea-readonly.html textarea-ref.html
 == textarea-dyn-readonly.html textarea-ref.html
 == textarea-dyn-not-readonly.html textarea-ref.html
 == textarea-dyn-not-readonly-changed.html textarea-ref.html
-== textarea-maxlength-valid.html textarea-ref.html
-== textarea-maxlength-valid-changed.html textarea-ref.html
-== textarea-maxlength-invalid.html textarea-withtext-ref.html
 == textarea-required-valid.html textarea-withtext-ref.html
 == textarea-required-valid-changed.html textarea-withtext-ref.html
 == textarea-required-invalid.html textarea-ref.html
 == textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
 == textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
 == textarea-fieldset-legend.html textarea-fieldset-legend-ref.html
 == textarea-novalidate.html textarea-withtext-ref.html
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/textarea/textarea-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if textarea isn't valid nor barred from constraint validation,
-             it should not be affected by :-moz-ui-valid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('t').value='foo'; document.documentElement.className='';">
-    <textarea class='valid' maxlength="2" id='t'></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid-changed.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html class='reftest-wait'>
-  <head>
-    <script>
-      function doTest() {
-        document.getElementById('t').value = '';
-        document.documentElement.className='';
-      }
-      document.addEventListener("MozReftestInvalidate", doTest, false);
-    </script>
-  </head>
-  <!-- Test: if textarea is valid and its value has been modified,
-             it should be affected by :-moz-ui-valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea id='t' class='valid' maxlength="2"></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-ui-valid/textarea/textarea-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if textarea is valid but its value hasn't been modifie,
-             it should not be affected by :-moz-ui-valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea class='notvalid' maxlength="2"></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-valid/input/input-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if input isn't valid nor barred from constraint validation,
-             it should not be affected by :valid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('i').value='foo'; document.documentElement.className='';">
-    <input class='valid' maxlength="2" id='i'>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-valid/input/input-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if input is valid and is not barred from constraint validation,
-             it should be affected by :valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <input class='valid' maxlength="2">
-  </body>
-</html>
-
--- a/layout/reftests/css-valid/input/reftest.list
+++ b/layout/reftests/css-valid/input/reftest.list
@@ -1,18 +1,16 @@
 == input-valid.html input-ref.html
 fuzzy(64,4) == input-customerror.html input-ref.html
 fails-if(B2G||Mulet) fuzzy-if(skiaContent,1,3) == input-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(B2G||Mulet) fuzzy-if(skiaContent,1,3) == input-dyn-disabled.html input-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(skiaContent,1,3) == input-dyn-not-disabled.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-readonly.html input-ref.html
 fuzzy-if(skiaContent,1,3) == input-dyn-not-readonly.html input-ref.html
-fuzzy-if(skiaContent,1,3) == input-maxlength-valid.html input-ref.html
-== input-maxlength-invalid.html input-withtext-ref.html
 == input-required-valid.html input-withtext-ref.html
 fuzzy-if(skiaContent,1,3) == input-required-invalid.html input-ref.html
 fuzzy-if(skiaContent,2,5) == input-button.html input-button-ref.html
 fuzzy-if(skiaContent,2,5) == input-reset.html input-button-ref.html
 == input-email-invalid.html input-withtext-ref.html
 fuzzy-if(skiaContent,2,5) == input-email-valid.html input-email-ref.html
 == input-url-invalid.html input-withtext-ref.html
 == input-url-valid.html input-url-ref.html
--- a/layout/reftests/css-valid/textarea/reftest.list
+++ b/layout/reftests/css-valid/textarea/reftest.list
@@ -1,15 +1,13 @@
 == textarea-valid.html textarea-ref.html
 == textarea-customerror.html textarea-ref.html
 == textarea-disabled.html textarea-ref.html
 == textarea-dyn-disabled.html textarea-ref.html
 == textarea-dyn-not-disabled.html textarea-ref.html
 == textarea-readonly.html textarea-ref.html
 == textarea-dyn-readonly.html textarea-ref.html
 == textarea-dyn-not-readonly.html textarea-ref.html
-== textarea-maxlength-valid.html textarea-ref.html
-== textarea-maxlength-invalid.html textarea-withtext-ref.html
 == textarea-required-valid.html textarea-withtext-ref.html
 == textarea-required-invalid.html textarea-ref.html
 == textarea-disabled-fieldset-1.html textarea-fieldset-ref.html
 == textarea-disabled-fieldset-2.html textarea-fieldset-ref.html
 == textarea-fieldset-legend.html textarea-fieldset-legend-ref.html
deleted file mode 100644
--- a/layout/reftests/css-valid/textarea/textarea-maxlength-invalid.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html class="reftest-wait">
-  <!-- Test: if textarea isn't valid nor barred from constraint validation,
-             it should not be affected by :valid pseudo-class. -->
-  <!-- TODO: this is valid until bug bug 613016 and bug 613019 are fixed. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body onload="document.getElementById('t').value='foo'; document.documentElement.className='';">
-    <textarea class='valid' maxlength="2" id='t'></textarea>
-  </body>
-</html>
-
deleted file mode 100644
--- a/layout/reftests/css-valid/textarea/textarea-maxlength-valid.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <!-- Test: if textarea is valid and is not barred from constraint validation,
-             it should be affected by :valid pseudo-class. -->
-  <link rel='stylesheet' type='text/css' href='style.css'>
-  <body>
-    <textarea class='valid' maxlength="2"></textarea>
-  </body>
-</html>
-
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1157,34 +1157,28 @@
     expected: FAIL
 
   [HTMLFormElement interface: document.createElement("form") must inherit property "requestAutocomplete" with the proper type (17)]
     expected: FAIL
 
   [HTMLInputElement interface: attribute dirName]
     expected: FAIL
 
-  [HTMLInputElement interface: attribute minLength]
-    expected: FAIL
-
   [HTMLInputElement interface: attribute valueLow]
     expected: FAIL
 
   [HTMLInputElement interface: attribute valueHigh]
     expected: FAIL
 
   [HTMLInputElement interface: attribute labels]
     expected: FAIL
 
   [HTMLInputElement interface: document.createElement("input") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: document.createElement("input") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: document.createElement("input") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: document.createElement("input") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: document.createElement("input") must inherit property "labels" with the proper type (48)]
     expected: FAIL
@@ -1217,34 +1211,28 @@
     expected: FAIL
 
   [HTMLTextAreaElement interface: attribute dirName]
     expected: FAIL
 
   [HTMLTextAreaElement interface: attribute inputMode]
     expected: FAIL
 
-  [HTMLTextAreaElement interface: attribute minLength]
-    expected: FAIL
-
   [HTMLTextAreaElement interface: attribute labels]
     expected: FAIL
 
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type (0)]
     expected: FAIL
 
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type (3)]
     expected: FAIL
 
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type (6)]
     expected: FAIL
 
-  [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "minLength" with the proper type (8)]
-    expected: FAIL
-
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "labels" with the proper type (25)]
     expected: FAIL
 
   [HTMLKeygenElement interface: existence and properties of interface object]
     expected: FAIL
 
   [HTMLKeygenElement interface object length]
     expected: FAIL
@@ -1376,22 +1364,16 @@
     expected: FAIL
 
   [AutocompleteErrorEvent interface: existence and properties of interface prototype object's "constructor" property]
     expected: FAIL
 
   [AutocompleteErrorEvent interface: attribute reason]
     expected: FAIL
 
-  [ValidityState interface: attribute tooShort]
-    expected: FAIL
-
-  [ValidityState interface: document.createElement("input").validity must inherit property "tooShort" with the proper type (4)]
-    expected: FAIL
-
   [HTMLMenuItemElement interface: attribute default]
     expected: FAIL
 
   [HTMLMenuItemElement interface: attribute command]
     expected: FAIL
 
   [RelatedEvent interface: existence and properties of interface object]
     expected: FAIL
@@ -2693,337 +2675,271 @@
     expected: FAIL
 
   [HTMLSlotElement interface: calling assignedNodes(AssignedNodesOptions) on document.createElement("slot") with too few arguments must throw TypeError]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("text") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("text") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("text") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("text") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("text") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("hidden") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("hidden") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("hidden") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("hidden") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("hidden") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("search") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("search") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("search") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("search") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("search") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("tel") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("tel") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("tel") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("tel") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("tel") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("url") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("url") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("url") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("url") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("url") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("email") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("email") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("email") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("email") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("email") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("password") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("password") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("password") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("password") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("password") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("date") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("date") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("date") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("date") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("date") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("month") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("month") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("month") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("month") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("month") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("week") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("week") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("week") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("week") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("week") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("time") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("time") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("time") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("time") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("time") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("datetime-local") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("datetime-local") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("datetime-local") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("datetime-local") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("datetime-local") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("number") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("number") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("number") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("number") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("number") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("range") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("range") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("range") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("range") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("range") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("color") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("color") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("color") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("color") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("color") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("checkbox") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("checkbox") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("checkbox") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("checkbox") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("checkbox") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("radio") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("radio") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("radio") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("radio") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("radio") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("file") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("file") must inherit property "files" with the proper type (9)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("file") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("file") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("file") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("file") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("submit") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("submit") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("submit") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("submit") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("submit") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("image") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("image") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("image") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("image") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("image") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("reset") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("reset") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("reset") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("reset") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("reset") must inherit property "labels" with the proper type (48)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("button") must inherit property "dirName" with the proper type (6)]
     expected: FAIL
 
-  [HTMLInputElement interface: createInput("button") must inherit property "minLength" with the proper type (22)]
-    expected: FAIL
-
   [HTMLInputElement interface: createInput("button") must inherit property "valueLow" with the proper type (37)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("button") must inherit property "valueHigh" with the proper type (38)]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("button") must inherit property "labels" with the proper type (48)]
     expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-tooShort.html.ini
+++ /dev/null
@@ -1,191 +0,0 @@
-[form-validation-validity-tooShort.html]
-  type: testharness
-  [[INPUT in TEXT status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in TEXT status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in SEARCH status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in TEL status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in URL status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in URL status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in URL status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in EMAIL status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Non-dirty value - minLength is not set]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Non-dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Dirty value - value is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Dirty value - length of value(AAAAA) in unicode is greater than minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Dirty value - value equals to minLength]
-    expected: FAIL
-
-  [[INPUT in PASSWORD status\] Dirty value - length of value is less than minLength]
-    expected: FAIL
-
-  [[textarea\]  Non-dirty value - minLength is no set]
-    expected: FAIL
-
-  [[textarea\]  Non-dirty value - value is empty string]
-    expected: FAIL
-
-  [[textarea\]  Non-dirty value - length of value is greater than minLength]
-    expected: FAIL
-
-  [[textarea\]  Non-dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[textarea\]  Non-dirty value - length of length of value is greater than minLength]
-    expected: FAIL
-
-  [[textarea\]  Dirty value - value is less than minLength]
-    expected: FAIL
-
-  [[textarea\]  Dirty value - length of value(LF, CRLF) in unicode is less than minLength]
-    expected: FAIL
-
-  [[textarea\]  Dirty value - length of value equals to minLength]
-    expected: FAIL
-
-  [[textarea\]  Dirty value - length of value is greater than minLength]
-    expected: FAIL
-
--- a/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
+++ b/testing/web-platform/tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
@@ -19,32 +19,34 @@
         {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
         {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
         {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
         {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than minLength"},
         //Dirty value
         {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is greater than minLength", dirty: true},
         {conditions: {minLength: "4", value: "\u0041\u0041\u0041\u0041\u0041"}, expected: false, name: "[target] Dirty value - length of value(AAAAA) in unicode is greater than minLength", dirty: true},
         {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - value equals to minLength", dirty: true},
-        {conditions: {minLength: "4", value: "abc"}, expected: true, name: "[target] Dirty value - length of value is less than minLength", dirty: true}
+        // False due to lack of required interactive editing by the user
+        {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - length of value is less than minLength", dirty: true}
       ]
     },
     {
       tag: "textarea",
       types: [],
       testData: [
         // Non-dirty value
         {conditions: {minLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - minLength is no set"},
         {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
         {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
         {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
         {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of length of value is greater than minLength"},
         //Dirty value
         {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is less than minLength", dirty: true},
         {conditions: {minLength: "4", value: "\u000D\u000A\u000D\u000A\u000D\u000A"}, expected: false, name: "[target] Dirty value - length of value(LF, CRLF) in unicode is less than minLength", dirty: true},
         {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - length of value equals to minLength", dirty: true},
-        {conditions: {minLength: "4", value: "abc"}, expected: true, name: "[target] Dirty value - length of value is greater than minLength", dirty: true}
+        // False due to lack of required interactive editing by the user
+        {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - length of value is greater than minLength", dirty: true}
       ]
     }
   ];
 
   validator.run_test (testElements, "tooShort");
 </script>