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:
Emilio Cobos Álvarez
2023-08-30 09:18:32 +00:00
parent 18854ff8b5
commit 72f00fc947
25 changed files with 249 additions and 299 deletions

View File

@@ -302,9 +302,7 @@ void HTMLTextAreaElement::SetValueChanged(bool aValueChanged) {
}
UpdateTooLongValidityState();
UpdateTooShortValidityState();
// We need to do this unconditionally because the validity ui bits depend on
// this.
UpdateState(true);
UpdateValidityElementStates(true);
}
void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
@@ -317,7 +315,7 @@ void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
UpdateTooLongValidityState();
UpdateTooShortValidityState();
if (wasValid != IsValid()) {
UpdateState(true);
UpdateValidityElementStates(true);
}
}
@@ -497,8 +495,7 @@ nsresult HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
mCanShowInvalidUI = true;
mCanShowValidUI = true;
}
UpdateState(true);
UpdateValidityElementStates(true);
}
return NS_OK;
@@ -745,37 +742,38 @@ bool HTMLTextAreaElement::RestoreState(PresState* aState) {
return false;
}
ElementState HTMLTextAreaElement::IntrinsicState() const {
ElementState state =
nsGenericHTMLFormControlElementWithState::IntrinsicState();
if (IsCandidateForConstraintValidation()) {
if (IsValid()) {
state |= ElementState::VALID;
} else {
state |= ElementState::INVALID;
// :-moz-ui-invalid always apply if the element suffers from a custom
// error.
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;
void HTMLTextAreaElement::UpdateValidityElementStates(bool aNotify) {
AutoStateChangeNotifier notifier(*this, aNotify);
RemoveStatesSilently(ElementState::VALIDITY_STATES);
if (!IsCandidateForConstraintValidation()) {
return;
}
ElementState state;
if (IsValid()) {
state |= ElementState::VALID;
} else {
state |= ElementState::INVALID;
// :-moz-ui-invalid always apply if the element suffers from a custom
// error.
if (GetValidityState(VALIDITY_STATE_CUSTOM_ERROR) ||
(mCanShowInvalidUI && ShouldShowValidityUI())) {
state |= ElementState::USER_INVALID;
}
}
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,
@@ -795,7 +793,7 @@ nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
UpdateBarredFromConstraintValidation();
// And now make sure our state is up to date
UpdateState(false);
UpdateValidityElementStates(false);
return rv;
}
@@ -808,7 +806,7 @@ void HTMLTextAreaElement::UnbindFromTree(bool aNullParent) {
UpdateBarredFromConstraintValidation();
// And now make sure our state is up to date
UpdateState(false);
UpdateValidityElementStates(false);
}
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) {
UpdateBarredFromConstraintValidation();
}
UpdateValidityElementStates(aNotify);
} else if (aName == nsGkAtoms::autocomplete) {
// Clear the cached @autocomplete attribute state.
mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
} else if (aName == nsGkAtoms::maxlength) {
UpdateTooLongValidityState();
UpdateValidityElementStates(aNotify);
} else if (aName == nsGkAtoms::minlength) {
UpdateTooShortValidityState();
UpdateValidityElementStates(aNotify);
} else if (aName == nsGkAtoms::placeholder) {
if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
f->PlaceholderChanged(aOldValue, aValue);
@@ -957,8 +958,7 @@ bool HTMLTextAreaElement::IsMutable() const { return !IsDisabledOrReadOnly(); }
void HTMLTextAreaElement::SetCustomValidity(const nsAString& aError) {
ConstraintValidation::SetCustomValidity(aError);
UpdateState(true);
UpdateValidityElementStates(true);
}
bool HTMLTextAreaElement::IsTooLong() {
@@ -1147,7 +1147,7 @@ void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
}
if (validBefore != IsValid()) {
UpdateState(true);
UpdateValidityElementStates(true);
}
}
@@ -1164,7 +1164,7 @@ void HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify) {
UpdateValueMissingValidityState();
UpdateBarredFromConstraintValidation();
UpdateState(aNotify);
UpdateValidityElementStates(true);
}
JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,