Title: [291990] trunk
Revision
291990
Author
z...@igalia.com
Date
2022-03-28 14:11:37 -0700 (Mon, 28 Mar 2022)

Log Message

[selection] Fire Select event when selection extent or direction changes
https://bugs.webkit.org/show_bug.cgi?id=238142

Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

Update test expectations as more sub-tests are now passing.
* web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end-expected.txt:
* web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText-expected.txt:
* web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt:

Source/WebCore:

As per step 6 at [1], if either extent or direction of the text control to be modified,
we need to queue an element task on the user interaction task source given the element
to fire an select event with the bubbles attribute initialized to true.

[1] https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#set-the-selection-range

* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::setSelectionRange):
(WebCore::HTMLTextFormControlElement::cacheSelection):
(WebCore::HTMLTextFormControlElement::restoreCachedSelection):
(WebCore::HTMLTextFormControlElement::scheduleSelectEvent):
* html/HTMLTextFormControlElement.h:
(WebCore::HTMLTextFormControlElement::cacheSelection): Deleted.

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (291989 => 291990)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-03-28 21:11:37 UTC (rev 291990)
@@ -1,3 +1,15 @@
+2022-03-28  Ziran Sun  <z...@igalia.com>
+
+        [selection] Fire Select event when selection extent or direction changes
+        https://bugs.webkit.org/show_bug.cgi?id=238142
+
+        Reviewed by Chris Dumez.
+
+        Update test expectations as more sub-tests are now passing.
+        * web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end-expected.txt:
+        * web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText-expected.txt:
+        * web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt:
+
 2022-03-27  Matt Woodrow  <mattwood...@apple.com>
 
         Preserve repeat() notation for grid-templates

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end-expected.txt (291989 => 291990)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end-expected.txt	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/selection-start-end-expected.txt	2022-03-28 21:11:37 UTC (rev 291990)
@@ -1,6 +1,4 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS Sanity check for testValue length; if this fails, variou absolute offsets in the test below need to be adjusted to be less than testValue.length
 PASS Initial .value set on input-appended should set selectionStart to end of value
 PASS Initial .value set on input-not-appended should set selectionStart to end of value
@@ -19,25 +17,25 @@
 PASS Initial .value set on textarea-appended-prefocused should set selectionEnd to end of value
 PASS Initial .value set on textarea-not-appended-prefocused should set selectionEnd to end of value
 PASS onselect should fire when selectionStart is changed
-NOTRUN onselect should fire when selectionStart is changed on input-appended
-NOTRUN onselect should fire when selectionStart is changed on input-not-appended
-NOTRUN onselect should fire when selectionStart is changed on input-appended-prefocused
-NOTRUN onselect should fire when selectionStart is changed on input-not-appended-prefocused
-NOTRUN onselect should fire when selectionStart is changed on textarea-appended
-NOTRUN onselect should fire when selectionStart is changed on textarea-not-appended
-NOTRUN onselect should fire when selectionStart is changed on textarea-appended-prefocused
-NOTRUN onselect should fire when selectionStart is changed on textarea-not-appended-prefocused
-NOTRUN onselect should fire when selectionStart is changed on
+PASS onselect should fire when selectionStart is changed on input-appended
+PASS onselect should fire when selectionStart is changed on input-not-appended
+PASS onselect should fire when selectionStart is changed on input-appended-prefocused
+PASS onselect should fire when selectionStart is changed on input-not-appended-prefocused
+PASS onselect should fire when selectionStart is changed on textarea-appended
+PASS onselect should fire when selectionStart is changed on textarea-not-appended
+PASS onselect should fire when selectionStart is changed on textarea-appended-prefocused
+PASS onselect should fire when selectionStart is changed on textarea-not-appended-prefocused
+PASS onselect should fire when selectionStart is changed on
 PASS onselect should fire when selectionEnd is changed
-NOTRUN onselect should fire when selectionEnd is changed on input-appended
-NOTRUN onselect should fire when selectionEnd is changed on input-not-appended
-NOTRUN onselect should fire when selectionEnd is changed on input-appended-prefocused
-NOTRUN onselect should fire when selectionEnd is changed on input-not-appended-prefocused
-NOTRUN onselect should fire when selectionEnd is changed on textarea-appended
-NOTRUN onselect should fire when selectionEnd is changed on textarea-not-appended
-NOTRUN onselect should fire when selectionEnd is changed on textarea-appended-prefocused
-NOTRUN onselect should fire when selectionEnd is changed on textarea-not-appended-prefocused
-NOTRUN onselect should fire when selectionEnd is changed on
+PASS onselect should fire when selectionEnd is changed on input-appended
+PASS onselect should fire when selectionEnd is changed on input-not-appended
+PASS onselect should fire when selectionEnd is changed on input-appended-prefocused
+PASS onselect should fire when selectionEnd is changed on input-not-appended-prefocused
+PASS onselect should fire when selectionEnd is changed on textarea-appended
+PASS onselect should fire when selectionEnd is changed on textarea-not-appended
+PASS onselect should fire when selectionEnd is changed on textarea-appended-prefocused
+PASS onselect should fire when selectionEnd is changed on textarea-not-appended-prefocused
+PASS onselect should fire when selectionEnd is changed on
 PASS Setting selectionStart to a value larger than selectionEnd should increase selectionEnd
 PASS Setting selectionEnd to a value smaller than selectionStart should decrease selectionStart
 PASS selectionStart edge-case values

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText-expected.txt (291989 => 291990)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText-expected.txt	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText-expected.txt	2022-03-28 21:11:37 UTC (rev 291990)
@@ -1,6 +1,4 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS text setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS text selectionMode missing
 PASS text selectionMode 'select'
@@ -10,8 +8,8 @@
 PASS text setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS text setRangeText without argument throws a type error
 PASS text setRangeText fires a select event
-TIMEOUT text setRangeText fires a select event when fully selected Test timed out
-NOTRUN text setRangeText fires a select event after select()
+PASS text setRangeText fires a select event when fully selected
+PASS text setRangeText fires a select event after select()
 PASS search setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS search selectionMode missing
 PASS search selectionMode 'select'
@@ -20,9 +18,9 @@
 PASS search selectionMode 'preserve'
 PASS search setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS search setRangeText without argument throws a type error
-NOTRUN search setRangeText fires a select event
-NOTRUN search setRangeText fires a select event when fully selected
-NOTRUN search setRangeText fires a select event after select()
+PASS search setRangeText fires a select event
+PASS search setRangeText fires a select event when fully selected
+PASS search setRangeText fires a select event after select()
 PASS tel setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS tel selectionMode missing
 PASS tel selectionMode 'select'
@@ -31,9 +29,9 @@
 PASS tel selectionMode 'preserve'
 PASS tel setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS tel setRangeText without argument throws a type error
-NOTRUN tel setRangeText fires a select event
-NOTRUN tel setRangeText fires a select event when fully selected
-NOTRUN tel setRangeText fires a select event after select()
+PASS tel setRangeText fires a select event
+PASS tel setRangeText fires a select event when fully selected
+PASS tel setRangeText fires a select event after select()
 PASS url setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS url selectionMode missing
 PASS url selectionMode 'select'
@@ -42,9 +40,9 @@
 PASS url selectionMode 'preserve'
 PASS url setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS url setRangeText without argument throws a type error
-NOTRUN url setRangeText fires a select event
-NOTRUN url setRangeText fires a select event when fully selected
-NOTRUN url setRangeText fires a select event after select()
+PASS url setRangeText fires a select event
+PASS url setRangeText fires a select event when fully selected
+PASS url setRangeText fires a select event after select()
 PASS password setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS password selectionMode missing
 PASS password selectionMode 'select'
@@ -53,9 +51,9 @@
 PASS password selectionMode 'preserve'
 PASS password setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS password setRangeText without argument throws a type error
-NOTRUN password setRangeText fires a select event
-NOTRUN password setRangeText fires a select event when fully selected
-NOTRUN password setRangeText fires a select event after select()
+PASS password setRangeText fires a select event
+PASS password setRangeText fires a select event when fully selected
+PASS password setRangeText fires a select event after select()
 PASS display_none setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS display_none selectionMode missing
 PASS display_none selectionMode 'select'
@@ -64,9 +62,9 @@
 PASS display_none selectionMode 'preserve'
 PASS display_none setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS display_none setRangeText without argument throws a type error
-NOTRUN display_none setRangeText fires a select event
-NOTRUN display_none setRangeText fires a select event when fully selected
-NOTRUN display_none setRangeText fires a select event after select()
+PASS display_none setRangeText fires a select event
+PASS display_none setRangeText fires a select event when fully selected
+PASS display_none setRangeText fires a select event after select()
 PASS textarea setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS textarea selectionMode missing
 PASS textarea selectionMode 'select'
@@ -75,9 +73,9 @@
 PASS textarea selectionMode 'preserve'
 PASS textarea setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS textarea setRangeText without argument throws a type error
-NOTRUN textarea setRangeText fires a select event
-NOTRUN textarea setRangeText fires a select event when fully selected
-NOTRUN textarea setRangeText fires a select event after select()
+PASS textarea setRangeText fires a select event
+PASS textarea setRangeText fires a select event when fully selected
+PASS textarea setRangeText fires a select event after select()
 PASS input_not_in_doc setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments
 PASS input_not_in_doc selectionMode missing
 PASS input_not_in_doc selectionMode 'select'
@@ -86,7 +84,7 @@
 PASS input_not_in_doc selectionMode 'preserve'
 PASS input_not_in_doc setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception
 PASS input_not_in_doc setRangeText without argument throws a type error
-NOTRUN input_not_in_doc setRangeText fires a select event
-NOTRUN input_not_in_doc setRangeText fires a select event when fully selected
-NOTRUN input_not_in_doc setRangeText fires a select event after select()
+PASS input_not_in_doc setRangeText fires a select event
+PASS input_not_in_doc setRangeText fires a select event when fully selected
+PASS input_not_in_doc setRangeText fires a select event after select()
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt (291989 => 291990)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt	2022-03-28 21:11:37 UTC (rev 291990)
@@ -1,6 +1,4 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS test of input.setSelectionRange
 PASS input typeof(input.setSelectionRange)'
 PASS input setSelectionRange return void
@@ -27,7 +25,7 @@
 PASS input setSelectionRange(undefined,1)
 PASS input setSelectionRange(Math.pow(2,32) - 2, Math.pow(2,32) - 1)
 PASS input setSelectionRange(Math.pow(2,31), Math.pow(2,32) - 1)
-TIMEOUT input setSelectionRange fires a select event Test timed out
+PASS input setSelectionRange fires a select event
 PASS test of textarea.setSelectionRange
 PASS textarea typeof(input.setSelectionRange)'
 PASS textarea setSelectionRange return void

Modified: trunk/Source/WebCore/ChangeLog (291989 => 291990)


--- trunk/Source/WebCore/ChangeLog	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/Source/WebCore/ChangeLog	2022-03-28 21:11:37 UTC (rev 291990)
@@ -1,3 +1,25 @@
+2022-03-28  Ziran Sun  <z...@igalia.com>
+
+        [selection] Fire Select event when selection extent or direction changes
+        https://bugs.webkit.org/show_bug.cgi?id=238142
+
+        Reviewed by Chris Dumez.
+
+        As per step 6 at [1], if either extent or direction of the text control to be modified,
+        we need to queue an element task on the user interaction task source given the element
+        to fire an select event with the bubbles attribute initialized to true.
+        
+        [1] https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#set-the-selection-range
+
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::setSelectionRange):
+        (WebCore::HTMLTextFormControlElement::cacheSelection):
+        (WebCore::HTMLTextFormControlElement::restoreCachedSelection):
+        (WebCore::HTMLTextFormControlElement::scheduleSelectEvent):
+        * html/HTMLTextFormControlElement.h:
+        (WebCore::HTMLTextFormControlElement::cacheSelection): Deleted.
+
+
 2022-03-28  Kimmo Kinnunen  <kkinnu...@apple.com>
 
         Accessing WebGL content crashes in macOS Recovery OS, workaround 2

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp (291989 => 291990)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2022-03-28 21:11:37 UTC (rev 291990)
@@ -33,6 +33,7 @@
 #include "Editor.h"
 #include "ElementAncestorIterator.h"
 #include "Event.h"
+#include "EventLoop.h"
 #include "EventNames.h"
 #include "Frame.h"
 #include "FrameSelection.h"
@@ -292,13 +293,14 @@
     else if (directionString == "backward")
         direction = SelectionHasBackwardDirection;
 
-    return setSelectionRange(start, end, direction, SelectionRevealMode::DoNotReveal, intent);
+    if (setSelectionRange(start, end, direction, SelectionRevealMode::DoNotReveal, intent))
+        scheduleSelectEvent();
 }
 
-void HTMLTextFormControlElement::setSelectionRange(unsigned start, unsigned end, TextFieldSelectionDirection direction, SelectionRevealMode revealMode, const AXTextStateChangeIntent& intent)
+bool HTMLTextFormControlElement::setSelectionRange(unsigned start, unsigned end, TextFieldSelectionDirection direction, SelectionRevealMode revealMode, const AXTextStateChangeIntent& intent)
 {
     if (!isTextField())
-        return;
+        return false;
 
     // Clamps to the current value length.
     unsigned innerTextValueLength = innerTextValue().length();
@@ -311,10 +313,10 @@
     RefPtr frame = document().frame();
     if (direction == SelectionHasNoDirection && frame && frame->editor().behavior().shouldConsiderSelectionAsDirectional())
         direction = SelectionHasForwardDirection;
+
     if (!hasFocus && innerText) {
         if (!isConnected()) {
-            cacheSelection(start, end, direction);
-            return;
+            return cacheSelection(start, end, direction);
         }
 
         // FIXME: Removing this synchronous layout requires fixing setSelectionWithoutUpdatingAppearance not needing up-to-date style.
@@ -321,12 +323,11 @@
         document().updateLayoutIgnorePendingStylesheets();
 
         if (!isTextField())
-            return;
+            return false;
 
         // Double-check our connected state after the layout update.
         if (!isConnected()) {
-            cacheSelection(start, end, direction);
-            return;
+            return cacheSelection(start, end, direction);
         }
 
         // Double-check the state of innerTextElement after the layout.
@@ -335,12 +336,12 @@
 
         if (innerText && rendererTextControl) {
             if (rendererTextControl->style().visibility() == Visibility::Hidden || !innerText->renderBox() || !innerText->renderBox()->height()) {
-                cacheSelection(start, end, direction);
-                return;
+                return cacheSelection(start, end, direction);
             }
         }
     }
 
+    bool didChange = cacheSelection(start, end, direction);
     Position startPosition = positionForIndex(innerText.get(), start);
     Position endPosition;
     if (start == end)
@@ -355,8 +356,20 @@
 
     if (RefPtr<Frame> frame = document().frame())
         frame->selection().moveWithoutValidationTo(startPosition, endPosition, direction != SelectionHasNoDirection, !hasFocus, revealMode, intent);
+
+    return didChange;
 }
 
+bool HTMLTextFormControlElement::cacheSelection(unsigned start, unsigned end, TextFieldSelectionDirection direction)
+{
+    bool didChange = m_cachedSelectionStart != start || m_cachedSelectionEnd != end || m_cachedSelectionDirection != direction;
+    m_cachedSelectionStart = start;
+    m_cachedSelectionEnd = end;
+    m_cachedSelectionDirection = direction;
+    m_hasCachedSelection = true;
+    return didChange;
+}
+
 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& position) const
 {
     auto innerText = innerTextElement();
@@ -509,7 +522,8 @@
 
 void HTMLTextFormControlElement::restoreCachedSelection(SelectionRevealMode revealMode, const AXTextStateChangeIntent& intent)
 {
-    setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, cachedSelectionDirection(), revealMode, intent);
+    if (setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, cachedSelectionDirection(), revealMode, intent))
+        scheduleSelectEvent();
 }
 
 void HTMLTextFormControlElement::selectionChanged(bool shouldFireSelectEvent)
@@ -525,6 +539,13 @@
         dispatchEvent(Event::create(eventNames().selectEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
 }
 
+void HTMLTextFormControlElement::scheduleSelectEvent()
+{
+    document().eventLoop().queueTask(TaskSource::UserInteraction, [protectedThis = GCReachableRef { *this }] {
+        protectedThis->dispatchEvent(Event::create(eventNames().selectEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
+    });
+} 
+
 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomString& value)
 {
     if (name == placeholderAttr) {

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.h (291989 => 291990)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.h	2022-03-28 21:02:59 UTC (rev 291989)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.h	2022-03-28 21:11:37 UTC (rev 291990)
@@ -80,12 +80,13 @@
     WEBCORE_EXPORT virtual ExceptionOr<void> setRangeText(const String& replacement);
     WEBCORE_EXPORT virtual ExceptionOr<void> setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode);
     void setSelectionRange(unsigned start, unsigned end, const String& direction, const AXTextStateChangeIntent& = AXTextStateChangeIntent());
-    WEBCORE_EXPORT void setSelectionRange(unsigned start, unsigned end, TextFieldSelectionDirection = SelectionHasNoDirection, SelectionRevealMode = SelectionRevealMode::DoNotReveal, const AXTextStateChangeIntent& = AXTextStateChangeIntent());
+    WEBCORE_EXPORT bool setSelectionRange(unsigned start, unsigned end, TextFieldSelectionDirection = SelectionHasNoDirection, SelectionRevealMode = SelectionRevealMode::DoNotReveal, const AXTextStateChangeIntent& = AXTextStateChangeIntent());
 
     std::optional<SimpleRange> selection() const;
     String selectedText() const;
 
     void dispatchFormControlChangeEvent() final;
+    void scheduleSelectEvent();
 
     virtual String value() const = 0;
 
@@ -117,13 +118,7 @@
 
     void updateInnerTextElementEditability();
 
-    void cacheSelection(int start, int end, TextFieldSelectionDirection direction)
-    {
-        m_cachedSelectionStart = start;
-        m_cachedSelectionEnd = end;
-        m_cachedSelectionDirection = direction;
-        m_hasCachedSelection = true;
-    }
+    bool cacheSelection(unsigned start, unsigned end, TextFieldSelectionDirection);
 
     void restoreCachedSelection(SelectionRevealMode, const AXTextStateChangeIntent& = AXTextStateChangeIntent());
     bool hasCachedSelection() const { return m_hasCachedSelection; }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to