Bug 827158 - Part 3: Move the ValidityState API to Web IDL bindings; r=bzbarsky
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 16 Jan 2013 13:01:01 -0500
changeset 119053 abd216c2ded312961abb828844980d474768f46b
parent 119052 43391698ce5e19e62172c4ee5c748e1a4d117644
child 119054 752093e9327e2a4a6bb95a56f807efb95020627e
push id24189
push useremorley@mozilla.com
push dateThu, 17 Jan 2013 10:42:06 +0000
treeherdermozilla-central@712eca11a04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs827158
milestone21.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 827158 - Part 3: Move the ValidityState API to Web IDL bindings; r=bzbarsky
content/html/content/public/nsIConstraintValidation.h
content/html/content/src/ValidityState.cpp
content/html/content/src/ValidityState.h
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLButtonElement.cpp
content/html/content/src/nsHTMLFieldSetElement.cpp
content/html/content/src/nsHTMLInputElement.cpp
content/html/content/src/nsHTMLOutputElement.cpp
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsHTMLSelectElement.h
content/html/content/src/nsHTMLTextAreaElement.cpp
content/html/content/src/nsIConstraintValidation.cpp
dom/webidl/ValidityState.webidl
dom/webidl/WebIDL.mk
--- a/content/html/content/public/nsIConstraintValidation.h
+++ b/content/html/content/public/nsIConstraintValidation.h
@@ -59,16 +59,23 @@ public:
     VALIDITY_STATE_RANGE_OVERFLOW   = 0x20, // 0b00100000
     VALIDITY_STATE_STEP_MISMATCH    = 0x40, // 0b01000000
     VALIDITY_STATE_CUSTOM_ERROR     = 0x80  // 0b10000000
   };
 
   void SetValidityState(ValidityStateType mState,
                         bool mValue);
 
+  // Web IDL binding methods
+  bool WillValidate() const {
+    return IsCandidateForConstraintValidation();
+  }
+  mozilla::dom::ValidityState* Validity();
+  bool CheckValidity();
+
 protected:
 
   // You can't instantiate an object from that class.
   nsIConstraintValidation();
 
   nsresult GetValidity(nsIDOMValidityState** aValidity);
   nsresult CheckValidity(bool* aValidity);
   void     SetCustomValidity(const nsAString& aError);
@@ -79,30 +86,31 @@ protected:
 
   void SetBarredFromConstraintValidation(bool aBarred);
 
   virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
                                         ValidityStateType aType) {
                      return NS_OK;
                    }
 
+protected:
+  /**
+   * A pointer to the ValidityState object.
+   */
+  nsRefPtr<mozilla::dom::ValidityState>  mValidity;
+
 private:
 
   /**
    * A bitfield representing the current validity state of the element.
    * Each bit represent an error. All bits to zero means the element is valid.
    */
   int8_t                        mValidityBitField;
 
   /**
-   * A pointer to the ValidityState object.
-   */
-  nsRefPtr<mozilla::dom::ValidityState>  mValidity;
-
-  /**
    * Keeps track whether the element is barred from constraint validation.
    */
   bool                          mBarredFromConstraintValidation;
 
   /**
    * The string representing the custom error.
    */
   nsString                      mCustomValidity;
@@ -111,42 +119,43 @@ private:
 /**
  * Use these macro for class inheriting from nsIConstraintValidation to forward
  * functions to nsIConstraintValidation.
  */
 #define NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY           \
   NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) {                   \
     return nsIConstraintValidation::GetValidity(aValidity);                   \
   }                                                                           \
-  NS_IMETHOD GetWillValidate(bool* aWillValidate) {                         \
-    *aWillValidate = IsCandidateForConstraintValidation();                    \
+  NS_IMETHOD GetWillValidate(bool* aWillValidate) {                           \
+    *aWillValidate = WillValidate();                                          \
     return NS_OK;                                                             \
   }                                                                           \
   NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) {            \
     return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
   }                                                                           \
-  NS_IMETHOD CheckValidity(bool* aValidity) {                               \
+  using nsIConstraintValidation::CheckValidity;                               \
+  NS_IMETHOD CheckValidity(bool* aValidity) {                                 \
     return nsIConstraintValidation::CheckValidity(aValidity);                 \
   }
 
 #define NS_FORWARD_NSICONSTRAINTVALIDATION                                    \
   NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY                 \
   NS_IMETHOD SetCustomValidity(const nsAString& aError) {                     \
     nsIConstraintValidation::SetCustomValidity(aError);                       \
     return NS_OK;                                                             \
   }
 
 
 /* Use these macro when class declares functions from nsIConstraintValidation */
 #define NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from)       \
   NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) {         \
     return nsIConstraintValidation::GetValidity(aValidity);                   \
   }                                                                           \
-  NS_IMETHODIMP _from::GetWillValidate(bool* aWillValidate) {               \
-    *aWillValidate = IsCandidateForConstraintValidation();                    \
+  NS_IMETHODIMP _from::GetWillValidate(bool* aWillValidate) {                 \
+    *aWillValidate = WillValidate();                                          \
     return NS_OK;                                                             \
   }                                                                           \
   NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) {  \
     return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
   }                                                                           \
   NS_IMETHODIMP _from::CheckValidity(bool* aValidity) {                     \
     return nsIConstraintValidation::CheckValidity(aValidity);                 \
   }
--- a/content/html/content/src/ValidityState.cpp
+++ b/content/html/content/src/ValidityState.cpp
@@ -1,95 +1,107 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ValidityState.h"
+#include "mozilla/dom/ValidityStateBinding.h"
 
 #include "nsDOMClassInfoID.h"
-
+#include "nsCycleCollectionParticipant.h"
+#include "nsContentUtils.h"
 
 DOMCI_DATA(ValidityState, mozilla::dom::ValidityState)
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_ADDREF(ValidityState)
-NS_IMPL_RELEASE(ValidityState)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(ValidityState)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ValidityState)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ValidityState)
 
-NS_INTERFACE_MAP_BEGIN(ValidityState)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ValidityState)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMValidityState)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMValidityState)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ValidityState)
 NS_INTERFACE_MAP_END
 
 ValidityState::ValidityState(nsIConstraintValidation* aConstraintValidation)
   : mConstraintValidation(aConstraintValidation)
 {
+  SetIsDOMBinding();
 }
 
 NS_IMETHODIMP
 ValidityState::GetValueMissing(bool* aValueMissing)
 {
-  *aValueMissing = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
+  *aValueMissing = ValueMissing();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetTypeMismatch(bool* aTypeMismatch)
 {
-  *aTypeMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
+  *aTypeMismatch = TypeMismatch();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetPatternMismatch(bool* aPatternMismatch)
 {
-  *aPatternMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
+  *aPatternMismatch = PatternMismatch();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetTooLong(bool* aTooLong)
 {
-  *aTooLong = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
+  *aTooLong = TooLong();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetRangeUnderflow(bool* aRangeUnderflow)
 {
-  *aRangeUnderflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
+  *aRangeUnderflow = RangeUnderflow();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetRangeOverflow(bool* aRangeOverflow)
 {
-  *aRangeOverflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
+  *aRangeOverflow = RangeOverflow();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetStepMismatch(bool* aStepMismatch)
 {
-  *aStepMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
+  *aStepMismatch = StepMismatch();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetCustomError(bool* aCustomError)
 {
-  *aCustomError = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
+  *aCustomError = CustomError();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ValidityState::GetValid(bool* aValid)
 {
-  *aValid = !mConstraintValidation || mConstraintValidation->IsValid();
+  *aValid = Valid();
   return NS_OK;
 }
 
+JSObject*
+ValidityState::WrapObject(JSContext* aCx, JSObject* aScope,
+                          bool* aTriedToWrap)
+{
+  return ValidityStateBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
 } // namespace dom
 } // namespace mozilla
 
--- a/content/html/content/src/ValidityState.h
+++ b/content/html/content/src/ValidityState.h
@@ -3,28 +3,79 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_ValidityState_h
 #define mozilla_dom_ValidityState_h
 
 #include "nsIDOMValidityState.h"
 #include "nsIConstraintValidation.h"
+#include "nsWrapperCache.h"
+
+struct JSObject;
+struct JSContext;
 
 namespace mozilla {
 namespace dom {
 
-class ValidityState MOZ_FINAL : public nsIDOMValidityState
+class ValidityState MOZ_FINAL : public nsIDOMValidityState,
+                                public nsWrapperCache
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ValidityState)
   NS_DECL_NSIDOMVALIDITYSTATE
 
   friend class ::nsIConstraintValidation;
 
+  nsIConstraintValidation* GetParentObject() const {
+    return mConstraintValidation;
+  }
+
+  virtual JSObject* WrapObject(JSContext *aCx, JSObject *aScope,
+                               bool *aTriedToWrap) MOZ_OVERRIDE;
+
+  // Web IDL methods
+  bool ValueMissing() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
+  }
+  bool TypeMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
+  }
+  bool PatternMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
+  }
+  bool TooLong() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
+  }
+  bool RangeUnderflow() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
+  }
+  bool RangeOverflow() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
+  }
+  bool StepMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
+  }
+  bool CustomError() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
+  }
+  bool Valid() const
+  {
+    return !mConstraintValidation || mConstraintValidation->IsValid();
+  }
+
 protected:
   ValidityState(nsIConstraintValidation* aConstraintValidation);
 
   /**
    * This function should be called by nsIConstraintValidation
    * to set mConstraintValidation to null to be sure
    * it will not be used when the object is destroyed.
    */
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -10,16 +10,17 @@
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozilla/ErrorResult.h"
 #include "nsContentUtils.h"
 #include "nsIDOMHTMLMenuElement.h"
+#include "mozilla/dom/ValidityState.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -54,16 +54,19 @@ class nsHTMLButtonElement : public nsGen
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                       FromParser aFromParser = NOT_FROM_PARSER);
   virtual ~nsHTMLButtonElement();
 
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLButtonElement,
+                                           nsGenericHTMLFormElement)
+
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
@@ -147,16 +150,26 @@ nsHTMLButtonElement::nsHTMLButtonElement
 }
 
 nsHTMLButtonElement::~nsHTMLButtonElement()
 {
 }
 
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLButtonElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLButtonElement,
+                                                  nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLButtonElement,
+                                                nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_ADDREF_INHERITED(nsHTMLButtonElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLButtonElement, Element)
 
 
 DOMCI_NODE_DATA(HTMLButtonElement, nsHTMLButtonElement)
 
 // QueryInterface implementation for nsHTMLButtonElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -37,22 +37,24 @@ nsHTMLFieldSetElement::~nsHTMLFieldSetEl
     mDependentElements[i]->ForgetFieldSet(this);
   }
 }
 
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLFieldSetElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLFieldSetElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFieldSetElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFieldSetElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFieldSetElement, Element)
 
 DOMCI_NODE_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
 
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -632,26 +632,28 @@ nsHTMLInputElement::GetEditorState() con
 }
 
 
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLInputElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLInputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   if (tmp->IsSingleLineTextControl(false)) {
     tmp->mInputData.mState->Traverse(cb);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLInputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
   if (tmp->mFileList) {
     tmp->mFileList->Disconnect();
     tmp->mFileList = nullptr;
   }
   if (tmp->IsSingleLineTextControl(false)) {
     tmp->mInputData.mState->Unlink();
--- a/content/html/content/src/nsHTMLOutputElement.cpp
+++ b/content/html/content/src/nsHTMLOutputElement.cpp
@@ -105,23 +105,25 @@ nsHTMLOutputElement::~nsHTMLOutputElemen
   if (mTokenList) {
     mTokenList->DropReference();
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLOutputElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLOutputElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   if (tmp->mTokenList) {
     tmp->mTokenList->DropReference();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mTokenList)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLOutputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLOutputElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLOutputElement, Element)
 
 DOMCI_NODE_DATA(HTMLOutputElement, nsHTMLOutputElement)
 
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -133,18 +133,23 @@ nsHTMLSelectElement::~nsHTMLSelectElemen
   mOptions->DropReference();
 }
 
 // ISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLSelectElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLSelectElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLSelectElement,
+                                                nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLSelectElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLSelectElement, Element)
 
 
 DOMCI_NODE_DATA(HTMLSelectElement, nsHTMLSelectElement)
 
 // QueryInterface implementation for nsHTMLSelectElement
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -377,18 +377,18 @@ public:
                                 nsAttrValue& aResult);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
-                                                     nsGenericHTMLFormElement)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLSelectElement,
+                                           nsGenericHTMLFormElement)
 
   nsHTMLOptionCollection *GetOptions()
   {
     return mOptions;
   }
 
   static nsHTMLSelectElement *FromSupports(nsISupports *aSupports)
   {
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -298,21 +298,23 @@ nsHTMLTextAreaElement::nsHTMLTextAreaEle
                     NS_EVENT_STATE_OPTIONAL |
                     NS_EVENT_STATE_VALID);
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTextAreaElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLTextAreaElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   tmp->mState.Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTextAreaElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   tmp->mState.Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLTextAreaElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLTextAreaElement, Element)
 
 
--- a/content/html/content/src/nsIConstraintValidation.cpp
+++ b/content/html/content/src/nsIConstraintValidation.cpp
@@ -11,37 +11,44 @@
 #include "mozilla/dom/ValidityState.h"
 #include "nsIFormControl.h"
 #include "nsContentUtils.h"
 
 const uint16_t nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
 
 nsIConstraintValidation::nsIConstraintValidation()
   : mValidityBitField(0)
-  , mValidity(nullptr)
   // By default, all elements are subjects to constraint validation.
   , mBarredFromConstraintValidation(false)
 {
 }
 
 nsIConstraintValidation::~nsIConstraintValidation()
 {
   if (mValidity) {
     mValidity->Disconnect();
   }
 }
 
-nsresult
-nsIConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
+mozilla::dom::ValidityState*
+nsIConstraintValidation::Validity()
 {
   if (!mValidity) {
     mValidity = new mozilla::dom::ValidityState(this);
   }
 
-  NS_ADDREF(*aValidity = mValidity);
+  return mValidity;
+}
+
+nsresult
+nsIConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
+{
+  NS_ENSURE_ARG_POINTER(aValidity);
+
+  NS_ADDREF(*aValidity = Validity());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
 {
   aValidationMessage.Truncate();
@@ -84,32 +91,40 @@ nsIConstraintValidation::GetValidationMe
     }
   } else {
     aValidationMessage.Truncate();
   }
 
   return NS_OK;
 }
 
-nsresult
-nsIConstraintValidation::CheckValidity(bool* aValidity)
+bool
+nsIConstraintValidation::CheckValidity()
 {
   if (!IsCandidateForConstraintValidation() || IsValid()) {
-    *aValidity = true;
-    return NS_OK;
+    return true;
   }
 
-  *aValidity = false;
-
   nsCOMPtr<nsIContent> content = do_QueryInterface(this);
   NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
 
-  return nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
-                                              NS_LITERAL_STRING("invalid"),
-                                              false, true);
+  nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
+                                       NS_LITERAL_STRING("invalid"),
+                                       false, true);
+  return false;
+}
+
+nsresult
+nsIConstraintValidation::CheckValidity(bool* aValidity)
+{
+  NS_ENSURE_ARG_POINTER(aValidity);
+
+  *aValidity = CheckValidity();
+
+  return NS_OK;
 }
 
 void
 nsIConstraintValidation::SetValidityState(ValidityStateType aState,
                                           bool aValue)
 {
   bool previousValidity = IsValid();
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ValidityState.webidl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#validitystate
+ * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce
+ * 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 rangeUnderflow;
+  readonly attribute boolean rangeOverflow;
+  readonly attribute boolean stepMismatch;
+//  readonly attribute boolean badInput;
+  readonly attribute boolean customError;
+  readonly attribute boolean valid;
+};
+
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -159,16 +159,17 @@ webidl_files = \
   SVGUnitTypes.webidl \
   SVGURIReference.webidl \
   SVGViewElement.webidl \
   SVGZoomAndPan.webidl \
   Text.webidl \
   TextDecoder.webidl \
   TextEncoder.webidl \
   URL.webidl \
+  ValidityState.webidl \
   WebSocket.webidl \
   UndoManager.webidl \
   XMLHttpRequest.webidl \
   XMLHttpRequestEventTarget.webidl \
   XMLHttpRequestUpload.webidl \
   XMLSerializer.webidl \
   XPathEvaluator.webidl \
   $(NULL)