Title: [287551] trunk
Revision
287551
Author
[email protected]
Date
2022-01-03 10:49:55 -0800 (Mon, 03 Jan 2022)

Log Message

[:has() pseudo-class] Style invalidation for :valid and :invalid
https://bugs.webkit.org/show_bug.cgi?id=234815

Reviewed by Sam Weinig.

LayoutTests/imported/w3c:

* web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt: Renamed from LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt.
* web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html: Renamed from LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html.

Source/WebCore:

Use PseudoClassChangeInvalidation for accurate and :has() supporting style invalidation.

Test: imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html

* html/FormAssociatedElement.cpp:
(WebCore::FormAssociatedElement::computeValidity const):
(WebCore::FormAssociatedElement::isValid const): Deleted.
* html/FormAssociatedElement.h:
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::addInvalidDescendant):
(WebCore::HTMLFieldSetElement::removeInvalidDescendant):
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::updateWillValidateAndValidity):
(WebCore::HTMLFormControlElement::isValidFormControlElement const):
(WebCore::HTMLFormControlElement::updateValidity):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::registerInvalidAssociatedFormControl):
(WebCore::HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::computeValidity const):
(WebCore::HTMLInputElement::isValid const): Deleted.
* html/HTMLInputElement.h:
* html/ValidityState.idl:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (287550 => 287551)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-03 18:49:55 UTC (rev 287551)
@@ -1,3 +1,13 @@
+2022-01-03  Antti Koivisto  <[email protected]>
+
+        [:has() pseudo-class] Style invalidation for :valid and :invalid
+        https://bugs.webkit.org/show_bug.cgi?id=234815
+
+        Reviewed by Sam Weinig.
+
+        * web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt: Renamed from LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt.
+        * web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html: Renamed from LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html.
+
 2022-01-03  Antoine Quint  <[email protected]>
 
         [Web Animations] changing the effect of a transition should no longer have it marked as running

Deleted: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt (287550 => 287551)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt	2022-01-03 18:49:55 UTC (rev 287551)
@@ -1,32 +0,0 @@
-
-
-PASS Before set checked on checkbox, testing subject
-PASS Set checked on checkbox, testing subject
-PASS Unset checked on checkbox, testing subject
-PASS Set select on option
-PASS Reset select
-PASS Before set disabled on checkbox, testing subject
-PASS Set disabled on checkbox, testing subject
-PASS Unset disabled on checkbox, testing subject
-PASS Before set disabled on checkbox, testing subject3
-PASS Set disabled on checkbox, testing subject3
-PASS Unset disabled on checkbox, testing subject3
-PASS Before set disabled on option, testing subject
-PASS Set disabled on option, testing subject
-PASS Unset disabled on option, testing subject
-PASS Before set disabled on option, testing subject3
-PASS Set disabled on option, testing subject3
-PASS Unset disabled on option, testing subject3
-PASS Before set disabled on optgroup, testing subject
-PASS Set disabled on optgroup, testing subject
-PASS Unset disabled on optgroup, testing subject
-PASS Before set disabled on optgroup, testing subject2
-PASS Set disabled on optgroup, testing subject2
-PASS Unset disabled on optgroup, testing subject2
-PASS Before set disabled on optgroup, testing subject3
-PASS Set disabled on optgroup, testing subject3
-PASS Unset disabled on optgroup, testing subject3
-PASS Before set disabled on optgroup, testing subject4
-PASS Set disabled on optgroup, testing subject4
-PASS Unset disabled on optgroup, testing subject4
-

Deleted: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html (287550 => 287551)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html	2022-01-03 18:49:55 UTC (rev 287551)
@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Selector Invalidation: :has() with pseudo-classes</title>
-<link rel="author" title="Antti Koivisto" href=""
-<script src=""
-<script src=""
-<link rel="help" href=""
-<style>
-main:has(input) div { color: grey }
-main:has(#checkbox:checked) > #subject { color: red }
-main:has(#option:checked) > #subject { color: red }
-main:has(#checkbox:disabled) > #subject { color: green }
-main:has(#option:disabled) > :is(#subject, #subject2) { color: green }
-main:has(#optgroup:disabled) > #subject { color: blue }
-main:not(:has(#checkbox:enabled)) > #subject3 { color: green }
-main:not(:has(#option:enabled)) :is(#subject3, #subject4) { color: green }
-main:not(:has(#optgroup:enabled)) > #subject3 { color: blue }
-</style>
-
-<main id=main>
-    <input type=checkbox id=checkbox></input>
-    <select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
-    <div id=subject></div>
-    <div id=subject2></div>
-    <div id=subject3></div>
-    <div id=subject4></div>
-</main>
-
-<script>
-const grey = 'rgb(128, 128, 128)';
-const red = 'rgb(255, 0, 0)';
-const green = 'rgb(0, 128, 0)';
-const blue = 'rgb(0, 0, 255)';
-const yellow = 'rgb(255, 255, 0)';
-const purple = 'rgb(128, 0, 128)';
-const pink = 'rgb(255, 192, 203)';
-
-function testColor(test_name, subject_element, color) {
-    test(function() {
-        assert_equals(getComputedStyle(subject_element).color, color);
-    }, test_name);
-}
-
-function testPseudoClassChange(element, property, subject_element, expectedColor)
-{
-    testColor(`Before set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
-
-    element[property] = true;
-    testColor(`Set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, expectedColor);
-
-    element[property] = false;
-    testColor(`Unset ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
-}
-
-function testSelectedChange(option, subject_element, expectedColor)
-{
-    const oldOption = select.selectedOptions[0];
-    option.selected = true;
-    testColor(`Set select on ${option.id}`, subject_element, expectedColor);
-    oldOption.selected = true;
-    testColor(`Reset select`, subject, grey);
-}
-
-testPseudoClassChange(checkbox, "checked", subject, red);
-testSelectedChange(option, subject, red);
-
-testPseudoClassChange(checkbox, "disabled", subject, green);
-testPseudoClassChange(checkbox, "disabled", subject3, green);
-testPseudoClassChange(option, "disabled", subject, green);
-testPseudoClassChange(option, "disabled", subject3, green);
-
-testPseudoClassChange(optgroup, "disabled", subject, blue);
-testPseudoClassChange(optgroup, "disabled", subject2, green);
-testPseudoClassChange(optgroup, "disabled", subject3, blue);
-testPseudoClassChange(optgroup, "disabled", subject4, green);
-
-</script>

Copied: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt (from rev 287550, trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class-expected.txt) (0 => 287551)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt	2022-01-03 18:49:55 UTC (rev 287551)
@@ -0,0 +1,44 @@
+
+
+PASS Before set checked on checkbox, testing subject
+PASS Set checked on checkbox, testing subject
+PASS Unset checked on checkbox, testing subject
+PASS Set select on option
+PASS Reset select
+PASS Before set disabled on checkbox, testing subject
+PASS Set disabled on checkbox, testing subject
+PASS Unset disabled on checkbox, testing subject
+PASS Before set disabled on checkbox, testing subject3
+PASS Set disabled on checkbox, testing subject3
+PASS Unset disabled on checkbox, testing subject3
+PASS Before set disabled on option, testing subject
+PASS Set disabled on option, testing subject
+PASS Unset disabled on option, testing subject
+PASS Before set disabled on option, testing subject3
+PASS Set disabled on option, testing subject3
+PASS Unset disabled on option, testing subject3
+PASS Before set disabled on optgroup, testing subject
+PASS Set disabled on optgroup, testing subject
+PASS Unset disabled on optgroup, testing subject
+PASS Before set disabled on optgroup, testing subject2
+PASS Set disabled on optgroup, testing subject2
+PASS Unset disabled on optgroup, testing subject2
+PASS Before set disabled on optgroup, testing subject3
+PASS Set disabled on optgroup, testing subject3
+PASS Unset disabled on optgroup, testing subject3
+PASS Before set disabled on optgroup, testing subject4
+PASS Set disabled on optgroup, testing subject4
+PASS Unset disabled on optgroup, testing subject4
+PASS Before setting value of text_input, testing subject
+PASS Set value of text_input, testing subject
+PASS Clear value of text_input, testing subject
+PASS Before setting value of text_input, testing subject2
+PASS Set value of text_input, testing subject2
+PASS Clear value of text_input, testing subject2
+PASS Before setting value of text_input, testing subject3
+PASS Set value of text_input, testing subject3
+PASS Clear value of text_input, testing subject3
+PASS Before setting value of text_input, testing subject4
+PASS Set value of text_input, testing subject4
+PASS Clear value of text_input, testing subject4
+

Copied: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html (from rev 287550, trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-pseudo-class.html) (0 => 287551)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html	2022-01-03 18:49:55 UTC (rev 287551)
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() with pseudo-classes</title>
+<link rel="author" title="Antti Koivisto" href=""
+<script src=""
+<script src=""
+<link rel="help" href=""
+<style>
+main:has(input) div { color: grey }
+main:has(#checkbox:checked) > #subject { color: red }
+main:has(#option:checked) > #subject { color: red }
+main:has(#checkbox:disabled) > #subject { color: green }
+main:has(#option:disabled) > :is(#subject, #subject2) { color: green }
+main:has(#optgroup:disabled) > #subject { color: blue }
+main:not(:has(#checkbox:enabled)) > #subject3 { color: green }
+main:not(:has(#option:enabled)) :is(#subject3, #subject4) { color: green }
+main:not(:has(#optgroup:enabled)) > #subject3 { color: blue }
+main:has(#text_input:valid) > #subject { color: yellow }
+main:not(:has(#text_input:invalid)) > #subject2 { color: yellow }
+main:has(#form:valid) > #subject3 { color: yellow }
+main:not(:has(#form:invalid)) > #subject4 { color: yellow }
+</style>
+
+<main id=main>
+    <form id=form>
+        <input type=checkbox id=checkbox></input>
+        <select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
+        <input id=text_input type=text required></input>
+    </form>
+    <div id=subject></div>
+    <div id=subject2></div>
+    <div id=subject3></div>
+    <div id=subject4></div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const yellow = 'rgb(255, 255, 0)';
+const purple = 'rgb(128, 0, 128)';
+const pink = 'rgb(255, 192, 203)';
+
+function testColor(test_name, subject_element, color) {
+    test(function() {
+        assert_equals(getComputedStyle(subject_element).color, color);
+    }, test_name);
+}
+
+function testPseudoClassChange(element, property, subject_element, expectedColor)
+{
+    testColor(`Before set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
+
+    element[property] = true;
+    testColor(`Set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, expectedColor);
+
+    element[property] = false;
+    testColor(`Unset ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
+}
+
+function testSelectedChange(option, subject_element, expectedColor)
+{
+    const oldOption = select.selectedOptions[0];
+    option.selected = true;
+    testColor(`Set select on ${option.id}`, subject_element, expectedColor);
+    oldOption.selected = true;
+    testColor(`Reset select`, subject, grey);
+}
+
+function testValueChange(input, subject_element, expectedColor)
+{
+    testColor(`Before setting value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
+
+    input.value = "value";
+    testColor(`Set value of ${input.id}, testing ${subject_element.id}`, subject_element, expectedColor);
+
+    input.value = "";
+    testColor(`Clear value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
+}
+
+testPseudoClassChange(checkbox, "checked", subject, red);
+testSelectedChange(option, subject, red);
+
+testPseudoClassChange(checkbox, "disabled", subject, green);
+testPseudoClassChange(checkbox, "disabled", subject3, green);
+testPseudoClassChange(option, "disabled", subject, green);
+testPseudoClassChange(option, "disabled", subject3, green);
+
+testPseudoClassChange(optgroup, "disabled", subject, blue);
+testPseudoClassChange(optgroup, "disabled", subject2, green);
+testPseudoClassChange(optgroup, "disabled", subject3, blue);
+testPseudoClassChange(optgroup, "disabled", subject4, green);
+
+testValueChange(text_input, subject, yellow);
+testValueChange(text_input, subject2, yellow);
+testValueChange(text_input, subject3, yellow);
+testValueChange(text_input, subject4, yellow);
+</script>

Modified: trunk/Source/WebCore/ChangeLog (287550 => 287551)


--- trunk/Source/WebCore/ChangeLog	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/ChangeLog	2022-01-03 18:49:55 UTC (rev 287551)
@@ -1,3 +1,34 @@
+2022-01-03  Antti Koivisto  <[email protected]>
+
+        [:has() pseudo-class] Style invalidation for :valid and :invalid
+        https://bugs.webkit.org/show_bug.cgi?id=234815
+
+        Reviewed by Sam Weinig.
+
+        Use PseudoClassChangeInvalidation for accurate and :has() supporting style invalidation.
+
+        Test: imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html
+
+        * html/FormAssociatedElement.cpp:
+        (WebCore::FormAssociatedElement::computeValidity const):
+        (WebCore::FormAssociatedElement::isValid const): Deleted.
+        * html/FormAssociatedElement.h:
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::addInvalidDescendant):
+        (WebCore::HTMLFieldSetElement::removeInvalidDescendant):
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::updateWillValidateAndValidity):
+        (WebCore::HTMLFormControlElement::isValidFormControlElement const):
+        (WebCore::HTMLFormControlElement::updateValidity):
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::registerInvalidAssociatedFormControl):
+        (WebCore::HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::computeValidity const):
+        (WebCore::HTMLInputElement::isValid const): Deleted.
+        * html/HTMLInputElement.h:
+        * html/ValidityState.idl:
+
 2022-01-03  Antoine Quint  <[email protected]>
 
         [Web Animations] changing the effect of a transition should no longer have it marked as running

Modified: trunk/Source/WebCore/html/FormAssociatedElement.cpp (287550 => 287551)


--- trunk/Source/WebCore/html/FormAssociatedElement.cpp	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/FormAssociatedElement.cpp	2022-01-03 18:49:55 UTC (rev 287551)
@@ -253,7 +253,7 @@
     return false;
 }
 
-bool FormAssociatedElement::isValid() const
+bool FormAssociatedElement::computeValidity() const
 {
     bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
         || tooShort() || tooLong() || patternMismatch() || valueMissing() || hasBadInput() || customError();

Modified: trunk/Source/WebCore/html/FormAssociatedElement.h (287550 => 287551)


--- trunk/Source/WebCore/html/FormAssociatedElement.h	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/FormAssociatedElement.h	2022-01-03 18:49:55 UTC (rev 287551)
@@ -85,7 +85,7 @@
     virtual bool typeMismatch() const;
     virtual bool valueMissing() const;
     virtual String validationMessage() const;
-    virtual bool isValid() const;
+    virtual bool computeValidity() const;
     virtual void setCustomValidity(const String&);
 
     void formAttributeTargetChanged();

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.cpp (287550 => 287551)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2022-01-03 18:49:55 UTC (rev 287551)
@@ -32,6 +32,7 @@
 #include "HTMLNames.h"
 #include "HTMLObjectElement.h"
 #include "NodeRareData.h"
+#include "PseudoClassChangeInvalidation.h"
 #include "RenderElement.h"
 #include "ScriptDisallowedScope.h"
 #include <wtf/IsoMallocInlines.h>
@@ -180,8 +181,10 @@
     ASSERT(static_cast<const Element&>(invalidFormControlElement).matchesInvalidPseudoClass());
     ASSERT_WITH_MESSAGE(!m_invalidDescendants.contains(invalidFormControlElement), "Updating the fieldset on validity change is not an efficient operation, it should only be done when necessary.");
 
+    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidDescendants.computesEmpty())
-        invalidateStyleForSubtree();
+        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+
     m_invalidDescendants.add(invalidFormControlElement);
 }
 
@@ -190,9 +193,11 @@
     ASSERT_WITH_MESSAGE(!is<HTMLFieldSetElement>(formControlElement), "FieldSet are never candidates for constraint validation.");
     ASSERT_WITH_MESSAGE(m_invalidDescendants.contains(formControlElement), "Updating the fieldset on validity change is not an efficient operation, it should only be done when necessary.");
 
+    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
+    if (m_invalidDescendants.computeSize() == 1)
+        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+
     m_invalidDescendants.remove(formControlElement);
-    if (m_invalidDescendants.computesEmpty())
-        invalidateStyleForSubtree();
 }
 
 } // namespace

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (287550 => 287551)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-01-03 18:49:55 UTC (rev 287551)
@@ -405,7 +405,6 @@
     m_willValidate = newWillValidate;
 
     updateValidity();
-    invalidateStyleForSubtree();
 
     if (!m_willValidate && !wasValid) {
         removeInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
@@ -503,9 +502,6 @@
 
 inline bool HTMLFormControlElement::isValidFormControlElement() const
 {
-    // If the following assertion fails, updateValidity() is not called
-    // correctly when something which changes validity is updated.
-    ASSERT(m_isValid == isValid());
     return m_isValid;
 }
 
@@ -533,28 +529,29 @@
         return;
 
     bool willValidate = this->willValidate();
-    bool wasValid = m_isValid;
+    bool newIsValid = this->computeValidity();
 
-    m_isValid = isValid();
+    if (newIsValid != m_isValid) {
+        Style::PseudoClassChangeInvalidation styleInvalidation(*this, { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
 
-    if (willValidate && m_isValid != wasValid) {
-        // Update style for pseudo classes such as :valid :invalid.
-        invalidateStyleForSubtree();
+        m_isValid = newIsValid;
 
-        if (!m_isValid) {
-            if (isConnected())
-                addInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
-            if (HTMLFormElement* form = this->form())
-                form->registerInvalidAssociatedFormControl(*this);
-        } else {
-            if (isConnected())
-                removeInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
-            if (HTMLFormElement* form = this->form())
-                form->removeInvalidAssociatedFormControlIfNeeded(*this);
+        if (willValidate) {
+            if (!m_isValid) {
+                if (isConnected())
+                    addInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
+                if (HTMLFormElement* form = this->form())
+                    form->registerInvalidAssociatedFormControl(*this);
+            } else {
+                if (isConnected())
+                    removeInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
+                if (HTMLFormElement* form = this->form())
+                    form->removeInvalidAssociatedFormControlIfNeeded(*this);
+            }
         }
     }
 
-    // Updates only if this control already has a validtion message.
+    // Updates only if this control already has a validation message.
     if (m_validationMessage && m_validationMessage->isVisible()) {
         // Calls updateVisibleValidationMessage() even if m_isValid is not
         // changed because a validation message can be chagned.

Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (287550 => 287551)


--- trunk/Source/WebCore/html/HTMLFormElement.cpp	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp	2022-01-03 18:49:55 UTC (rev 287551)
@@ -666,17 +666,23 @@
     ASSERT_WITH_MESSAGE(!is<HTMLFieldSetElement>(formControlElement), "FieldSet are never candidates for constraint validation.");
     ASSERT(static_cast<const Element&>(formControlElement).matchesInvalidPseudoClass());
 
+    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     if (m_invalidAssociatedFormControls.computesEmpty())
-        invalidateStyleForSubtree();
+        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+
     m_invalidAssociatedFormControls.add(const_cast<HTMLFormControlElement&>(formControlElement));
 }
 
 void HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded(const HTMLFormControlElement& formControlElement)
 {
-    if (m_invalidAssociatedFormControls.remove(formControlElement)) {
-        if (m_invalidAssociatedFormControls.computesEmpty())
-            invalidateStyleForSubtree();
-    }
+    if (!m_invalidAssociatedFormControls.contains(formControlElement))
+        return;
+
+    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
+    if (m_invalidAssociatedFormControls.computeSize() == 1)
+        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
+
+    m_invalidAssociatedFormControls.remove(formControlElement);
 }
 
 bool HTMLFormElement::isURLAttribute(const Attribute& attribute) const

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (287550 => 287551)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-01-03 18:49:55 UTC (rev 287551)
@@ -391,7 +391,7 @@
     return m_inputType->stepMismatch(value());
 }
 
-bool HTMLInputElement::isValid() const
+bool HTMLInputElement::computeValidity() const
 {
     String value = this->value();
     bool someError = m_inputType->isInvalid(value) || tooShort(value, CheckDirtyFlag) || tooLong(value, CheckDirtyFlag) || customError();

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (287550 => 287551)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2022-01-03 18:49:55 UTC (rev 287551)
@@ -73,7 +73,7 @@
     bool tooLong() const final;
     bool typeMismatch() const final;
     bool valueMissing() const final;
-    bool isValid() const final;
+    bool computeValidity() const final;
     WEBCORE_EXPORT String validationMessage() const final;
 
     // Returns the minimum value for type=date, number, or range.  Don't call this for other types.

Modified: trunk/Source/WebCore/html/ValidityState.idl (287550 => 287551)


--- trunk/Source/WebCore/html/ValidityState.idl	2022-01-03 18:49:23 UTC (rev 287550)
+++ trunk/Source/WebCore/html/ValidityState.idl	2022-01-03 18:49:55 UTC (rev 287551)
@@ -34,5 +34,5 @@
     readonly attribute boolean         stepMismatch;
     readonly attribute boolean         badInput;
     readonly attribute boolean         customError;
-    [ImplementedAs=isValid] readonly attribute boolean         valid;
+    [ImplementedAs=computeValidity] readonly attribute boolean         valid;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to