Title: [292466] trunk
Revision
292466
Author
n...@apple.com
Date
2022-04-06 08:07:06 -0700 (Wed, 06 Apr 2022)

Log Message

[:has() pseudo-class] Support invalidation for more input pseudo classes
https://bugs.webkit.org/show_bug.cgi?id=238451

Reviewed by Antti Koivisto.

- :indeterminate
- :read-only
- :read-write
- :required
- :optional

LayoutTests/imported/w3c:

Split the test in multiple subtests.

* web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has-expected.txt:
* web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has.html:

Source/WebCore:

* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::parseAttribute):
(WebCore::HTMLFormControlElement::readOnlyStateChanged):
(WebCore::HTMLFormControlElement::requiredStateChanged):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setIndeterminate):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (292465 => 292466)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-04-06 15:07:06 UTC (rev 292466)
@@ -1,3 +1,21 @@
+2022-04-06  Tim Nguyen  <n...@apple.com>
+
+        [:has() pseudo-class] Support invalidation for more input pseudo classes
+        https://bugs.webkit.org/show_bug.cgi?id=238451
+
+        Reviewed by Antti Koivisto.
+
+        - :indeterminate
+        - :read-only
+        - :read-write
+        - :required
+        - :optional
+
+        Split the test in multiple subtests.
+
+        * web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has-expected.txt:
+        * web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has.html:
+
 2022-04-06  Youenn Fablet  <you...@apple.com>
 
         Implement ServiceWorkerWindowClient.navigate

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has-expected.txt (292465 => 292466)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has-expected.txt	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has-expected.txt	2022-04-06 15:07:06 UTC (rev 292466)
@@ -1,4 +1,11 @@
  Check me!
 
-FAIL CSS Selectors Invalidation: input pseudo classes in :has() argument assert_equals: ancestor should be yellowgreen expected "rgb(154, 205, 50)" but got "rgb(0, 128, 0)"
+PASS :checked & :indeterminate invalidation
+PASS :disabled invalidation
+PASS :read-only invalidation
+PASS :valid invalidation
+FAIL :default invalidation with input[type=radio] assert_equals: ancestor should be lightblue expected "rgb(173, 216, 230)" but got "rgb(0, 0, 0)"
+PASS :required invalidation
+FAIL :out-of-range invalidation assert_equals: ancestor should be darkgreen expected "rgb(0, 100, 0)" but got "rgb(0, 0, 0)"
+FAIL :placeholder-shown invalidation assert_equals: ancestor should be navy expected "rgb(0, 0, 128)" but got "rgb(0, 0, 0)"
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has.html (292465 => 292466)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has.html	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/input-pseudo-classes-in-has.html	2022-04-06 15:07:06 UTC (rev 292466)
@@ -5,9 +5,6 @@
 <link rel="help" href=""
 <script src=""
 <script src=""
-<script src=""
-<script src=""
-<script src=""
 <style>
   .ancestor:has(#checkme:checked) { color: green }
   .ancestor:has(#checkme:indeterminate) { color: yellowgreen }
@@ -27,7 +24,10 @@
   <input id="numberinput" type="number" min="1" max="10" value="5">
 </div>
 <script>
-  test(() => {
+  test(function() {
+    this.add_cleanup(() => {
+      checkme.checked = false;
+    });
     checkme.checked = false;
     assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
                   "ancestor should be black");
@@ -37,51 +37,92 @@
     checkme.indeterminate = true;
     assert_equals(getComputedStyle(subject).color, "rgb(154, 205, 50)",
                   "ancestor should be yellowgreen");
+    const input = checkme;
     checkme.remove();
+    input.indeterminate = false;
     assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
                   "ancestor should be black");
 
-    {
-      const input = document.createElement('input');
-      input.id = 'checkme';
-      input.setAttribute('type', 'checkbox');
-      input.setAttribute('name', 'my-checkbox');
-      input.checked = true;
-      assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
-                    "ancestor should be black");
-      subject.prepend(input);
-      assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
-                    "ancestor should be green");
-    }
+    subject.prepend(input);
+    checkme.checked = true;
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+                  "ancestor should be green");
+  }, ":checked & :indeterminate invalidation");
 
+  test(function() {
+    this.add_cleanup(() => {
+      checkme.disabled = false;
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
     checkme.disabled = true;
     assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)",
                   "ancestor should be blue");
+  }, ":disabled invalidation");
 
+  test(function() {
+    this.add_cleanup(() => {
+      textinput.readOnly = false;
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
     textinput.readOnly = true;
     assert_equals(getComputedStyle(subject).color, "rgb(135, 206, 235)",
                   "ancestor should be skyblue");
-    textinput.readOnly = false;
+  }, ":read-only invalidation");
 
-    textinput.placeholder = 'placeholder text';
-    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 128)",
-                  "ancestor should be navy");
+  test(function() {
+    this.add_cleanup(() => {
+      textinput.value = "";
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
+    textinput.value = "text input";
+    assert_equals(getComputedStyle(subject).color, "rgb(144, 238, 144)",
+                  "ancestor should be lightgreen");
+  }, ":valid invalidation");
 
+  test(function() {
+    this.add_cleanup(() => {
+      radioinput.removeAttribute("type");
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
     radioinput.type = 'radio';
     assert_equals(getComputedStyle(subject).color, "rgb(173, 216, 230)",
                   "ancestor should be lightblue");
+  }, ":default invalidation with input[type=radio]");
 
-    textinput.value = "text input";
-    assert_equals(getComputedStyle(subject).color, "rgb(144, 238, 144)",
-                  "ancestor should be lightgreen");
+  test(function() {
+    this.add_cleanup(() => {
+      numberinput.required = false;
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
+    numberinput.required = true;
+    assert_equals(getComputedStyle(subject).color, "rgb(255, 192, 203)",
+                  "ancestor should be pink");
+  }, ":required invalidation");
 
+  test(function() {
+    this.add_cleanup(() => {
+      numberinput.value = 5;
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
     numberinput.value = 12;
     assert_equals(getComputedStyle(subject).color, "rgb(0, 100, 0)",
                   "ancestor should be darkgreen");
+  }, ":out-of-range invalidation");
 
-    numberinput.required = true;
-    assert_equals(getComputedStyle(subject).color, "rgb(255, 192, 203)",
-                  "ancestor should be pink");
-
-  });
-</script>
\ No newline at end of file
+  test(function() {
+    this.add_cleanup(() => {
+      textinput.removeAttribute("placeholder");
+    });
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+                  "ancestor should be black");
+    textinput.placeholder = 'placeholder text';
+    assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 128)",
+                  "ancestor should be navy");
+  }, ":placeholder-shown invalidation");
+</script>

Modified: trunk/Source/WebCore/ChangeLog (292465 => 292466)


--- trunk/Source/WebCore/ChangeLog	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/Source/WebCore/ChangeLog	2022-04-06 15:07:06 UTC (rev 292466)
@@ -1,3 +1,23 @@
+2022-04-06  Tim Nguyen  <n...@apple.com>
+
+        [:has() pseudo-class] Support invalidation for more input pseudo classes
+        https://bugs.webkit.org/show_bug.cgi?id=238451
+
+        Reviewed by Antti Koivisto.
+
+        - :indeterminate
+        - :read-only
+        - :read-write
+        - :required
+        - :optional
+
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::parseAttribute):
+        (WebCore::HTMLFormControlElement::readOnlyStateChanged):
+        (WebCore::HTMLFormControlElement::requiredStateChanged):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setIndeterminate):
+
 2022-04-06  Alan Bujtas  <za...@apple.com>
 
         [CSS-Contain] Grid layout should take "contain: inline-size" into account when computing the grid item's logical width

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (292465 => 292466)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2022-04-06 15:07:06 UTC (rev 292466)
@@ -167,15 +167,19 @@
             }
         }
     } else if (name == readonlyAttr) {
-        bool wasReadOnly = m_isReadOnly;
-        m_isReadOnly = !value.isNull();
-        if (wasReadOnly != m_isReadOnly)
+        bool newReadOnly = !value.isNull();
+        if (m_isReadOnly != newReadOnly) {
+            Style::PseudoClassChangeInvalidation readOnlyInvalidation(*this, { { CSSSelector::PseudoClassReadOnly, newReadOnly }, { CSSSelector::PseudoClassReadWrite, !newReadOnly } });
+            m_isReadOnly = newReadOnly;
             readOnlyStateChanged();
+        }
     } else if (name == requiredAttr) {
-        bool wasRequired = m_isRequired;
-        m_isRequired = !value.isNull();
-        if (wasRequired != m_isRequired)
+        bool newRequired = !value.isNull();
+        if (m_isRequired != newRequired) {
+            Style::PseudoClassChangeInvalidation requiredInvalidation(*this, { { CSSSelector::PseudoClassRequired, newRequired }, { CSSSelector::PseudoClassOptional, !newRequired } });
+            m_isRequired = newRequired;
             requiredStateChanged();
+        }
     } else
         HTMLElement::parseAttribute(name, value);
 }
@@ -195,6 +199,9 @@
 void HTMLFormControlElement::readOnlyStateChanged()
 {
     updateWillValidateAndValidity();
+
+    // Some input pseudo classes like :in-range/out-of-range change based on the readonly state.
+    // FIXME: Use PseudoClassChangeInvalidation instead for :has() support and more efficiency.
     invalidateStyleForSubtree();
 }
 
@@ -201,9 +208,6 @@
 void HTMLFormControlElement::requiredStateChanged()
 {
     updateValidity();
-    // Style recalculation is needed because style selectors may include
-    // :required and :optional pseudo-classes.
-    invalidateStyleForSubtree();
 }
 
 void HTMLFormControlElement::didAttachRenderers()

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (292465 => 292466)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-04-06 15:02:01 UTC (rev 292465)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2022-04-06 15:07:06 UTC (rev 292466)
@@ -992,10 +992,9 @@
     if (indeterminate() == newValue)
         return;
 
+    Style::PseudoClassChangeInvalidation indeterminateInvalidation(*this, CSSSelector::PseudoClassIndeterminate, newValue);
     m_isIndeterminate = newValue;
 
-    invalidateStyleForSubtree();
-
     if (renderer() && renderer()->style().hasEffectiveAppearance())
         renderer()->theme().stateChanged(*renderer(), ControlStates::States::Checked);
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to