Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(960)

Unified Diff: Source/core/html/HTMLFormControlElement.cpp

Issue 672163002: Fix bug where form/fieldset :valid/:invalid won't be recalculated upon control's willValidate change Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add layout tests to catch the problem Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/HTMLFormControlElement.cpp
diff --git a/Source/core/html/HTMLFormControlElement.cpp b/Source/core/html/HTMLFormControlElement.cpp
index 75f2402d2c782128eb57e2c5c92b7f9adfe90112..2018afe65268e7eceff9da7192b201489fabd6ca 100644
--- a/Source/core/html/HTMLFormControlElement.cpp
+++ b/Source/core/html/HTMLFormControlElement.cpp
@@ -268,23 +268,19 @@ void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint)
FormAssociatedElement::removedFrom(insertionPoint);
}
-void HTMLFormControlElement::willChangeForm()
+void HTMLFormControlElement::didChangeForm(HTMLFormElement* oldForm)
{
- formOwnerSetNeedsValidityCheck();
- FormAssociatedElement::willChangeForm();
+ FormAssociatedElement::didChangeForm(oldForm);
+ if (oldForm)
+ oldForm->setNeedsValidityCheck(ElementRemoval, isValidElement());
+ formOwnerSetNeedsValidityCheck(ElementAddition, isValidElement());
}
-void HTMLFormControlElement::didChangeForm()
-{
- formOwnerSetNeedsValidityCheck();
- FormAssociatedElement::didChangeForm();
-}
-
-void HTMLFormControlElement::formOwnerSetNeedsValidityCheck()
+void HTMLFormControlElement::formOwnerSetNeedsValidityCheck(ValidityChangeAction action, bool isValid)
{
HTMLFormElement* form = formOwner();
if (form)
- form->setNeedsValidityCheck();
+ form->setNeedsValidityCheck(action, isValid);
}
void HTMLFormControlElement::fieldSetAncestorsSetNeedsValidityCheck(Node* node)
@@ -410,15 +406,25 @@ bool HTMLFormControlElement::recalcWillValidate() const
return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly();
}
+bool HTMLFormControlElement::refreshWillValidate()
+{
+ bool newWillValidate = recalcWillValidate();
+ if (m_willValidateInitialized && m_willValidate == newWillValidate)
+ return false;
+ m_willValidateInitialized = true;
+ m_willValidate = newWillValidate;
+ // Use m_isValid, because isValidElement() calls valid(), which in turn can
+ // call willValidate() again.
keishi 2014/10/24 10:25:49 Is this true? m_willValidateInitialized is set to
Bartek Nowierski 2014/10/24 10:48:30 It's a little more complex than that. Calling isVa
keishi 2014/10/24 11:07:17 I think using ElementAddition/Removal here when we
Bartek Nowierski 2014/10/24 14:47:16 Done.
+ formOwnerSetNeedsValidityCheck(newWillValidate ? ElementAddition : ElementRemoval, m_isValid);
+ fieldSetAncestorsSetNeedsValidityCheck(parentNode());
+ setNeedsValidityCheck();
+ return true;
+}
+
bool HTMLFormControlElement::willValidate() const
{
if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) {
- m_willValidateInitialized = true;
- bool newWillValidate = recalcWillValidate();
- if (m_willValidate != newWillValidate) {
- m_willValidate = newWillValidate;
- const_cast<HTMLFormControlElement*>(this)->setNeedsValidityCheck();
- }
+ const_cast<HTMLFormControlElement*>(this)->refreshWillValidate();
} else {
// If the following assertion fails, setNeedsWillValidateCheck() is not
// called correctly when something which changes recalcWillValidate() result
@@ -431,13 +437,8 @@ bool HTMLFormControlElement::willValidate() const
void HTMLFormControlElement::setNeedsWillValidateCheck()
{
// We need to recalculate willValidate immediately because willValidate change can causes style change.
- bool newWillValidate = recalcWillValidate();
- if (m_willValidateInitialized && m_willValidate == newWillValidate)
- return;
- m_willValidateInitialized = true;
- m_willValidate = newWillValidate;
- setNeedsValidityCheck();
- setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Validate));
+ if (refreshWillValidate())
+ setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Validate));
if (!m_willValidate)
hideVisibleValidationMessage();
}
@@ -564,13 +565,14 @@ bool HTMLFormControlElement::isValidElement()
void HTMLFormControlElement::setNeedsValidityCheck()
{
bool newIsValid = valid();
- if (willValidate() && newIsValid != m_isValid) {
- formOwnerSetNeedsValidityCheck();
+ bool changed = newIsValid != m_isValid;
+ m_isValid = newIsValid;
+ if (willValidate() && changed) {
+ formOwnerSetNeedsValidityCheck(ElementModification, newIsValid);
fieldSetAncestorsSetNeedsValidityCheck(parentNode());
// Update style for pseudo classes such as :valid :invalid.
setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid));
}
- m_isValid = newIsValid;
// Updates only if this control already has a validation message.
if (isValidationMessageVisible()) {

Powered by Google App Engine
This is Rietveld 408576698