Changeset 287551 in webkit


Ignore:
Timestamp:
Jan 3, 2022 10:49:55 AM (7 months ago)
Author:
Antti Koivisto
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:
Location:
trunk
Files:
10 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r287550 r287551  
     12022-01-03  Antti Koivisto  <antti@apple.com>
     2
     3        [:has() pseudo-class] Style invalidation for :valid and :invalid
     4        https://bugs.webkit.org/show_bug.cgi?id=234815
     5
     6        Reviewed by Sam Weinig.
     7
     8        * 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.
     9        * 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.
     10
    1112022-01-03  Antoine Quint  <graouts@webkit.org>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class-expected.txt

    r287550 r287551  
    3030PASS Set disabled on optgroup, testing subject4
    3131PASS Unset disabled on optgroup, testing subject4
     32PASS Before setting value of text_input, testing subject
     33PASS Set value of text_input, testing subject
     34PASS Clear value of text_input, testing subject
     35PASS Before setting value of text_input, testing subject2
     36PASS Set value of text_input, testing subject2
     37PASS Clear value of text_input, testing subject2
     38PASS Before setting value of text_input, testing subject3
     39PASS Set value of text_input, testing subject3
     40PASS Clear value of text_input, testing subject3
     41PASS Before setting value of text_input, testing subject4
     42PASS Set value of text_input, testing subject4
     43PASS Clear value of text_input, testing subject4
    3244
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html

    r287550 r287551  
    1616main:not(:has(#option:enabled)) :is(#subject3, #subject4) { color: green }
    1717main:not(:has(#optgroup:enabled)) > #subject3 { color: blue }
     18main:has(#text_input:valid) > #subject { color: yellow }
     19main:not(:has(#text_input:invalid)) > #subject2 { color: yellow }
     20main:has(#form:valid) > #subject3 { color: yellow }
     21main:not(:has(#form:invalid)) > #subject4 { color: yellow }
    1822</style>
    1923
    2024<main id=main>
    21     <input type=checkbox id=checkbox></input>
    22     <select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
     25    <form id=form>
     26        <input type=checkbox id=checkbox></input>
     27        <select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
     28        <input id=text_input type=text required></input>
     29    </form>
    2330    <div id=subject></div>
    2431    <div id=subject2></div>
     
    6269}
    6370
     71function testValueChange(input, subject_element, expectedColor)
     72{
     73    testColor(`Before setting value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
     74
     75    input.value = "value";
     76    testColor(`Set value of ${input.id}, testing ${subject_element.id}`, subject_element, expectedColor);
     77
     78    input.value = "";
     79    testColor(`Clear value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
     80}
     81
    6482testPseudoClassChange(checkbox, "checked", subject, red);
    6583testSelectedChange(option, subject, red);
     
    7593testPseudoClassChange(optgroup, "disabled", subject4, green);
    7694
     95testValueChange(text_input, subject, yellow);
     96testValueChange(text_input, subject2, yellow);
     97testValueChange(text_input, subject3, yellow);
     98testValueChange(text_input, subject4, yellow);
    7799</script>
  • trunk/Source/WebCore/ChangeLog

    r287550 r287551  
     12022-01-03  Antti Koivisto  <antti@apple.com>
     2
     3        [:has() pseudo-class] Style invalidation for :valid and :invalid
     4        https://bugs.webkit.org/show_bug.cgi?id=234815
     5
     6        Reviewed by Sam Weinig.
     7
     8        Use PseudoClassChangeInvalidation for accurate and :has() supporting style invalidation.
     9
     10        Test: imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-pseudo-class.html
     11
     12        * html/FormAssociatedElement.cpp:
     13        (WebCore::FormAssociatedElement::computeValidity const):
     14        (WebCore::FormAssociatedElement::isValid const): Deleted.
     15        * html/FormAssociatedElement.h:
     16        * html/HTMLFieldSetElement.cpp:
     17        (WebCore::HTMLFieldSetElement::addInvalidDescendant):
     18        (WebCore::HTMLFieldSetElement::removeInvalidDescendant):
     19        * html/HTMLFormControlElement.cpp:
     20        (WebCore::HTMLFormControlElement::updateWillValidateAndValidity):
     21        (WebCore::HTMLFormControlElement::isValidFormControlElement const):
     22        (WebCore::HTMLFormControlElement::updateValidity):
     23        * html/HTMLFormElement.cpp:
     24        (WebCore::HTMLFormElement::registerInvalidAssociatedFormControl):
     25        (WebCore::HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded):
     26        * html/HTMLInputElement.cpp:
     27        (WebCore::HTMLInputElement::computeValidity const):
     28        (WebCore::HTMLInputElement::isValid const): Deleted.
     29        * html/HTMLInputElement.h:
     30        * html/ValidityState.idl:
     31
    1322022-01-03  Antoine Quint  <graouts@webkit.org>
    233
  • trunk/Source/WebCore/html/FormAssociatedElement.cpp

    r286321 r287551  
    254254}
    255255
    256 bool FormAssociatedElement::isValid() const
     256bool FormAssociatedElement::computeValidity() const
    257257{
    258258    bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
  • trunk/Source/WebCore/html/FormAssociatedElement.h

    r286447 r287551  
    8686    virtual bool valueMissing() const;
    8787    virtual String validationMessage() const;
    88     virtual bool isValid() const;
     88    virtual bool computeValidity() const;
    8989    virtual void setCustomValidity(const String&);
    9090
  • trunk/Source/WebCore/html/HTMLFieldSetElement.cpp

    r278919 r287551  
    3333#include "HTMLObjectElement.h"
    3434#include "NodeRareData.h"
     35#include "PseudoClassChangeInvalidation.h"
    3536#include "RenderElement.h"
    3637#include "ScriptDisallowedScope.h"
     
    181182    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.");
    182183
     184    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
    183185    if (m_invalidDescendants.computesEmpty())
    184         invalidateStyleForSubtree();
     186        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
     187
    185188    m_invalidDescendants.add(invalidFormControlElement);
    186189}
     
    191194    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.");
    192195
     196    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     197    if (m_invalidDescendants.computeSize() == 1)
     198        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
     199
    193200    m_invalidDescendants.remove(formControlElement);
    194     if (m_invalidDescendants.computesEmpty())
    195         invalidateStyleForSubtree();
    196201}
    197202
  • trunk/Source/WebCore/html/HTMLFormControlElement.cpp

    r287540 r287551  
    406406
    407407    updateValidity();
    408     invalidateStyleForSubtree();
    409408
    410409    if (!m_willValidate && !wasValid) {
     
    504503inline bool HTMLFormControlElement::isValidFormControlElement() const
    505504{
    506     // If the following assertion fails, updateValidity() is not called
    507     // correctly when something which changes validity is updated.
    508     ASSERT(m_isValid == isValid());
    509505    return m_isValid;
    510506}
     
    534530
    535531    bool willValidate = this->willValidate();
    536     bool wasValid = m_isValid;
    537 
    538     m_isValid = isValid();
    539 
    540     if (willValidate && m_isValid != wasValid) {
    541         // Update style for pseudo classes such as :valid :invalid.
    542         invalidateStyleForSubtree();
    543 
    544         if (!m_isValid) {
    545             if (isConnected())
    546                 addInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
    547             if (HTMLFormElement* form = this->form())
    548                 form->registerInvalidAssociatedFormControl(*this);
    549         } else {
    550             if (isConnected())
    551                 removeInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
    552             if (HTMLFormElement* form = this->form())
    553                 form->removeInvalidAssociatedFormControlIfNeeded(*this);
     532    bool newIsValid = this->computeValidity();
     533
     534    if (newIsValid != m_isValid) {
     535        Style::PseudoClassChangeInvalidation styleInvalidation(*this, { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
     536
     537        m_isValid = newIsValid;
     538
     539        if (willValidate) {
     540            if (!m_isValid) {
     541                if (isConnected())
     542                    addInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
     543                if (HTMLFormElement* form = this->form())
     544                    form->registerInvalidAssociatedFormControl(*this);
     545            } else {
     546                if (isConnected())
     547                    removeInvalidElementToAncestorFromInsertionPoint(*this, parentNode());
     548                if (HTMLFormElement* form = this->form())
     549                    form->removeInvalidAssociatedFormControlIfNeeded(*this);
     550            }
    554551        }
    555552    }
    556553
    557     // Updates only if this control already has a validtion message.
     554    // Updates only if this control already has a validation message.
    558555    if (m_validationMessage && m_validationMessage->isVisible()) {
    559556        // Calls updateVisibleValidationMessage() even if m_isValid is not
  • trunk/Source/WebCore/html/HTMLFormElement.cpp

    r286447 r287551  
    667667    ASSERT(static_cast<const Element&>(formControlElement).matchesInvalidPseudoClass());
    668668
     669    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
    669670    if (m_invalidAssociatedFormControls.computesEmpty())
    670         invalidateStyleForSubtree();
     671        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
     672
    671673    m_invalidAssociatedFormControls.add(const_cast<HTMLFormControlElement&>(formControlElement));
    672674}
     
    674676void HTMLFormElement::removeInvalidAssociatedFormControlIfNeeded(const HTMLFormControlElement& formControlElement)
    675677{
    676     if (m_invalidAssociatedFormControls.remove(formControlElement)) {
    677         if (m_invalidAssociatedFormControls.computesEmpty())
    678             invalidateStyleForSubtree();
    679     }
     678    if (!m_invalidAssociatedFormControls.contains(formControlElement))
     679        return;
     680
     681    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
     682    if (m_invalidAssociatedFormControls.computeSize() == 1)
     683        styleInvalidation.emplace(*this, std::initializer_list<CSSSelector::PseudoClassType> { CSSSelector::PseudoClassValid, CSSSelector::PseudoClassInvalid });
     684
     685    m_invalidAssociatedFormControls.remove(formControlElement);
    680686}
    681687
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r287363 r287551  
    392392}
    393393
    394 bool HTMLInputElement::isValid() const
     394bool HTMLInputElement::computeValidity() const
    395395{
    396396    String value = this->value();
  • trunk/Source/WebCore/html/HTMLInputElement.h

    r286560 r287551  
    7474    bool typeMismatch() const final;
    7575    bool valueMissing() const final;
    76     bool isValid() const final;
     76    bool computeValidity() const final;
    7777    WEBCORE_EXPORT String validationMessage() const final;
    7878
  • trunk/Source/WebCore/html/ValidityState.idl

    r267813 r287551  
    3535    readonly attribute boolean         badInput;
    3636    readonly attribute boolean         customError;
    37     [ImplementedAs=isValid] readonly attribute boolean         valid;
     37    [ImplementedAs=computeValidity] readonly attribute boolean         valid;
    3838};
Note: See TracChangeset for help on using the changeset viewer.