mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1850293 - Make validity states non-intrinsic. r=smaug
Add a RAII helper to notify of multiple state changes together for these. The UpdateState CustomElementInternals calls that are getting removed are unnecessary (the state should be up-to-date by then, there's nothing changing there particularly). Same for the call in nsGenericHTMLFormElement::UnbindFromTree. ClearForm already does an state update. Differential Revision: https://phabricator.services.mozilla.com/D187033
This commit is contained in:
parent
7855659a73
commit
c27a2129fd
@ -651,9 +651,7 @@ class Element : public FragmentOrElement {
|
|||||||
|
|
||||||
const AttrArray& GetAttrs() const { return mAttrs; }
|
const AttrArray& GetAttrs() const { return mAttrs; }
|
||||||
|
|
||||||
void SetDefined(bool aSet) {
|
void SetDefined(bool aSet) { SetStates(ElementState::DEFINED, aSet); }
|
||||||
SetStates(ElementState::DEFINED, aSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessibilityRole
|
// AccessibilityRole
|
||||||
REFLECT_DOMSTRING_ATTR(Role, role)
|
REFLECT_DOMSTRING_ATTR(Role, role)
|
||||||
@ -728,6 +726,25 @@ class Element : public FragmentOrElement {
|
|||||||
already_AddRefed<ShadowRoot> AttachShadowInternal(ShadowRootMode,
|
already_AddRefed<ShadowRoot> AttachShadowInternal(ShadowRootMode,
|
||||||
ErrorResult& aError);
|
ErrorResult& aError);
|
||||||
|
|
||||||
|
struct AutoStateChangeNotifier {
|
||||||
|
AutoStateChangeNotifier(Element& aElement, bool aNotify)
|
||||||
|
: mElement(aElement), mOldState(aElement.State()), mNotify(aNotify) {}
|
||||||
|
~AutoStateChangeNotifier() {
|
||||||
|
if (!mNotify) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ElementState newState = mElement.State();
|
||||||
|
if (mOldState != newState) {
|
||||||
|
mElement.NotifyStateChange(mOldState ^ newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Element& mElement;
|
||||||
|
const ElementState mOldState;
|
||||||
|
const bool mNotify;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsIScrollableFrame* GetScrollFrame(nsIFrame** aStyledFrame = nullptr,
|
nsIScrollableFrame* GetScrollFrame(nsIFrame** aStyledFrame = nullptr,
|
||||||
|
@ -66,7 +66,7 @@ bool Link::ElementHasHref() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Link::SetLinkState(State aState, bool aNotify) {
|
void Link::SetLinkState(State aState, bool aNotify) {
|
||||||
auto old = mElement->State();
|
Element::AutoStateChangeNotifier notifier(*mElement, aNotify);
|
||||||
switch (aState) {
|
switch (aState) {
|
||||||
case State::Visited:
|
case State::Visited:
|
||||||
mElement->AddStatesSilently(ElementState::VISITED);
|
mElement->AddStatesSilently(ElementState::VISITED);
|
||||||
@ -80,9 +80,6 @@ void Link::SetLinkState(State aState, bool aNotify) {
|
|||||||
mElement->RemoveStatesSilently(ElementState::VISITED_OR_UNVISITED);
|
mElement->RemoveStatesSilently(ElementState::VISITED_OR_UNVISITED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aNotify) {
|
|
||||||
mElement->NotifyStateChange(old ^ mElement->State());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Link::TriggerLinkUpdate(bool aNotify) {
|
void Link::TriggerLinkUpdate(bool aNotify) {
|
||||||
|
@ -46,6 +46,8 @@ bitflags! {
|
|||||||
const USER_VALID = 1 << 12;
|
const USER_VALID = 1 << 12;
|
||||||
/// <https://drafts.csswg.org/selectors-4/#user-invalid-pseudo>
|
/// <https://drafts.csswg.org/selectors-4/#user-invalid-pseudo>
|
||||||
const USER_INVALID = 1 << 13;
|
const USER_INVALID = 1 << 13;
|
||||||
|
/// All the validity bits at once.
|
||||||
|
const VALIDITY_STATES = Self::VALID.bits | Self::INVALID.bits | Self::USER_VALID.bits | Self::USER_INVALID.bits;
|
||||||
/// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-broken
|
/// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-broken
|
||||||
const BROKEN = 1 << 14;
|
const BROKEN = 1 << 14;
|
||||||
/// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-loading
|
/// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-loading
|
||||||
@ -188,7 +190,8 @@ bitflags! {
|
|||||||
Self::INRANGE.bits |
|
Self::INRANGE.bits |
|
||||||
Self::OUTOFRANGE.bits |
|
Self::OUTOFRANGE.bits |
|
||||||
Self::VISITED.bits |
|
Self::VISITED.bits |
|
||||||
Self::UNVISITED.bits;
|
Self::UNVISITED.bits |
|
||||||
|
Self::VALIDITY_STATES.bits;
|
||||||
|
|
||||||
const INTRINSIC_STATES = !Self::EXTERNALLY_MANAGED_STATES.bits;
|
const INTRINSIC_STATES = !Self::EXTERNALLY_MANAGED_STATES.bits;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ void ElementInternals::SetValidity(
|
|||||||
SetValidityState(VALIDITY_STATE_STEP_MISMATCH, aFlags.mStepMismatch);
|
SetValidityState(VALIDITY_STATE_STEP_MISMATCH, aFlags.mStepMismatch);
|
||||||
SetValidityState(VALIDITY_STATE_BAD_INPUT, aFlags.mBadInput);
|
SetValidityState(VALIDITY_STATE_BAD_INPUT, aFlags.mBadInput);
|
||||||
SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, aFlags.mCustomError);
|
SetValidityState(VALIDITY_STATE_CUSTOM_ERROR, aFlags.mCustomError);
|
||||||
mTarget->UpdateState(true);
|
mTarget->UpdateValidityElementStates(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 5. Set element's validation message to the empty string if message is not
|
* 5. Set element's validation message to the empty string if message is not
|
||||||
@ -305,8 +305,6 @@ bool ElementInternals::ReportValidity(ErrorResult& aRv) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTarget->UpdateState(true);
|
|
||||||
|
|
||||||
RefPtr<CustomEvent> event =
|
RefPtr<CustomEvent> event =
|
||||||
NS_NewDOMCustomEvent(mTarget->OwnerDoc(), nullptr, nullptr);
|
NS_NewDOMCustomEvent(mTarget->OwnerDoc(), nullptr, nullptr);
|
||||||
event->InitCustomEvent(jsapi.cx(), u"MozInvalidForm"_ns,
|
event->InitCustomEvent(jsapi.cx(), u"MozInvalidForm"_ns,
|
||||||
@ -448,8 +446,6 @@ nsresult ElementInternals::SetAttr(nsAtom* aName, const nsAString& aValue) {
|
|||||||
|
|
||||||
MutationObservers::NotifyARIAAttributeDefaultChanged(mTarget, aName, modType);
|
MutationObservers::NotifyARIAAttributeDefaultChanged(mTarget, aName, modType);
|
||||||
|
|
||||||
mTarget->UpdateState(true);
|
|
||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +76,7 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
|
|||||||
|
|
||||||
void HTMLButtonElement::SetCustomValidity(const nsAString& aError) {
|
void HTMLButtonElement::SetCustomValidity(const nsAString& aError) {
|
||||||
ConstraintValidation::SetCustomValidity(aError);
|
ConstraintValidation::SetCustomValidity(aError);
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLButtonElement::UpdateBarredFromConstraintValidation() {
|
void HTMLButtonElement::UpdateBarredFromConstraintValidation() {
|
||||||
@ -94,7 +93,7 @@ void HTMLButtonElement::FieldSetDisabledChanged(bool aNotify) {
|
|||||||
nsGenericHTMLFormControlElementWithState::FieldSetDisabledChanged(aNotify);
|
nsGenericHTMLFormControlElementWithState::FieldSetDisabledChanged(aNotify);
|
||||||
|
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ELEMENT_CLONE(HTMLButtonElement)
|
NS_IMPL_ELEMENT_CLONE(HTMLButtonElement)
|
||||||
@ -269,9 +268,7 @@ nsresult HTMLButtonElement::BindToTree(BindContext& aContext,
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
UpdateValidityElementStates(false);
|
||||||
// Update our state; we may now be the default submit element
|
|
||||||
UpdateState(false);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -280,9 +277,7 @@ void HTMLButtonElement::UnbindFromTree(bool aNullParent) {
|
|||||||
nsGenericHTMLFormControlElementWithState::UnbindFromTree(aNullParent);
|
nsGenericHTMLFormControlElementWithState::UnbindFromTree(aNullParent);
|
||||||
|
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
UpdateValidityElementStates(false);
|
||||||
// Update our state; we may no longer be the default submit element
|
|
||||||
UpdateState(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -358,6 +353,7 @@ void HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,23 +379,20 @@ bool HTMLButtonElement::RestoreState(PresState* aState) {
|
|||||||
if (aState && aState->disabledSet() && !aState->disabled()) {
|
if (aState && aState->disabledSet() && !aState->disabled()) {
|
||||||
SetDisabled(false, IgnoreErrors());
|
SetDisabled(false, IgnoreErrors());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLButtonElement::IntrinsicState() const {
|
void HTMLButtonElement::UpdateValidityElementStates(bool aNotify) {
|
||||||
ElementState state =
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
nsGenericHTMLFormControlElementWithState::IntrinsicState();
|
RemoveStatesSilently(ElementState::VALIDITY_STATES);
|
||||||
|
if (!IsCandidateForConstraintValidation()) {
|
||||||
if (IsCandidateForConstraintValidation()) {
|
return;
|
||||||
if (IsValid()) {
|
}
|
||||||
state |= ElementState::VALID | ElementState::USER_VALID;
|
if (IsValid()) {
|
||||||
} else {
|
AddStatesSilently(ElementState::VALID | ElementState::USER_VALID);
|
||||||
state |= ElementState::INVALID | ElementState::USER_INVALID;
|
} else {
|
||||||
}
|
AddStatesSilently(ElementState::INVALID | ElementState::USER_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* HTMLButtonElement::WrapNode(JSContext* aCx,
|
JSObject* HTMLButtonElement::WrapNode(JSContext* aCx,
|
||||||
|
@ -64,8 +64,7 @@ class HTMLButtonElement final : public nsGenericHTMLFormControlElementWithState,
|
|||||||
void DoneCreatingElement() override;
|
void DoneCreatingElement() override;
|
||||||
|
|
||||||
void UpdateBarredFromConstraintValidation();
|
void UpdateBarredFromConstraintValidation();
|
||||||
// Element
|
void UpdateValidityElementStates(bool aNotify) final;
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
/**
|
/**
|
||||||
* Called when an attribute is about to be changed
|
* Called when an attribute is about to be changed
|
||||||
*/
|
*/
|
||||||
|
@ -331,24 +331,25 @@ void HTMLElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
UpdateReadOnlyState(aNotify);
|
UpdateReadOnlyState(aNotify);
|
||||||
}
|
}
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormElement::AfterSetAttr(
|
return nsGenericHTMLFormElement::AfterSetAttr(
|
||||||
aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify);
|
aNameSpaceID, aName, aValue, aOldValue, aMaybeScriptedPrincipal, aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLElement::IntrinsicState() const {
|
void HTMLElement::UpdateValidityElementStates(bool aNotify) {
|
||||||
ElementState state = nsGenericHTMLFormElement::IntrinsicState();
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
if (ElementInternals* internals = GetElementInternals()) {
|
RemoveStatesSilently(ElementState::VALIDITY_STATES);
|
||||||
if (internals->IsCandidateForConstraintValidation()) {
|
ElementInternals* internals = GetElementInternals();
|
||||||
if (internals->IsValid()) {
|
if (!internals || !internals->IsCandidateForConstraintValidation()) {
|
||||||
state |= ElementState::VALID | ElementState::USER_VALID;
|
return;
|
||||||
} else {
|
}
|
||||||
state |= ElementState::INVALID | ElementState::USER_INVALID;
|
if (internals->IsValid()) {
|
||||||
}
|
AddStatesSilently(ElementState::VALID | ElementState::USER_VALID);
|
||||||
}
|
} else {
|
||||||
|
AddStatesSilently(ElementState::INVALID | ElementState::USER_INVALID);
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLElement::SetFormInternal(HTMLFormElement* aForm, bool aBindToTree) {
|
void HTMLElement::SetFormInternal(HTMLFormElement* aForm, bool aBindToTree) {
|
||||||
|
@ -49,6 +49,7 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||||||
void AfterClearForm(bool aUnbindOrDelete) override;
|
void AfterClearForm(bool aUnbindOrDelete) override;
|
||||||
void FieldSetDisabledChanged(bool aNotify) override;
|
void FieldSetDisabledChanged(bool aNotify) override;
|
||||||
void SaveState() override;
|
void SaveState() override;
|
||||||
|
void UpdateValidityElementStates(bool aNotify) final;
|
||||||
|
|
||||||
void UpdateFormOwner();
|
void UpdateFormOwner();
|
||||||
|
|
||||||
@ -67,7 +68,6 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||||||
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
|
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
|
||||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||||
bool aNotify) override;
|
bool aNotify) override;
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
|
|
||||||
// nsGenericHTMLFormElement
|
// nsGenericHTMLFormElement
|
||||||
void SetFormInternal(HTMLFormElement* aForm, bool aBindToTree) override;
|
void SetFormInternal(HTMLFormElement* aForm, bool aBindToTree) override;
|
||||||
|
@ -294,7 +294,10 @@ void HTMLFieldSetElement::UpdateValidity(bool aElementValidity) {
|
|||||||
// - or there is one invalid elmement and an element just became invalid.
|
// - or there is one invalid elmement and an element just became invalid.
|
||||||
if (!mInvalidElementsCount ||
|
if (!mInvalidElementsCount ||
|
||||||
(mInvalidElementsCount == 1 && !aElementValidity)) {
|
(mInvalidElementsCount == 1 && !aElementValidity)) {
|
||||||
UpdateState(true);
|
AutoStateChangeNotifier notifier(*this, true);
|
||||||
|
RemoveStatesSilently(ElementState::VALID | ElementState::INVALID);
|
||||||
|
AddStatesSilently(mInvalidElementsCount ? ElementState::INVALID
|
||||||
|
: ElementState::VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should propagate the change to the fieldset parent chain.
|
// We should propagate the change to the fieldset parent chain.
|
||||||
@ -303,18 +306,6 @@ void HTMLFieldSetElement::UpdateValidity(bool aElementValidity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLFieldSetElement::IntrinsicState() const {
|
|
||||||
ElementState state = nsGenericHTMLFormControlElement::IntrinsicState();
|
|
||||||
|
|
||||||
if (mInvalidElementsCount) {
|
|
||||||
state |= ElementState::INVALID;
|
|
||||||
} else {
|
|
||||||
state |= ElementState::VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject* HTMLFieldSetElement::WrapNode(JSContext* aCx,
|
JSObject* HTMLFieldSetElement::WrapNode(JSContext* aCx,
|
||||||
JS::Handle<JSObject*> aGivenProto) {
|
JS::Handle<JSObject*> aGivenProto) {
|
||||||
return HTMLFieldSetElement_Binding::Wrap(aCx, this, aGivenProto);
|
return HTMLFieldSetElement_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
|
@ -90,8 +90,6 @@ class HTMLFieldSetElement final : public nsGenericHTMLFormControlElement,
|
|||||||
|
|
||||||
// XPCOM SetCustomValidity is OK for us
|
// XPCOM SetCustomValidity is OK for us
|
||||||
|
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This method will update the fieldset's validity. This method has to be
|
* This method will update the fieldset's validity. This method has to be
|
||||||
* called by fieldset elements whenever their validity state or status
|
* called by fieldset elements whenever their validity state or status
|
||||||
@ -133,7 +131,7 @@ class HTMLFieldSetElement final : public nsGenericHTMLFormControlElement,
|
|||||||
* Number of invalid and candidate for constraint validation
|
* Number of invalid and candidate for constraint validation
|
||||||
* elements in the fieldSet the last time UpdateValidity has been called.
|
* elements in the fieldSet the last time UpdateValidity has been called.
|
||||||
*
|
*
|
||||||
* @note Should only be used by UpdateValidity() and IntrinsicState()!
|
* @note Should only be used by UpdateValidity()
|
||||||
*/
|
*/
|
||||||
int32_t mInvalidElementsCount;
|
int32_t mInvalidElementsCount;
|
||||||
};
|
};
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
|
|
||||||
// radio buttons
|
// radio buttons
|
||||||
#include "mozilla/dom/HTMLInputElement.h"
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
|
#include "mozilla/dom/HTMLButtonElement.h"
|
||||||
|
#include "mozilla/dom/HTMLSelectElement.h"
|
||||||
#include "nsIRadioVisitor.h"
|
#include "nsIRadioVisitor.h"
|
||||||
#include "RadioNodeList.h"
|
#include "RadioNodeList.h"
|
||||||
|
|
||||||
@ -388,9 +390,6 @@ static void CollectOrphans(nsINode* aRemovalRoot,
|
|||||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
||||||
MOZ_ASSERT(fc);
|
MOZ_ASSERT(fc);
|
||||||
fc->ClearForm(true, false);
|
fc->ClearForm(true, false);
|
||||||
|
|
||||||
// When a form control loses its form owner, its state can change.
|
|
||||||
node->UpdateState(true);
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
removed = true;
|
removed = true;
|
||||||
#endif
|
#endif
|
||||||
@ -1215,7 +1214,6 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
|||||||
// unless it replaces what's in the slot. If it _does_ replace what's in
|
// unless it replaces what's in the slot. If it _does_ replace what's in
|
||||||
// the slot, it becomes the default submit if either the default submit is
|
// the slot, it becomes the default submit if either the default submit is
|
||||||
// what's in the slot or the child is earlier than the default submit.
|
// what's in the slot or the child is earlier than the default submit.
|
||||||
nsGenericHTMLFormElement* oldDefaultSubmit = mDefaultSubmitElement;
|
|
||||||
if (!*firstSubmitSlot ||
|
if (!*firstSubmitSlot ||
|
||||||
(!lastElement && nsContentUtils::CompareTreePosition(
|
(!lastElement && nsContentUtils::CompareTreePosition(
|
||||||
aChild, *firstSubmitSlot, this) < 0)) {
|
aChild, *firstSubmitSlot, this) < 0)) {
|
||||||
@ -1236,13 +1234,6 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
|||||||
mDefaultSubmitElement == mFirstSubmitNotInElements ||
|
mDefaultSubmitElement == mFirstSubmitNotInElements ||
|
||||||
!mDefaultSubmitElement,
|
!mDefaultSubmitElement,
|
||||||
"What happened here?");
|
"What happened here?");
|
||||||
|
|
||||||
// Notify that the state of the previous default submit element has changed
|
|
||||||
// if the element which is the default submit element has changed. The new
|
|
||||||
// default submit element is responsible for its own state update.
|
|
||||||
if (oldDefaultSubmit && oldDefaultSubmit != mDefaultSubmitElement) {
|
|
||||||
oldDefaultSubmit->UpdateState(aNotify);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the element is subject to constraint validaton and is invalid, we need
|
// If the element is subject to constraint validaton and is invalid, we need
|
||||||
@ -1342,7 +1333,7 @@ nsresult HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
|
|||||||
// own notifications.
|
// own notifications.
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the element was subject to constraint validaton and is invalid, we need
|
// If the element was subject to constraint validation and is invalid, we need
|
||||||
// to update our internal counter.
|
// to update our internal counter.
|
||||||
if (aUpdateValidity) {
|
if (aUpdateValidity) {
|
||||||
nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aChild);
|
nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aChild);
|
||||||
@ -1794,30 +1785,27 @@ bool HTMLFormElement::CheckValidFormSubmission() {
|
|||||||
|
|
||||||
nsAutoScriptBlocker scriptBlocker;
|
nsAutoScriptBlocker scriptBlocker;
|
||||||
|
|
||||||
for (uint32_t i = 0, length = mControls->mElements.Length(); i < length;
|
for (nsGenericHTMLFormElement* element : mControls->mElements) {
|
||||||
++i) {
|
|
||||||
// Input elements can trigger a form submission and we want to
|
// Input elements can trigger a form submission and we want to
|
||||||
// update the style in that case.
|
// update the style in that case.
|
||||||
if (mControls->mElements[i]->IsHTMLElement(nsGkAtoms::input) &&
|
if (auto* input = HTMLInputElement::FromNode(*element)) {
|
||||||
// We don't use nsContentUtils::IsFocusedContent here, because it
|
// We don't use nsContentUtils::IsFocusedContent here, because it
|
||||||
// doesn't really do what we want for number controls: it's true
|
// doesn't really do what we want for number controls: it's true
|
||||||
// for the anonymous textnode inside, but not the number control
|
// for the anonymous textnode inside, but not the number control
|
||||||
// itself. We can use the focus state, though, because that gets
|
// itself. We can use the focus state, though, because that gets
|
||||||
// synced to the number control by the anonymous text control.
|
// synced to the number control by the anonymous text control.
|
||||||
mControls->mElements[i]->State().HasState(ElementState::FOCUS)) {
|
if (input->State().HasState(ElementState::FOCUS)) {
|
||||||
static_cast<HTMLInputElement*>(mControls->mElements[i])
|
input->UpdateValidityUIBits(true);
|
||||||
->UpdateValidityUIBits(true);
|
}
|
||||||
}
|
}
|
||||||
|
element->UpdateValidityElementStates(true);
|
||||||
mControls->mElements[i]->UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because of backward compatibility, <input type='image'> is not in
|
// Because of backward compatibility, <input type='image'> is not in
|
||||||
// elements but can be invalid.
|
// elements but can be invalid.
|
||||||
// TODO: should probably be removed when bug 606491 will be fixed.
|
// TODO: should probably be removed when bug 606491 will be fixed.
|
||||||
for (uint32_t i = 0, length = mControls->mNotInElements.Length();
|
for (nsGenericHTMLFormElement* element : mControls->mNotInElements) {
|
||||||
i < length; ++i) {
|
element->UpdateValidityElementStates(true);
|
||||||
mControls->mNotInElements[i]->UpdateState(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1861,7 +1849,10 @@ void HTMLFormElement::UpdateValidity(bool aElementValidity) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateState(true);
|
AutoStateChangeNotifier notifier(*this, true);
|
||||||
|
RemoveStatesSilently(ElementState::VALID | ElementState::INVALID);
|
||||||
|
AddStatesSilently(mInvalidElementsCount ? ElementState::INVALID
|
||||||
|
: ElementState::VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t HTMLFormElement::IndexOfContent(nsIContent* aContent) {
|
int32_t HTMLFormElement::IndexOfContent(nsIContent* aContent) {
|
||||||
@ -1922,18 +1913,6 @@ void HTMLFormElement::SetValueMissingState(const nsAString& aName,
|
|||||||
RadioGroupManager::SetValueMissingState(aName, aValue);
|
RadioGroupManager::SetValueMissingState(aName, aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLFormElement::IntrinsicState() const {
|
|
||||||
ElementState state = nsGenericHTMLElement::IntrinsicState();
|
|
||||||
|
|
||||||
if (mInvalidElementsCount) {
|
|
||||||
state |= ElementState::INVALID;
|
|
||||||
} else {
|
|
||||||
state |= ElementState::VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HTMLFormElement::Clear() {
|
void HTMLFormElement::Clear() {
|
||||||
for (int32_t i = mImageElements.Length() - 1; i >= 0; i--) {
|
for (int32_t i = mImageElements.Length() - 1; i >= 0; i--) {
|
||||||
mImageElements[i]->ClearForm(false);
|
mImageElements[i]->ClearForm(false);
|
||||||
|
@ -80,8 +80,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
|
|||||||
bool GetValueMissingState(const nsAString& aName) const override;
|
bool GetValueMissingState(const nsAString& aName) const override;
|
||||||
void SetValueMissingState(const nsAString& aName, bool aValue) override;
|
void SetValueMissingState(const nsAString& aName, bool aValue) override;
|
||||||
|
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
|
|
||||||
// EventTarget
|
// EventTarget
|
||||||
void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||||
|
|
||||||
|
@ -1214,6 +1214,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
nsIPrincipal* aSubjectPrincipal,
|
nsIPrincipal* aSubjectPrincipal,
|
||||||
bool aNotify) {
|
bool aNotify) {
|
||||||
if (aNameSpaceID == kNameSpaceID_None) {
|
if (aNameSpaceID == kNameSpaceID_None) {
|
||||||
|
bool needValidityUpdate = false;
|
||||||
if (aName == nsGkAtoms::src) {
|
if (aName == nsGkAtoms::src) {
|
||||||
mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
|
mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
|
||||||
this, aValue ? aValue->GetStringValue() : EmptyString(),
|
this, aValue ? aValue->GetStringValue() : EmptyString(),
|
||||||
@ -1244,6 +1245,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
// GetStepBase() depends on the `value` attribute if `min` is not present,
|
// GetStepBase() depends on the `value` attribute if `min` is not present,
|
||||||
// even if the value doesn't change.
|
// even if the value doesn't change.
|
||||||
UpdateStepMismatchValidityState();
|
UpdateStepMismatchValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checked must be set no matter what type of control it is, since
|
// Checked must be set no matter what type of control it is, since
|
||||||
@ -1261,6 +1263,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
DoSetChecked(!!aValue, aNotify, false);
|
DoSetChecked(!!aValue, aNotify, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aName == nsGkAtoms::type) {
|
if (aName == nsGkAtoms::type) {
|
||||||
@ -1273,6 +1276,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
}
|
}
|
||||||
if (newType != mType) {
|
if (newType != mType) {
|
||||||
HandleTypeChange(newType, aNotify);
|
HandleTypeChange(newType, aNotify);
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1282,6 +1286,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
mType == FormControlType::InputRadio && (mForm || mDoneCreating)) {
|
mType == FormControlType::InputRadio && (mForm || mDoneCreating)) {
|
||||||
AddedToRadioGroup();
|
AddedToRadioGroup();
|
||||||
UpdateValueMissingValidityStateForRadio(false);
|
UpdateValueMissingValidityStateForRadio(false);
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
||||||
@ -1310,10 +1315,13 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
}
|
}
|
||||||
|
needValidityUpdate = true;
|
||||||
} else if (aName == nsGkAtoms::maxlength) {
|
} else if (aName == nsGkAtoms::maxlength) {
|
||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
} else if (aName == nsGkAtoms::minlength) {
|
} else if (aName == nsGkAtoms::minlength) {
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
} else if (aName == nsGkAtoms::pattern) {
|
} else if (aName == nsGkAtoms::pattern) {
|
||||||
// Although pattern attribute only applies to single line text controls,
|
// Although pattern attribute only applies to single line text controls,
|
||||||
// we set this flag for all input types to save having to check the type
|
// we set this flag for all input types to save having to check the type
|
||||||
@ -1323,8 +1331,10 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
if (mDoneCreating) {
|
if (mDoneCreating) {
|
||||||
UpdatePatternMismatchValidityState();
|
UpdatePatternMismatchValidityState();
|
||||||
}
|
}
|
||||||
|
needValidityUpdate = true;
|
||||||
} else if (aName == nsGkAtoms::multiple) {
|
} else if (aName == nsGkAtoms::multiple) {
|
||||||
UpdateTypeMismatchValidityState();
|
UpdateTypeMismatchValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
} else if (aName == nsGkAtoms::max) {
|
} else if (aName == nsGkAtoms::max) {
|
||||||
UpdateHasRange(aNotify);
|
UpdateHasRange(aNotify);
|
||||||
mInputType->MinMaxStepAttrChanged();
|
mInputType->MinMaxStepAttrChanged();
|
||||||
@ -1333,6 +1343,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
// We don't assert the state of underflow during creation since
|
// We don't assert the state of underflow during creation since
|
||||||
// DoneCreatingElement sanitizes.
|
// DoneCreatingElement sanitizes.
|
||||||
UpdateRangeOverflowValidityState();
|
UpdateRangeOverflowValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
||||||
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
||||||
"HTML5 spec does not allow underflow for type=range");
|
"HTML5 spec does not allow underflow for type=range");
|
||||||
@ -1342,6 +1353,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
// See corresponding @max comment
|
// See corresponding @max comment
|
||||||
UpdateRangeUnderflowValidityState();
|
UpdateRangeUnderflowValidityState();
|
||||||
UpdateStepMismatchValidityState();
|
UpdateStepMismatchValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
||||||
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
||||||
"HTML5 spec does not allow underflow for type=range");
|
"HTML5 spec does not allow underflow for type=range");
|
||||||
@ -1349,6 +1361,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
mInputType->MinMaxStepAttrChanged();
|
mInputType->MinMaxStepAttrChanged();
|
||||||
// See corresponding @max comment
|
// See corresponding @max comment
|
||||||
UpdateStepMismatchValidityState();
|
UpdateStepMismatchValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
MOZ_ASSERT(!mDoneCreating || mType != FormControlType::InputRange ||
|
||||||
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
!GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW),
|
||||||
"HTML5 spec does not allow underflow for type=range");
|
"HTML5 spec does not allow underflow for type=range");
|
||||||
@ -1361,6 +1374,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
if (mType == FormControlType::InputNumber) {
|
if (mType == FormControlType::InputNumber) {
|
||||||
// The validity of our value may have changed based on the locale.
|
// The validity of our value may have changed based on the locale.
|
||||||
UpdateValidityState();
|
UpdateValidityState();
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
} else if (aName == nsGkAtoms::autocomplete) {
|
} else if (aName == nsGkAtoms::autocomplete) {
|
||||||
// Clear the cached @autocomplete attribute and autocompleteInfo state.
|
// Clear the cached @autocomplete attribute and autocompleteInfo state.
|
||||||
@ -1372,6 +1386,7 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
f->PlaceholderChanged(aOldValue, aValue);
|
f->PlaceholderChanged(aOldValue, aValue);
|
||||||
}
|
}
|
||||||
UpdatePlaceholderShownState();
|
UpdatePlaceholderShownState();
|
||||||
|
needValidityUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CreatesDateTimeWidget()) {
|
if (CreatesDateTimeWidget()) {
|
||||||
@ -1389,6 +1404,9 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (needValidityUpdate) {
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormControlElementWithState::AfterSetAttr(
|
return nsGenericHTMLFormControlElementWithState::AfterSetAttr(
|
||||||
@ -2250,7 +2268,7 @@ void HTMLInputElement::UpdateValidityState() {
|
|||||||
// become valid/invalid. For other validity states, they will be updated when
|
// become valid/invalid. For other validity states, they will be updated when
|
||||||
// .value is actually changed.
|
// .value is actually changed.
|
||||||
UpdateBadInputValidityState();
|
UpdateBadInputValidityState();
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTMLInputElement::MozIsTextField(bool aExcludePassword) {
|
bool HTMLInputElement::MozIsTextField(bool aExcludePassword) {
|
||||||
@ -2771,9 +2789,7 @@ void HTMLInputElement::SetValueChanged(bool aValueChanged) {
|
|||||||
mValueChanged = aValueChanged;
|
mValueChanged = aValueChanged;
|
||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
// We need to do this unconditionally because the validity ui bits depend on
|
UpdateValidityElementStates(true);
|
||||||
// this.
|
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::SetLastValueChangeWasInteractive(bool aWasInteractive) {
|
void HTMLInputElement::SetLastValueChangeWasInteractive(bool aWasInteractive) {
|
||||||
@ -2785,7 +2801,7 @@ void HTMLInputElement::SetLastValueChangeWasInteractive(bool aWasInteractive) {
|
|||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
if (wasValid != IsValid()) {
|
if (wasValid != IsValid()) {
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2806,15 +2822,11 @@ void HTMLInputElement::DoSetCheckedChanged(bool aCheckedChanged, bool aNotify) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::SetCheckedChangedInternal(bool aCheckedChanged) {
|
void HTMLInputElement::SetCheckedChangedInternal(bool aCheckedChanged) {
|
||||||
bool checkedChangedBefore = mCheckedChanged;
|
if (mCheckedChanged == aCheckedChanged) {
|
||||||
|
return;
|
||||||
mCheckedChanged = aCheckedChanged;
|
|
||||||
|
|
||||||
// This method can't be called when we are not authorized to notify
|
|
||||||
// so we do not need a aNotify parameter.
|
|
||||||
if (checkedChangedBefore != aCheckedChanged) {
|
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
mCheckedChanged = aCheckedChanged;
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::SetChecked(bool aChecked) {
|
void HTMLInputElement::SetChecked(bool aChecked) {
|
||||||
@ -2986,8 +2998,7 @@ void HTMLInputElement::SetCheckedInternal(bool aChecked, bool aNotify) {
|
|||||||
// UpdateState anyway.
|
// UpdateState anyway.
|
||||||
UpdateAllValidityStatesButNotElementState();
|
UpdateAllValidityStatesButNotElementState();
|
||||||
UpdateIndeterminateState(aNotify);
|
UpdateIndeterminateState(aNotify);
|
||||||
// validity state still require UpdateState to be called.
|
UpdateValidityElementStates(aNotify);
|
||||||
UpdateState(aNotify);
|
|
||||||
|
|
||||||
// Notify all radios in the group that value has changed, this is to let
|
// Notify all radios in the group that value has changed, this is to let
|
||||||
// radios to have the chance to update its states, e.g., :indeterminate.
|
// radios to have the chance to update its states, e.g., :indeterminate.
|
||||||
@ -3461,7 +3472,7 @@ void HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection) {
|
|||||||
// regardless because we need the UI to update _now_ or the user will
|
// regardless because we need the UI to update _now_ or the user will
|
||||||
// wonder why the step behavior isn't functioning.
|
// wonder why the step behavior isn't functioning.
|
||||||
UpdateValidityUIBits(true);
|
UpdateValidityUIBits(true);
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3627,8 +3638,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateValidityUIBits(aVisitor.mEvent->mMessage == eFocus);
|
UpdateValidityUIBits(aVisitor.mEvent->mMessage == eFocus);
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
@ -4276,7 +4286,7 @@ nsresult HTMLInputElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(true);
|
||||||
|
|
||||||
if (CreatesDateTimeWidget() && IsInComposedDoc()) {
|
if (CreatesDateTimeWidget() && IsInComposedDoc()) {
|
||||||
// Construct Shadow Root so web content can be hidden in the DOM.
|
// Construct Shadow Root so web content can be hidden in the DOM.
|
||||||
@ -4325,9 +4335,8 @@ void HTMLInputElement::UnbindFromTree(bool aNullParent) {
|
|||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
// We might be no longer disabled because of parent chain changed.
|
// We might be no longer disabled because of parent chain changed.
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6062,34 +6071,38 @@ ElementState HTMLInputElement::IntrinsicState() const {
|
|||||||
if (mType == FormControlType::InputImage) {
|
if (mType == FormControlType::InputImage) {
|
||||||
state |= nsImageLoadingContent::ImageState();
|
state |= nsImageLoadingContent::ImageState();
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsCandidateForConstraintValidation()) {
|
void HTMLInputElement::UpdateValidityElementStates(bool aNotify) {
|
||||||
if (IsValid()) {
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
state |= ElementState::VALID;
|
RemoveStatesSilently(ElementState::VALIDITY_STATES);
|
||||||
} else {
|
if (!IsCandidateForConstraintValidation()) {
|
||||||
state |= ElementState::INVALID;
|
return;
|
||||||
|
}
|
||||||
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
ElementState state;
|
||||||
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
if (IsValid()) {
|
||||||
state |= ElementState::USER_INVALID;
|
state |= ElementState::VALID;
|
||||||
}
|
} else {
|
||||||
}
|
state |= ElementState::INVALID;
|
||||||
|
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
||||||
// :-moz-ui-valid applies if all of the following conditions are true:
|
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
||||||
// 1. The element is not focused, or had either :-moz-ui-valid or
|
state |= ElementState::USER_INVALID;
|
||||||
// :-moz-ui-invalid applying before it was focused ;
|
|
||||||
// 2. The element is either valid or isn't allowed to have
|
|
||||||
// :-moz-ui-invalid applying ;
|
|
||||||
// 3. The element has already been modified or the user tried to submit the
|
|
||||||
// form owner while invalid.
|
|
||||||
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
|
||||||
(IsValid() ||
|
|
||||||
(!state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
|
||||||
state |= ElementState::USER_VALID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// :-moz-ui-valid applies if all of the following conditions are true:
|
||||||
return state;
|
// 1. The element is not focused, or had either :-moz-ui-valid or
|
||||||
|
// :-moz-ui-invalid applying before it was focused ;
|
||||||
|
// 2. The element is either valid or isn't allowed to have
|
||||||
|
// :-moz-ui-invalid applying ;
|
||||||
|
// 3. The element has already been modified or the user tried to submit the
|
||||||
|
// form owner while invalid.
|
||||||
|
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
||||||
|
(IsValid() ||
|
||||||
|
(!state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
||||||
|
state |= ElementState::USER_VALID;
|
||||||
|
}
|
||||||
|
AddStatesSilently(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsTArray<OwningFileOrDirectory> RestoreFileContentData(
|
static nsTArray<OwningFileOrDirectory> RestoreFileContentData(
|
||||||
@ -6540,8 +6553,7 @@ Decimal HTMLInputElement::GetStep() const {
|
|||||||
|
|
||||||
void HTMLInputElement::SetCustomValidity(const nsAString& aError) {
|
void HTMLInputElement::SetCustomValidity(const nsAString& aError) {
|
||||||
ConstraintValidation::SetCustomValidity(aError);
|
ConstraintValidation::SetCustomValidity(aError);
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTMLInputElement::IsTooLong() {
|
bool HTMLInputElement::IsTooLong() {
|
||||||
@ -6705,7 +6717,7 @@ void HTMLInputElement::UpdateAllValidityStates(bool aNotify) {
|
|||||||
bool validBefore = IsValid();
|
bool validBefore = IsValid();
|
||||||
UpdateAllValidityStatesButNotElementState();
|
UpdateAllValidityStatesButNotElementState();
|
||||||
if (validBefore != IsValid()) {
|
if (validBefore != IsValid()) {
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6873,7 +6885,7 @@ void HTMLInputElement::FieldSetDisabledChanged(bool aNotify) {
|
|||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::SetFilePickerFiltersFromAccept(
|
void HTMLInputElement::SetFilePickerFiltersFromAccept(
|
||||||
@ -7115,23 +7127,15 @@ void HTMLInputElement::UpdateValidityUIBits(bool aIsFocused) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::UpdateInRange(bool aNotify) {
|
void HTMLInputElement::UpdateInRange(bool aNotify) {
|
||||||
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
|
RemoveStatesSilently(ElementState::INRANGE | ElementState::OUTOFRANGE);
|
||||||
if (!mHasRange || !IsCandidateForConstraintValidation()) {
|
if (!mHasRange || !IsCandidateForConstraintValidation()) {
|
||||||
RemoveStates(ElementState::INRANGE | ElementState::OUTOFRANGE, aNotify);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool outOfRange = GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) ||
|
bool outOfRange = GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) ||
|
||||||
GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW);
|
GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW);
|
||||||
auto oldState = State();
|
|
||||||
RemoveStatesSilently(ElementState::INRANGE | ElementState::OUTOFRANGE);
|
|
||||||
AddStatesSilently(outOfRange ? ElementState::OUTOFRANGE
|
AddStatesSilently(outOfRange ? ElementState::OUTOFRANGE
|
||||||
: ElementState::INRANGE);
|
: ElementState::INRANGE);
|
||||||
if (!aNotify) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto newState = State();
|
|
||||||
if (oldState != newState) {
|
|
||||||
NotifyStateChange(oldState ^ newState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLInputElement::UpdateHasRange(bool aNotify) {
|
void HTMLInputElement::UpdateHasRange(bool aNotify) {
|
||||||
|
@ -331,6 +331,7 @@ class HTMLInputElement final : public TextControlElement,
|
|||||||
// as needed. aNotify controls whether the element state update
|
// as needed. aNotify controls whether the element state update
|
||||||
// needs to notify.
|
// needs to notify.
|
||||||
void UpdateAllValidityStates(bool aNotify);
|
void UpdateAllValidityStates(bool aNotify);
|
||||||
|
void UpdateValidityElementStates(bool aNotify) final;
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void MaybeUpdateAllValidityStates(bool aNotify) {
|
void MaybeUpdateAllValidityStates(bool aNotify) {
|
||||||
// If you need to add new type which supports validationMessage, you should
|
// If you need to add new type which supports validationMessage, you should
|
||||||
|
@ -56,13 +56,9 @@ void HTMLMeterElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HTMLMeterElement::UpdateOptimumState(bool aNotify) {
|
void HTMLMeterElement::UpdateOptimumState(bool aNotify) {
|
||||||
const auto oldState = State();
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
RemoveStatesSilently(ElementState::METER_OPTIMUM_STATES);
|
RemoveStatesSilently(ElementState::METER_OPTIMUM_STATES);
|
||||||
AddStatesSilently(GetOptimumState());
|
AddStatesSilently(GetOptimumState());
|
||||||
const auto newState = State();
|
|
||||||
if (aNotify && oldState != newState) {
|
|
||||||
NotifyStateChange(oldState ^ newState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -45,8 +45,6 @@ NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
|
|||||||
|
|
||||||
void HTMLOutputElement::SetCustomValidity(const nsAString& aError) {
|
void HTMLOutputElement::SetCustomValidity(const nsAString& aError) {
|
||||||
ConstraintValidation::SetCustomValidity(aError);
|
ConstraintValidation::SetCustomValidity(aError);
|
||||||
|
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -79,21 +77,6 @@ void HTMLOutputElement::DoneAddingChildren(bool aHaveNotified) {
|
|||||||
DescendantsChanged();
|
DescendantsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult HTMLOutputElement::BindToTree(BindContext& aContext,
|
|
||||||
nsINode& aParent) {
|
|
||||||
nsresult rv = nsGenericHTMLFormControlElement::BindToTree(aContext, aParent);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// Unfortunately, we can actually end up having to change our state
|
|
||||||
// as a result of being bound to a tree even from the parser: we
|
|
||||||
// might end up a in a novalidate form, and unlike other form
|
|
||||||
// controls that on its own is enough to make change ui-valid state.
|
|
||||||
// So just go ahead and update our state now.
|
|
||||||
UpdateState(false);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HTMLOutputElement::GetValue(nsAString& aValue) const {
|
void HTMLOutputElement::GetValue(nsAString& aValue) const {
|
||||||
nsContentUtils::GetNodeTextContent(this, true, aValue);
|
nsContentUtils::GetNodeTextContent(this, true, aValue);
|
||||||
}
|
}
|
||||||
|
@ -36,14 +36,12 @@ class HTMLOutputElement final : public nsGenericHTMLFormControlElement,
|
|||||||
|
|
||||||
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
|
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
|
||||||
|
|
||||||
virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
||||||
const nsAString& aValue,
|
const nsAString& aValue,
|
||||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||||
nsAttrValue& aResult) override;
|
nsAttrValue& aResult) override;
|
||||||
|
|
||||||
virtual void DoneAddingChildren(bool aHaveNotified) override;
|
void DoneAddingChildren(bool aHaveNotified) override;
|
||||||
|
|
||||||
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
|
||||||
|
|
||||||
// This function is called when a callback function from nsIMutationObserver
|
// This function is called when a callback function from nsIMutationObserver
|
||||||
// has to be used to update the defaultValue attribute.
|
// has to be used to update the defaultValue attribute.
|
||||||
@ -58,8 +56,7 @@ class HTMLOutputElement final : public nsGenericHTMLFormControlElement,
|
|||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLOutputElement,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLOutputElement,
|
||||||
nsGenericHTMLFormControlElement)
|
nsGenericHTMLFormControlElement)
|
||||||
|
|
||||||
virtual JSObject* WrapNode(JSContext* aCx,
|
JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
// WebIDL
|
// WebIDL
|
||||||
nsDOMTokenList* HtmlFor();
|
nsDOMTokenList* HtmlFor();
|
||||||
|
@ -90,7 +90,7 @@ SafeOptionListMutation::~SafeOptionListMutation() {
|
|||||||
// update validity here as needed, because by now we know our <option>s
|
// update validity here as needed, because by now we know our <option>s
|
||||||
// are where they should be.
|
// are where they should be.
|
||||||
mSelect->UpdateValueMissingValidityState();
|
mSelect->UpdateValueMissingValidityState();
|
||||||
mSelect->UpdateState(mNotify);
|
mSelect->UpdateValidityElementStates(mNotify);
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mSelect->VerifyOptionsArray();
|
mSelect->VerifyOptionsArray();
|
||||||
@ -161,8 +161,7 @@ NS_IMPL_ELEMENT_CLONE(HTMLSelectElement)
|
|||||||
|
|
||||||
void HTMLSelectElement::SetCustomValidity(const nsAString& aError) {
|
void HTMLSelectElement::SetCustomValidity(const nsAString& aError) {
|
||||||
ConstraintValidation::SetCustomValidity(aError);
|
ConstraintValidation::SetCustomValidity(aError);
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLSelectElement::GetAutocomplete(DOMString& aValue) {
|
void HTMLSelectElement::GetAutocomplete(DOMString& aValue) {
|
||||||
@ -344,8 +343,7 @@ nsresult HTMLSelectElement::RemoveOptionsFromList(nsIContent* aOptions,
|
|||||||
// Update the validity state in case of we've just removed the last
|
// Update the validity state in case of we've just removed the last
|
||||||
// option.
|
// option.
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
UpdateState(aNotify);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +679,7 @@ void HTMLSelectElement::OnOptionSelected(nsISelectControlFrame* aSelectFrame,
|
|||||||
|
|
||||||
UpdateSelectedOptions();
|
UpdateSelectedOptions();
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLSelectElement::FindSelectedIndex(int32_t aStartIndex, bool aNotify) {
|
void HTMLSelectElement::FindSelectedIndex(int32_t aStartIndex, bool aNotify) {
|
||||||
@ -1010,7 +1008,7 @@ bool HTMLSelectElement::SelectSomething(bool aNotify) {
|
|||||||
SetSelectedIndexInternal(i, aNotify);
|
SetSelectedIndexInternal(i, aNotify);
|
||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1032,7 +1030,7 @@ nsresult HTMLSelectElement::BindToTree(BindContext& aContext,
|
|||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(false);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1046,7 +1044,7 @@ void HTMLSelectElement::UnbindFromTree(bool aNullParent) {
|
|||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
void HTMLSelectElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||||
@ -1087,13 +1085,14 @@ void HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
} else if (aName == nsGkAtoms::required) {
|
} else if (aName == nsGkAtoms::required) {
|
||||||
// This *has* to be called *before* UpdateValueMissingValidityState
|
// This *has* to be called *before* UpdateValueMissingValidityState
|
||||||
// because UpdateValueMissingValidityState depends on our required
|
// because UpdateValueMissingValidityState depends on our required
|
||||||
// state.
|
// state.
|
||||||
UpdateRequiredState(!!aValue, aNotify);
|
UpdateRequiredState(!!aValue, aNotify);
|
||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
} else if (aName == nsGkAtoms::autocomplete) {
|
} else if (aName == nsGkAtoms::autocomplete) {
|
||||||
// Clear the cached @autocomplete attribute and autocompleteInfo state.
|
// Clear the cached @autocomplete attribute and autocompleteInfo state.
|
||||||
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
|
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
|
||||||
@ -1142,7 +1141,7 @@ void HTMLSelectElement::DoneAddingChildren(bool aHaveNotified) {
|
|||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
|
|
||||||
// And now make sure we update our content state too
|
// And now make sure we update our content state too
|
||||||
UpdateState(aHaveNotified);
|
UpdateValidityElementStates(aHaveNotified);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDefaultSelectionSet = true;
|
mDefaultSelectionSet = true;
|
||||||
@ -1229,44 +1228,45 @@ nsresult HTMLSelectElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
|||||||
} else if (aVisitor.mEvent->mMessage == eBlur) {
|
} else if (aVisitor.mEvent->mMessage == eBlur) {
|
||||||
mCanShowInvalidUI = true;
|
mCanShowInvalidUI = true;
|
||||||
mCanShowValidUI = true;
|
mCanShowValidUI = true;
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormControlElementWithState::PostHandleEvent(aVisitor);
|
return nsGenericHTMLFormControlElementWithState::PostHandleEvent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLSelectElement::IntrinsicState() const {
|
void HTMLSelectElement::UpdateValidityElementStates(bool aNotify) {
|
||||||
ElementState state =
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
nsGenericHTMLFormControlElementWithState::IntrinsicState();
|
RemoveStatesSilently(ElementState::VALIDITY_STATES);
|
||||||
|
if (!IsCandidateForConstraintValidation()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsCandidateForConstraintValidation()) {
|
ElementState state;
|
||||||
if (IsValid()) {
|
if (IsValid()) {
|
||||||
state |= ElementState::VALID;
|
state |= ElementState::VALID;
|
||||||
} else {
|
} else {
|
||||||
state |= ElementState::INVALID;
|
state |= ElementState::INVALID;
|
||||||
|
|
||||||
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
||||||
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
||||||
state |= ElementState::USER_INVALID;
|
state |= ElementState::USER_INVALID;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// :-moz-ui-valid applies if all the following are true:
|
|
||||||
// 1. The element is not focused, or had either :-moz-ui-valid or
|
|
||||||
// :-moz-ui-invalid applying before it was focused ;
|
|
||||||
// 2. The element is either valid or isn't allowed to have
|
|
||||||
// :-moz-ui-invalid applying ;
|
|
||||||
// 3. The element has already been modified or the user tried to submit the
|
|
||||||
// form owner while invalid.
|
|
||||||
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
|
||||||
(IsValid() ||
|
|
||||||
(state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
|
||||||
state |= ElementState::USER_VALID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
// :-moz-ui-valid applies if all the following are true:
|
||||||
|
// 1. The element is not focused, or had either :-moz-ui-valid or
|
||||||
|
// :-moz-ui-invalid applying before it was focused ;
|
||||||
|
// 2. The element is either valid or isn't allowed to have
|
||||||
|
// :-moz-ui-invalid applying ;
|
||||||
|
// 3. The element has already been modified or the user tried to submit the
|
||||||
|
// form owner while invalid.
|
||||||
|
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
||||||
|
(IsValid() ||
|
||||||
|
(state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
||||||
|
state |= ElementState::USER_VALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddStatesSilently(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLSelectElement::SaveState() {
|
void HTMLSelectElement::SaveState() {
|
||||||
@ -1566,7 +1566,7 @@ void HTMLSelectElement::FieldSetDisabledChanged(bool aNotify) {
|
|||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify) {
|
void HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify) {
|
||||||
@ -1578,9 +1578,8 @@ void HTMLSelectElement::SetSelectionChanged(bool aValue, bool aNotify) {
|
|||||||
|
|
||||||
bool previousSelectionChangedValue = mSelectionHasChanged;
|
bool previousSelectionChangedValue = mSelectionHasChanged;
|
||||||
mSelectionHasChanged = aValue;
|
mSelectionHasChanged = aValue;
|
||||||
|
|
||||||
if (mSelectionHasChanged != previousSelectionChangedValue) {
|
if (mSelectionHasChanged != previousSelectionChangedValue) {
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(aNotify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +214,6 @@ class HTMLSelectElement final : public nsGenericHTMLFormControlElementWithState,
|
|||||||
|
|
||||||
void FieldSetDisabledChanged(bool aNotify) override;
|
void FieldSetDisabledChanged(bool aNotify) override;
|
||||||
|
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be called when stuff is added under a child of the select--but *before*
|
* To be called when stuff is added under a child of the select--but *before*
|
||||||
* they are actually added.
|
* they are actually added.
|
||||||
@ -300,6 +298,7 @@ class HTMLSelectElement final : public nsGenericHTMLFormControlElementWithState,
|
|||||||
ValidityStateType aType) override;
|
ValidityStateType aType) override;
|
||||||
|
|
||||||
void UpdateValueMissingValidityState();
|
void UpdateValueMissingValidityState();
|
||||||
|
void UpdateValidityElementStates(bool aNotify) final;
|
||||||
/**
|
/**
|
||||||
* Insert aElement before the node given by aBefore
|
* Insert aElement before the node given by aBefore
|
||||||
*/
|
*/
|
||||||
|
@ -302,9 +302,7 @@ void HTMLTextAreaElement::SetValueChanged(bool aValueChanged) {
|
|||||||
}
|
}
|
||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
// We need to do this unconditionally because the validity ui bits depend on
|
UpdateValidityElementStates(true);
|
||||||
// this.
|
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
|
void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
|
||||||
@ -317,7 +315,7 @@ void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
|
|||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
if (wasValid != IsValid()) {
|
if (wasValid != IsValid()) {
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,8 +495,7 @@ nsresult HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
|||||||
mCanShowInvalidUI = true;
|
mCanShowInvalidUI = true;
|
||||||
mCanShowValidUI = true;
|
mCanShowValidUI = true;
|
||||||
}
|
}
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -745,37 +742,38 @@ bool HTMLTextAreaElement::RestoreState(PresState* aState) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementState HTMLTextAreaElement::IntrinsicState() const {
|
void HTMLTextAreaElement::UpdateValidityElementStates(bool aNotify) {
|
||||||
ElementState state =
|
AutoStateChangeNotifier notifier(*this, aNotify);
|
||||||
nsGenericHTMLFormControlElementWithState::IntrinsicState();
|
RemoveStatesSilently(ElementState::VALIDITY_STATES);
|
||||||
|
if (!IsCandidateForConstraintValidation()) {
|
||||||
if (IsCandidateForConstraintValidation()) {
|
return;
|
||||||
if (IsValid()) {
|
}
|
||||||
state |= ElementState::VALID;
|
ElementState state;
|
||||||
} else {
|
if (IsValid()) {
|
||||||
state |= ElementState::INVALID;
|
state |= ElementState::VALID;
|
||||||
// :-moz-ui-invalid always apply if the element suffers from a custom
|
} else {
|
||||||
// error.
|
state |= ElementState::INVALID;
|
||||||
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
// :-moz-ui-invalid always apply if the element suffers from a custom
|
||||||
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
// error.
|
||||||
state |= ElementState::USER_INVALID;
|
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
|
||||||
}
|
(mCanShowInvalidUI && ShouldShowValidityUI())) {
|
||||||
}
|
state |= ElementState::USER_INVALID;
|
||||||
|
|
||||||
// :-moz-ui-valid applies if all the following are true:
|
|
||||||
// 1. The element is not focused, or had either :-moz-ui-valid or
|
|
||||||
// :-moz-ui-invalid applying before it was focused ;
|
|
||||||
// 2. The element is either valid or isn't allowed to have
|
|
||||||
// :-moz-ui-invalid applying ;
|
|
||||||
// 3. The element has already been modified or the user tried to submit the
|
|
||||||
// form owner while invalid.
|
|
||||||
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
|
||||||
(IsValid() ||
|
|
||||||
(state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
|
||||||
state |= ElementState::USER_VALID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
|
// :-moz-ui-valid applies if all the following are true:
|
||||||
|
// 1. The element is not focused, or had either :-moz-ui-valid or
|
||||||
|
// :-moz-ui-invalid applying before it was focused ;
|
||||||
|
// 2. The element is either valid or isn't allowed to have
|
||||||
|
// :-moz-ui-invalid applying ;
|
||||||
|
// 3. The element has already been modified or the user tried to submit the
|
||||||
|
// form owner while invalid.
|
||||||
|
if (mCanShowValidUI && ShouldShowValidityUI() &&
|
||||||
|
(IsValid() ||
|
||||||
|
(state.HasState(ElementState::USER_INVALID) && !mCanShowInvalidUI))) {
|
||||||
|
state |= ElementState::USER_VALID;
|
||||||
|
}
|
||||||
|
AddStatesSilently(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
|
nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
|
||||||
@ -795,7 +793,7 @@ nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
|
|||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(false);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -808,7 +806,7 @@ void HTMLTextAreaElement::UnbindFromTree(bool aNullParent) {
|
|||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
|
|
||||||
// And now make sure our state is up to date
|
// And now make sure our state is up to date
|
||||||
UpdateState(false);
|
UpdateValidityElementStates(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
void HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||||
@ -908,13 +906,16 @@ void HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
|||||||
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
}
|
}
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
} else if (aName == nsGkAtoms::autocomplete) {
|
} else if (aName == nsGkAtoms::autocomplete) {
|
||||||
// Clear the cached @autocomplete attribute state.
|
// Clear the cached @autocomplete attribute state.
|
||||||
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
|
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
|
||||||
} else if (aName == nsGkAtoms::maxlength) {
|
} else if (aName == nsGkAtoms::maxlength) {
|
||||||
UpdateTooLongValidityState();
|
UpdateTooLongValidityState();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
} else if (aName == nsGkAtoms::minlength) {
|
} else if (aName == nsGkAtoms::minlength) {
|
||||||
UpdateTooShortValidityState();
|
UpdateTooShortValidityState();
|
||||||
|
UpdateValidityElementStates(aNotify);
|
||||||
} else if (aName == nsGkAtoms::placeholder) {
|
} else if (aName == nsGkAtoms::placeholder) {
|
||||||
if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
|
if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
|
||||||
f->PlaceholderChanged(aOldValue, aValue);
|
f->PlaceholderChanged(aOldValue, aValue);
|
||||||
@ -957,8 +958,7 @@ bool HTMLTextAreaElement::IsMutable() const { return !IsDisabledOrReadOnly(); }
|
|||||||
|
|
||||||
void HTMLTextAreaElement::SetCustomValidity(const nsAString& aError) {
|
void HTMLTextAreaElement::SetCustomValidity(const nsAString& aError) {
|
||||||
ConstraintValidation::SetCustomValidity(aError);
|
ConstraintValidation::SetCustomValidity(aError);
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
UpdateState(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTMLTextAreaElement::IsTooLong() {
|
bool HTMLTextAreaElement::IsTooLong() {
|
||||||
@ -1147,7 +1147,7 @@ void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (validBefore != IsValid()) {
|
if (validBefore != IsValid()) {
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,7 +1164,7 @@ void HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify) {
|
|||||||
|
|
||||||
UpdateValueMissingValidityState();
|
UpdateValueMissingValidityState();
|
||||||
UpdateBarredFromConstraintValidation();
|
UpdateBarredFromConstraintValidation();
|
||||||
UpdateState(aNotify);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,
|
JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,
|
||||||
|
@ -71,8 +71,6 @@ class HTMLTextAreaElement final : public TextControlElement,
|
|||||||
|
|
||||||
void FieldSetDisabledChanged(bool aNotify) override;
|
void FieldSetDisabledChanged(bool aNotify) override;
|
||||||
|
|
||||||
ElementState IntrinsicState() const override;
|
|
||||||
|
|
||||||
void SetLastValueChangeWasInteractive(bool);
|
void SetLastValueChangeWasInteractive(bool);
|
||||||
|
|
||||||
// TextControlElement
|
// TextControlElement
|
||||||
@ -393,6 +391,8 @@ class HTMLTextAreaElement final : public TextControlElement,
|
|||||||
void GetSelectionRange(uint32_t* aSelectionStart, uint32_t* aSelectionEnd,
|
void GetSelectionRange(uint32_t* aSelectionStart, uint32_t* aSelectionEnd,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
void UpdateValidityElementStates(bool aNotify) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
|
static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
|
||||||
};
|
};
|
||||||
|
@ -1739,7 +1739,7 @@ void nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm,
|
|||||||
UnsetFlags(ADDED_TO_FORM);
|
UnsetFlags(ADDED_TO_FORM);
|
||||||
SetFormInternal(nullptr, false);
|
SetFormInternal(nullptr, false);
|
||||||
AfterClearForm(aUnbindOrDelete);
|
AfterClearForm(aUnbindOrDelete);
|
||||||
UpdateState(true);
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
||||||
@ -1760,7 +1760,6 @@ nsresult nsGenericHTMLFormElement::BindToTree(BindContext& aContext,
|
|||||||
|
|
||||||
// Set parent fieldset which should be used for the disabled state.
|
// Set parent fieldset which should be used for the disabled state.
|
||||||
UpdateFieldSet(false);
|
UpdateFieldSet(false);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1782,11 +1781,6 @@ void nsGenericHTMLFormElement::UnbindFromTree(bool aNullParent) {
|
|||||||
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetFormInternal()) {
|
|
||||||
// Our novalidate state might have changed
|
|
||||||
UpdateState(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to remove the form id observer if there was one.
|
// We have to remove the form id observer if there was one.
|
||||||
@ -2100,7 +2094,8 @@ void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (form != oldForm) {
|
if (form != oldForm) {
|
||||||
UpdateState(true);
|
// ui-valid / invalid depends on the form for some elements
|
||||||
|
UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,6 +1015,11 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
|
|||||||
*/
|
*/
|
||||||
already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead);
|
already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead);
|
||||||
|
|
||||||
|
// Form changes (in particular whether our current form has been submitted
|
||||||
|
// invalidly) affect the user-valid/user-invalid pseudo-classes. Sub-classes
|
||||||
|
// can override this to react to it.
|
||||||
|
virtual void UpdateValidityElementStates(bool aNotify) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsGenericHTMLFormElement() = default;
|
virtual ~nsGenericHTMLFormElement() = default;
|
||||||
|
|
||||||
|
@ -87,9 +87,9 @@ bool nsIConstraintValidation::ReportValidity() {
|
|||||||
auto* inputElement = HTMLInputElement::FromNode(element);
|
auto* inputElement = HTMLInputElement::FromNode(element);
|
||||||
if (inputElement && inputElement->State().HasState(ElementState::FOCUS)) {
|
if (inputElement && inputElement->State().HasState(ElementState::FOCUS)) {
|
||||||
inputElement->UpdateValidityUIBits(true);
|
inputElement->UpdateValidityUIBits(true);
|
||||||
|
inputElement->UpdateValidityElementStates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
element->UpdateState(true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,8 +111,7 @@ void nsIConstraintValidation::SetValidityState(ValidityStateType aState,
|
|||||||
if (HTMLFormElement* form = formCtrl->GetForm()) {
|
if (HTMLFormElement* form = formCtrl->GetForm()) {
|
||||||
form->UpdateValidity(IsValid());
|
form->UpdateValidity(IsValid());
|
||||||
}
|
}
|
||||||
HTMLFieldSetElement* fieldSet = formCtrl->GetFieldSet();
|
if (HTMLFieldSetElement* fieldSet = formCtrl->GetFieldSet()) {
|
||||||
if (fieldSet) {
|
|
||||||
fieldSet->UpdateValidity(IsValid());
|
fieldSet->UpdateValidity(IsValid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ bool nsRadioSetValueMissingState::Visit(HTMLInputElement* aRadio) {
|
|||||||
|
|
||||||
aRadio->SetValidityState(
|
aRadio->SetValidityState(
|
||||||
nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING, mValidity);
|
nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING, mValidity);
|
||||||
aRadio->UpdateState(true);
|
aRadio->UpdateValidityElementStates(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +44,6 @@ bool nsRadioUpdateStateVisitor::Visit(HTMLInputElement* aRadio) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
aRadio->UpdateIndeterminateState(true);
|
aRadio->UpdateIndeterminateState(true);
|
||||||
aRadio->UpdateState(true);
|
aRadio->UpdateValidityElementStates(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user