Title: [294610] trunk
Revision
294610
Author
brandonstew...@apple.com
Date
2022-05-20 23:09:00 -0700 (Fri, 20 May 2022)

Log Message

Release assert in Document::updateLayout() via HTMLTextAreaElement::childrenChanged
https://bugs.webkit.org/show_bug.cgi?id=224471

Reviewed by Ryosuke Niwa.

This patch is based on a set of patches made by Sergio Villar Senin
and Gabriel Nava Marino.

Executing some editing commands in a text area might force the recomputation of things
like caret or the visible selection position and extent. Under some circumstances (like
when the text area has no content and children) we might end up trying to update layout
when it is not safe as a side effect of updating the caret.

In order to fix that, we can switch to a model in which we update the selection asynchronously
in the case of having a non-user triggered change. That way we don't do it inside
a restricted layout scope.

The App Highlight restoration code had to be tuned as well (when restoring and scrolling to reveal
a Quick Note on iOS MacOS). It uses TemporarySelectionChange to select and scroll to reveal the highlight
range; the code assumed that this scrolling happens synchronously, since it reverts the selection to
the original range at the end of `AppHighlightStorage::attemptToRestoreHighlightAndScroll` when the
TemporarySelectionChange falls out of scope. That is however no longer the case. Actually no scrolling
happened after this patch because we end up only scheduling the appearance update timer before setting
the selection back to the original state with `SelectionRevealMode::DoNotReveal`. Since this only happens
when the user interacts in the Notes app, it seems sensible to consider it as a user triggered event.

Layout Tests

Moved some tests out of the text-based-repaint.js model because selection is now updated
and revealed asynchronously in the case of non-user triggered changes. The problem is that
by the time the repaint rects are queried the update has not happened yet. That's why
the tests were modified so that we wait until the repaint happens.

Same situation for other tests that do not involve repaint rects but trigger accesibility
tree updates. We must ensure that we let the notification be thrown before checking whether or
not has been emited. As it's done asynchronously we must let the main thread run before checking.

Last but not least, some of the tests are using setTimeout() instead of requestAnimationFrame()
because the results with the latter were not as reliable under stress/debug conditions.

* Source/WebCore/Modules/highlight/AppHighlightStorage.cpp:
(WebCore::AppHighlightStorage::attemptToRestoreHighlightAndScroll):
* Source/WebCore/editing/Editor.cpp:
(WebCore::TemporarySelectionChange::setSelection):
* Source/WebCore/editing/Editor.h:
* Source/WebCore/editing/FrameSelection.cpp:
(WebCore::FrameSelection::setSelection):
(WebCore::FrameSelection::updateSelectionAppearanceNow):
(WebCore::FrameSelection::absoluteCaretBounds):
(WebCore::FrameSelection::setCaretVisibility):
(WebCore::FrameSelection::selectionBounds):
(WebCore::FrameSelection::revealSelection):
(WebCore::updateSelectionByUpdatingLayoutOrStyle): Deleted.
(WebCore::FrameSelection::selectionBounds const): Deleted.
* Source/WebCore/editing/FrameSelection.h:
* Source/WebCore/page/EventHandler.cpp:
(WebCore::setSelectionIfNeeded):
* Source/WebCore/page/Page.cpp:
(WebCore::Page::doAfterUpdateRendering):
* LayoutTests/accessibility/mac/selection-boundary-userinfo.html:
* LayoutTests/accessibility/mac/selection-change-userinfo.html:
* LayoutTests/accessibility/mac/selection-value-changes-for-aria-textbox.html:
* LayoutTests/editing/selection-with-absolute-positioned-empty-content.html:
* LayoutTests/fast/forms/textarea-scrolled-endline-caret.html:
* LayoutTests/fast/repaint/selection-gap-absolute-child-expected.txt:
* LayoutTests/fast/repaint/selection-gap-absolute-child.html:
* LayoutTests/fast/repaint/selection-gap-fixed-child.html:
* LayoutTests/fast/repaint/selection-gap-flipped-absolute-child-expected.txt:
* LayoutTests/fast/repaint/selection-gap-flipped-absolute-child.html:
* LayoutTests/fast/repaint/selection-gap-transformed-absolute-child-expected.txt:
* LayoutTests/fast/repaint/selection-gap-transformed-absolute-child.html:
* LayoutTests/fast/repaint/selection-gap-transformed-fixed-child-expected.txt:
* LayoutTests/fast/repaint/selection-gap-transformed-fixed-child.html:
* LayoutTests/fast/repaint/selection-paint-invalidation-expected.txt:
* LayoutTests/fast/repaint/selection-ruby-rl-expected.txt:
* LayoutTests/fast/repaint/selection-ruby-rl.html:
* LayoutTests/fast/repaint/text-selection-overflow-hidden-expected.txt:
* LayoutTests/fast/repaint/text-selection-overflow-hidden.html:
* LayoutTests/fast/text/incorrect-deselection-across-multiple-elements.html:
* LayoutTests/platform/gtk/TestExpectations:
* LayoutTests/platform/gtk/fast/repaint/selection-ruby-rl-expected.txt: Copied from LayoutTests/fast/repaint/selection-ruby-rl-expected.txt.
* LayoutTests/platform/gtk/fast/repaint/text-selection-overflow-hidden-expected.txt:
* LayoutTests/platform/mac-wk1/TestExpectations:
* LayoutTests/platform/mac-wk1/accessibility/mac/focus-setting-selection-syncronizing-not-clearing-expected.txt: Added.
* LayoutTests/platform/mac-wk1/fast/repaint/4776765-expected.txt: Added.
* LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-margin-005-expected.txt:
* LayoutTests/platform/mac/TestExpectations:
* LayoutTests/platform/win/fast/repaint/4776765-expected.txt: Added.
* LayoutTests/platform/win/fast/repaint/selection-ruby-rl-expected.txt:
* LayoutTests/platform/win/fast/repaint/text-selection-overflow-hidden-expected.txt:

Canonical link: https://commits.webkit.org/250836@main

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html (294609 => 294610)


--- trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/accessibility/mac/selection-boundary-userinfo.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -162,20 +162,31 @@
         var addedNotification = webArea.addNotificationListener(notificationCallback);
         shouldBe("addedNotification", "true");
 
-        textbox = document.getElementById("textbox");
-        textbox.focus();
+        function waitForAnimationFrame() {
+            return new Promise(function(resolve, reject) {
+                requestAnimationFrame(resolve);
+            });
+        }
 
-        move(true);
+        function focusElement(elementId) {
+            element = document.getElementById(elementId);
+            element.focus();
+            return waitForAnimationFrame();
+        }
 
-        textbox = document.getElementById("input");
-        textbox.focus();
+        function moveAsync(isVertical) {
+            move(isVertical);
+            return waitForAnimationFrame();
+        }
 
-        move(false);
-
-        textbox = document.getElementById("textarea");
-        textbox.focus();
-
-        move(true);
+        (async function () {
+            await focusElement("textbox");
+            await moveAsync(true);
+            await focusElement("input");
+            await moveAsync(false);
+            await focusElement("textarea");
+            await moveAsync(true);
+        })();
     }
 
 </script>

Modified: trunk/LayoutTests/accessibility/mac/selection-change-userinfo.html (294609 => 294610)


--- trunk/LayoutTests/accessibility/mac/selection-change-userinfo.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/accessibility/mac/selection-change-userinfo.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -195,19 +195,87 @@
         shouldBe("addedNotification", "true");
 
         textbox = document.getElementById("textbox");
-        textbox.focus();
 
         // Trigger selection changes.
         var s = window.getSelection();
-        s.setPosition(textbox, 0);
-        for (var i in gran) {
-            s.modify("move", "forward", gran[i]);
-            s.modify("move", "backward", gran[i]);
+
+        function focusTextBox() {
+            return new Promise(function(resolve, reject) {
+                setTimeout(() => {
+                    textbox.focus();
+                    resolve();
+                }, 0);
+            });
         }
-        for (var i in gran) {
-            s.setPosition(textbox, 0);
-            s.modify("extend", "forward", gran[i]);
+
+        function moveSelection(direction, granularity) {
+            return new Promise(function(resolve, reject) {
+                setTimeout(function() {
+                    s.modify("move", direction, granularity);
+                    resolve();
+                }, 0);
+            });
         }
+
+        function extendSelection(granularity) {
+            return new Promise(function(resolve, reject) {
+                setTimeout(function() {
+                    s.modify("extend", "forward", granularity);
+                    resolve();
+                }, 0);
+            });
+        }
+
+        function resetPosition() {
+            return new Promise(function(resolve, reject) {
+                setTimeout(function() {
+                    s = window.getSelection();
+                    s.setPosition(textbox, 0);
+                    resolve();
+                }, 0);
+            });
+        }
+
+        (async function() {
+            await focusTextBox();
+            await resetPosition();
+            await moveSelection("forward", gran[0]);
+            await moveSelection("backward", gran[0]);
+            await moveSelection("forward", gran[1]);
+            await moveSelection("backward", gran[1]);
+            await moveSelection("forward", gran[2]);
+            await moveSelection("backward", gran[2]);
+            await moveSelection("forward", gran[3]);
+            await moveSelection("backward", gran[3]);
+            await moveSelection("forward", gran[4]);
+            await moveSelection("backward", gran[4]);
+            await moveSelection("forward", gran[5]);
+            await moveSelection("backward", gran[5]);
+            await moveSelection("forward", gran[6]);
+            await moveSelection("backward", gran[6]);
+            await moveSelection("forward", gran[7]);
+            await moveSelection("backward", gran[7]);
+            await moveSelection("forward", gran[8]);
+            await moveSelection("backward", gran[8]);
+            await resetPosition();
+            await extendSelection(gran[0]);
+            await resetPosition();
+            await extendSelection(gran[1]);
+            await resetPosition();
+            await extendSelection(gran[2]);
+            await resetPosition();
+            await extendSelection(gran[3]);
+            await resetPosition();
+            await extendSelection(gran[4]);
+            await resetPosition();
+            await extendSelection(gran[5]);
+            await resetPosition();
+            await extendSelection(gran[6]);
+            await resetPosition();
+            await extendSelection(gran[7]);
+            await resetPosition();
+            await extendSelection(gran[8]);
+          })();
     }
 
 </script>

Modified: trunk/LayoutTests/accessibility/mac/selection-value-changes-for-aria-textbox.html (294609 => 294610)


--- trunk/LayoutTests/accessibility/mac/selection-value-changes-for-aria-textbox.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/accessibility/mac/selection-value-changes-for-aria-textbox.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -43,12 +43,17 @@
         // Trigger selection changes.
         var s = window.getSelection();
         s.setPosition(textbox, 0);
-        for (var k = 0; k < 3; k++) {
+        requestAnimationFrame(() => {
             s.modify("move", "forward", "character");
-        }
-
-        // Trigger value change.
-        document.execCommand("InsertText", false, "hello ");
+            requestAnimationFrame(() => {
+                s.modify("move", "forward", "character");
+                requestAnimationFrame(() => {
+                    s.modify("move", "forward", "character");
+                    // Trigger value change.
+                    document.execCommand("InsertText", false, "hello ");
+                });
+            });
+        });
     }
 
 </script>

Modified: trunk/LayoutTests/editing/selection-with-absolute-positioned-empty-content.html (294609 => 294610)


--- trunk/LayoutTests/editing/selection-with-absolute-positioned-empty-content.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/editing/selection-with-absolute-positioned-empty-content.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -12,15 +12,26 @@
 <div><a id=foobar style="color: black" href="" this text<span></span></a> but not this</div>
 <pre id=result></pre>
 <script>
-if (window.internals)
-  internals.startTrackingRepaints();
-if (window.testRunner)
-  testRunner.dumpAsText();
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
 
-window.getSelection().selectAllChildren(foobar);
+function timerAfterRAF(callback) {
+    return requestAnimationFrame(() => setTimeout(callback, 0));
+}
 
-if (window.internals) {
-  result.innerText = internals.repaintRectsAsText();
-  internals.stopTrackingRepaints();
-}
-</script>
\ No newline at end of file
+timerAfterRAF(() => {
+    if (window.internals)
+        internals.startTrackingRepaints();
+    window.getSelection().selectAllChildren(foobar);
+    timerAfterRAF(() => {
+        if (window.internals) {
+            result.innerText = internals.repaintRectsAsText();
+            internals.stopTrackingRepaints();
+        }
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+});
+</script>

Modified: trunk/LayoutTests/fast/forms/textarea-scrolled-endline-caret.html (294609 => 294610)


--- trunk/LayoutTests/fast/forms/textarea-scrolled-endline-caret.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/forms/textarea-scrolled-endline-caret.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -15,13 +15,17 @@
     ta.focus();
     // click
     if (window.eventSender) {
-        eventSender.mouseMoveTo(90, 20);
-        eventSender.mouseDown();
-        eventSender.mouseUp();
-        if (ta.selectionEnd == 17)
-            res.innerHTML = "Test Succeeded";
-        else
-            res.innerHTML = "Test Failed: caret is at " + ta.selectionEnd;
+        testRunner.waitUntilDone();
+        requestAnimationFrame(() => {
+            eventSender.mouseMoveTo(90, 20);
+            eventSender.mouseDown();
+            eventSender.mouseUp();
+            if (ta.selectionEnd == 17)
+                res.innerHTML = "Test Succeeded";
+            else
+                res.innerHTML = "Test Failed: caret is at " + ta.selectionEnd;
+            testRunner.notifyDone();
+        });
     } else {
         res.innerHTML = "Test can't run without event sender (part of DumpRenderTree). "
             + "To test manually, click at the middle of the line marked 9 and check that the caret appears after the 9.";

Modified: trunk/LayoutTests/fast/repaint/selection-gap-absolute-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-absolute-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-absolute-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that absolute elements are invalidated correctly. The box will be competely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 0 0 100 100)
-)
-
+(repaint rects (rect 0 0 100 100) )

Modified: trunk/LayoutTests/fast/repaint/selection-gap-absolute-child.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-absolute-child.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-absolute-child.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,11 +1,27 @@
 <!doctype html>
 <head>
-    <script src=""
     <script>
-    function repaintTest()
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+    function runRepaintTest()
     {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         var target = document.getElementById("target");
         getSelection().setBaseAndExtent(target, 0, target.nextSibling, 0);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
     }
     </script>
     <style>
@@ -21,4 +37,5 @@
     <div>
         <div id="target" style="background-color: red; width: 100px; height: 100px; position: absolute;"><br/></div><br/>
     </div>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/selection-gap-fixed-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-fixed-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-fixed-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that fixed elements are invalidated correctly. The box will be competely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 0 0 100 100)
-)
-
+(repaint rects (rect 0 0 100 100) )

Modified: trunk/LayoutTests/fast/repaint/selection-gap-fixed-child.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-fixed-child.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-fixed-child.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,11 +1,26 @@
 <!doctype html>
 <head>
-    <script src=""
     <script>
-    function repaintTest()
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+    function runRepaintTest()
     {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         var target = document.getElementById("target");
         getSelection().setBaseAndExtent(target, 0, target.nextSibling, 0);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+            if (window.testRunner)
+                testRunner.notifyDone();
+        });
     }
     </script>
     <style>
@@ -21,4 +36,5 @@
     <div>
         <div id="target" style="background-color: red; width: 100px; height: 100px; position: fixed;"><br/></div><br/>
     </div>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that absolute elements that get flipped are invalidated correctly. The box will be competely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 0 0 100 100)
-)
-
+(repaint rects (rect 0 0 100 100) )

Modified: trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-flipped-absolute-child.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,11 +1,27 @@
 <!doctype html>
 <head>
-    <script src=""
     <script>
-    function repaintTest()
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+    function runRepaintTest()
     {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         var target = document.getElementById("target");
         getSelection().setBaseAndExtent(target, 0, target.nextSibling, 0);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
     }
     </script>
     <style>
@@ -21,4 +37,5 @@
     <div style="-webkit-writing-mode: vertical-rl">
         <div id="target" style="background-color: red; width: 100px; height: 100px; position: absolute;"><br/></div><br/>
     </div>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that absolute elements that get transformed are invalidated correctly. The box will be completely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 50 50 100 100)
-)
-
+(repaint rects (rect 50 50 100 100) )

Modified: trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-transformed-absolute-child.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,11 +1,27 @@
 <!doctype html>
 <head>
-    <script src=""
     <script>
-    function repaintTest()
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+    function runRepaintTest()
     {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         var target = document.getElementById("target");
         getSelection().setBaseAndExtent(target, 0, target.nextSibling, 0);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
     }
     </script>
     <style>
@@ -21,4 +37,5 @@
     <div style="-webkit-transform: translate(50px, 50px);">
         <div id="target" style="background-color: red; width: 100px; height: 100px; position: absolute;"><br/></div><br/>
     </div>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that fixed elements that get transformed are invalidated correctly. The box will be competely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 50 50 100 100)
-)
-
+(repaint rects (rect 50 50 100 100) )

Modified: trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-gap-transformed-fixed-child.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,11 +1,27 @@
 <!doctype html>
 <head>
-    <script src=""
     <script>
-    function repaintTest()
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+    function runRepaintTest()
     {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         var target = document.getElementById("target");
         getSelection().setBaseAndExtent(target, 0, target.nextSibling, 0);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
     }
     </script>
     <style>
@@ -21,4 +37,5 @@
     <div style="-webkit-transform: translate(50px, 50px);">
         <div id="target" style="background-color: red; width: 100px; height: 100px; position: fixed;"><br/></div><br/>
     </div>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/selection-paint-invalidation-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-paint-invalidation-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-paint-invalidation-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,6 +2,5 @@
 A
 (repaint rects
   (rect 8 68 20 100)
-  (rect 8 68 20 100)
 )
 

Modified: trunk/LayoutTests/fast/repaint/selection-ruby-rl-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-ruby-rl-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-ruby-rl-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -8,7 +8,4 @@
 Testing both hit testing and painting of selection.
 Testing both hit testing and painting of selection.
 Testing both hit testing and painting of selection.
-(repaint rects
-  (rect 774 38 18 79)
-)
-
+(repaint rects (rect 774 38 18 79) )

Modified: trunk/LayoutTests/fast/repaint/selection-ruby-rl.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/selection-ruby-rl.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/selection-ruby-rl.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -3,7 +3,15 @@
 <head>
 <script src=""
 <script>
-function repaintTest() {
+if (window.testRunner) {
+    testRunner.dumpAsText(false);
+    testRunner.waitUntilDone();
+}
+
+function runRepaintTest() {
+    if (window.internals)
+        internals.startTrackingRepaints();
+
     if (eventSender) {
         eventSender.mouseMoveTo(790, 40);
         eventSender.mouseDown();
@@ -11,6 +19,16 @@
         eventSender.mouseMoveTo(790, 120);
         eventSender.mouseUp();
     }
+
+    setTimeout(function() {
+        if (window.internals) {
+            document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+            internals.stopTrackingRepaints();
+        }
+
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }, 0);
 }
 </script>
 
@@ -26,4 +44,5 @@
 Testing both hit testing and painting of selection.<br>
 Testing both hit testing and painting of selection.<br>
 Testing both hit testing and painting of selection.<br>
+<div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden-expected.txt (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,6 +1,3 @@
 Should have green background
 
-(repaint rects
-  (rect 8 16 199 18)
-)
-
+(repaint rects (rect 8 16 199 18) )

Modified: trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden.html (294609 => 294610)


--- trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/repaint/text-selection-overflow-hidden.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,5 +1,4 @@
 <!DOCTYPE html>
-<script src="" type="text/_javascript_"></script>
 <style>
 #test {
     background-color: red;
@@ -12,11 +11,30 @@
 }
 </style>
 <script>
-    function repaintTest() {
+    if (window.testRunner) {
+        testRunner.dumpAsText(false);
+        testRunner.waitUntilDone();
+    }
+
+    function runRepaintTest() {
+        if (window.internals)
+            internals.startTrackingRepaints();
+
         getSelection().setBaseAndExtent(test, 0, test, 1);
+
+        setTimeout(function() {
+            if (window.internals) {
+                document.querySelector('#repaints').innerHTML = window.internals.repaintRectsAsText();
+                internals.stopTrackingRepaints();
+            }
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
     };
 </script>
 
 <body _onload_="runRepaintTest()">
     <p id="test">Should have green background</p>
+    <div id="repaints"></div>
 </body>

Modified: trunk/LayoutTests/fast/text/incorrect-deselection-across-multiple-elements.html (294609 => 294610)


--- trunk/LayoutTests/fast/text/incorrect-deselection-across-multiple-elements.html	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/fast/text/incorrect-deselection-across-multiple-elements.html	2022-05-21 06:09:00 UTC (rev 294610)
@@ -20,11 +20,13 @@
   if (window.internals)
     internals.startTrackingRepaints();
   window.getSelection().selectAllChildren(second);
-  if (window.internals) {
-    result.innerText = internals.repaintRectsAsText().indexOf("784 70") == -1 ? "FAIL" : "PASS";
-    internals.stopTrackingRepaints();
-  }
-  if (window.testRunner)
-    testRunner.notifyDone();
+  setTimeout(function() {
+    if (window.internals) {
+      result.innerText = internals.repaintRectsAsText().indexOf("784 70") == -1 ? "FAIL" : "PASS";
+      internals.stopTrackingRepaints();
+    }
+    if (window.testRunner)
+      testRunner.notifyDone();
+  }, 0);
 }, 0);
 </script>
\ No newline at end of file

Modified: trunk/LayoutTests/platform/gtk/TestExpectations (294609 => 294610)


--- trunk/LayoutTests/platform/gtk/TestExpectations	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/gtk/TestExpectations	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1531,8 +1531,6 @@
 # Incomplete implementation of eventSender causes this test to fail
 webkit.org/b/42194 fast/scrolling/scroll-select-list.html [ ImageOnlyFailure ]
 
-webkit.org/b/139354 fast/repaint/selection-ruby-rl.html [ Failure ]
-
 # Missing glyph symbol is not rendered properly.
 webkit.org/b/140252 fast/css/line-height-determined-by-primary-font.html [ Failure ]
 webkit.org/b/140252 fast/text/decorations-with-text-combine.html [ Failure ]

Copied: trunk/LayoutTests/platform/gtk/fast/repaint/selection-ruby-rl-expected.txt (from rev 294609, trunk/LayoutTests/fast/repaint/selection-ruby-rl-expected.txt) (0 => 294610)


--- trunk/LayoutTests/platform/gtk/fast/repaint/selection-ruby-rl-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/gtk/fast/repaint/selection-ruby-rl-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -0,0 +1,11 @@
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.Some ruby
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+Testing both hit testing and painting of selection.
+(repaint rects (rect 775 37 17 84) )

Modified: trunk/LayoutTests/platform/gtk/fast/repaint/text-selection-overflow-hidden-expected.txt (294609 => 294610)


--- trunk/LayoutTests/platform/gtk/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/gtk/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,6 +1,3 @@
 Should have green background
 
-(repaint rects
-  (rect 8 16 197 17)
-)
-
+(repaint rects (rect 8 16 197 17) )

Modified: trunk/LayoutTests/platform/mac/TestExpectations (294609 => 294610)


--- trunk/LayoutTests/platform/mac/TestExpectations	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2305,3 +2305,4 @@
 
 webkit.org/b/240074 imported/w3c/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html [ Pass Failure ]
 
+webkit.org/b/231298 accessibility/mac/selection-sync.html [ Skip ] # Timeout

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (294609 => 294610)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1841,3 +1841,6 @@
 
 # rdar://82399990 ([ Catalina EWS ] webgl/2.0.0/* tests are flaky crashing ASSERTION FAILED: !needsLayout() (229580)) Disable webgl tests for mac-wk1
 webgl [ Skip ]
+
+webkit.org/b/231298 accessibility/mac/selection-boundary-userinfo.html [ Failure ]
+webkit.org/b/232630 fast/forms/autofocus-opera-003.html [ Failure ]

Added: trunk/LayoutTests/platform/mac-wk1/accessibility/mac/focus-setting-selection-syncronizing-not-clearing-expected.txt (0 => 294610)


--- trunk/LayoutTests/platform/mac-wk1/accessibility/mac/focus-setting-selection-syncronizing-not-clearing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/accessibility/mac/focus-setting-selection-syncronizing-not-clearing-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -0,0 +1,17 @@
+
+ 1
+ 2
+This tests that calling focus on a render object when it doesn't result in a selection change won't leave isSynchronizingSelection set to true.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS addedNotification is true
+PASS accessibilityController.focusedElement.isEqual(accessibilityController.accessibleElementById("1")) is true
+PASS axTextStateSyncOne is undefined
+PASS accessibilityController.accessibleElementById("1").isFocusable is true
+PASS axTextStateSyncTwo is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/platform/mac-wk1/fast/repaint/4776765-expected.txt (0 => 294610)


--- trunk/LayoutTests/platform/mac-wk1/fast/repaint/4776765-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/fast/repaint/4776765-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -0,0 +1,14 @@
+
+
+
+(repaint rects
+  (rect 1 19 15 32)
+  (rect 8 26 1 18)
+  (rect 1 19 15 32)
+  (rect 8 26 1 18)
+  (rect 1 37 798 32)
+  (rect 8 44 784 18)
+  (rect 1 51 798 18)
+  (rect 1 44 798 7)
+)
+

Modified: trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-margin-005-expected.txt (294609 => 294610)


--- trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-margin-005-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-target-margin-005-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,4 +1,4 @@
 
 
-FAIL scroll-margin on input widget assert_between_exclusive: Should honor date input scroll-margin expected a number greater than 4750 and less than 4850 but got 4720
+FAIL scroll-margin on input widget assert_between_exclusive: Should honor date input scroll-margin expected a number greater than 4750 and less than 4850 but got 9439
 

Added: trunk/LayoutTests/platform/win/fast/repaint/4776765-expected.txt (0 => 294610)


--- trunk/LayoutTests/platform/win/fast/repaint/4776765-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/win/fast/repaint/4776765-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -0,0 +1,10 @@
+
+
+
+(repaint rects
+  (rect 1 37 798 32)
+  (rect 8 44 784 18)
+  (rect 1 51 798 18)
+  (rect 1 44 798 7)
+)
+

Modified: trunk/LayoutTests/platform/win/fast/repaint/selection-gap-fixed-child-expected.txt (294609 => 294610)


--- trunk/LayoutTests/platform/win/fast/repaint/selection-gap-fixed-child-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/win/fast/repaint/selection-gap-fixed-child-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -2,7 +2,4 @@
 This tests that fixed elements are invalidated correctly. The box will be competely green if the selected area was invalidated correctly.
 
 
-(repaint rects
-  (rect 0 0 100 100)
-)
-
+(repaint rects (rect 0 0 100 100) )

Modified: trunk/LayoutTests/platform/win/fast/repaint/selection-ruby-rl-expected.txt (294609 => 294610)


--- trunk/LayoutTests/platform/win/fast/repaint/selection-ruby-rl-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/win/fast/repaint/selection-ruby-rl-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -8,7 +8,4 @@
 Testing both hit testing and painting of selection.
 Testing both hit testing and painting of selection.
 Testing both hit testing and painting of selection.
-(repaint rects
-  (rect 774 39 18 83)
-)
-
+(repaint rects (rect 774 39 18 83) )

Modified: trunk/LayoutTests/platform/win/fast/repaint/text-selection-overflow-hidden-expected.txt (294609 => 294610)


--- trunk/LayoutTests/platform/win/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/LayoutTests/platform/win/fast/repaint/text-selection-overflow-hidden-expected.txt	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1,6 +1,3 @@
 Should have green background
 
-(repaint rects
-  (rect 8 16 197 18)
-)
-
+(repaint rects (rect 8 16 197 18) )

Modified: trunk/Source/WebCore/Modules/highlight/AppHighlightStorage.cpp (294609 => 294610)


--- trunk/Source/WebCore/Modules/highlight/AppHighlightStorage.cpp	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/Modules/highlight/AppHighlightStorage.cpp	2022-05-21 06:09:00 UTC (rev 294610)
@@ -271,7 +271,7 @@
         if (textIndicator)
             m_document->page()->chrome().client().setTextIndicator(textIndicator->data());
 
-        TemporarySelectionChange selectionChange(*strongDocument, { range.value() }, { TemporarySelectionOption::DelegateMainFrameScroll, TemporarySelectionOption::SmoothScroll, TemporarySelectionOption::RevealSelectionBounds });
+        TemporarySelectionChange selectionChange(*strongDocument, { *range }, { TemporarySelectionOption::DelegateMainFrameScroll, TemporarySelectionOption::SmoothScroll, TemporarySelectionOption::RevealSelectionBounds, TemporarySelectionOption::UserTriggered });
     }
 
     return true;

Modified: trunk/Source/WebCore/editing/Editor.cpp (294609 => 294610)


--- trunk/Source/WebCore/editing/Editor.cpp	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/editing/Editor.cpp	2022-05-21 06:09:00 UTC (rev 294610)
@@ -264,7 +264,7 @@
 
 void TemporarySelectionChange::setSelection(const VisibleSelection& selection, IsTemporarySelection isTemporarySelection)
 {
-    auto options = FrameSelection::defaultSetSelectionOptions();
+    auto options = FrameSelection::defaultSetSelectionOptions(m_options.contains(TemporarySelectionOption::UserTriggered) ? UserTriggered : NotUserTriggered);
     if (m_options & TemporarySelectionOption::DoNotSetFocus)
         options.add(FrameSelection::DoNotSetFocus);
 

Modified: trunk/Source/WebCore/editing/Editor.h (294609 => 294610)


--- trunk/Source/WebCore/editing/Editor.h	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/editing/Editor.h	2022-05-21 06:09:00 UTC (rev 294610)
@@ -126,6 +126,8 @@
     DelegateMainFrameScroll = 1 << 5,
     
     RevealSelectionBounds = 1 << 6,
+
+    UserTriggered = 1 << 7,
 };
 
 class TemporarySelectionChange {

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (294609 => 294610)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2022-05-21 06:09:00 UTC (rev 294610)
@@ -454,6 +454,11 @@
     if (frameView && frameView->layoutContext().isLayoutPending())
         return;
 
+    if (!(options & IsUserTriggered)) {
+        scheduleAppearanceUpdateAfterStyleChange();
+        return;
+    }
+
     updateAndRevealSelection(intent, options.contains(SmoothScroll) ? ScrollBehavior::Smooth : ScrollBehavior::Instant, options.contains(RevealSelectionBounds) ? RevealExtentOption::DoNotRevealExtent : RevealExtentOption::RevealExtent);
 
     if (options & IsUserTriggered) {
@@ -462,13 +467,19 @@
     }
 }
 
-static void updateSelectionByUpdatingLayoutOrStyle(Document& document)
+void FrameSelection::updateSelectionAppearanceNow()
 {
+    if (!m_document || !m_document->hasLivingRenderTree())
+        return;
+
+    Ref document = *m_document;
 #if ENABLE(TEXT_CARET)
-    document.updateLayoutIgnorePendingStylesheets();
+    document->updateLayoutIgnorePendingStylesheets();
 #else
-    document.updateStyleIfNeeded();
+    document->updateStyleIfNeeded();
 #endif
+    if (m_pendingSelectionUpdate)
+        updateAppearance();
 }
 
 void FrameSelection::setNeedsSelectionUpdate(RevealSelectionAfterUpdate revealMode)
@@ -1700,7 +1711,7 @@
 {
     if (!m_document)
         return IntRect();
-    updateSelectionByUpdatingLayoutOrStyle(*m_document);
+    updateSelectionAppearanceNow();
     recomputeCaretRect();
     if (insideFixed)
         *insideFixed = m_caretInsidePositionFixed;
@@ -2258,7 +2269,7 @@
 
     // FIXME: We shouldn't trigger a synchronous layout here.
     if (doAppearanceUpdate == ShouldUpdateAppearance::Yes && m_document)
-        updateSelectionByUpdatingLayoutOrStyle(*m_document);
+        updateSelectionAppearanceNow();
 
 #if ENABLE(TEXT_CARET)
     if (m_caretPaint) {
@@ -2361,12 +2372,12 @@
     return m_document->editor().client()->shouldDeleteRange(selection.toNormalizedRange());
 }
 
-FloatRect FrameSelection::selectionBounds(ClipToVisibleContent clipToVisibleContent) const
+FloatRect FrameSelection::selectionBounds(ClipToVisibleContent clipToVisibleContent)
 {
     if (!m_document)
         return LayoutRect();
 
-    updateSelectionByUpdatingLayoutOrStyle(*m_document);
+    updateSelectionAppearanceNow();
     auto* renderView = m_document->renderView();
     if (!renderView)
         return LayoutRect();
@@ -2462,6 +2473,8 @@
     if (isNone())
         return;
 
+    updateSelectionAppearanceNow();
+
     LayoutRect rect;
     bool insideFixed = false;
     if (isCaret())

Modified: trunk/Source/WebCore/editing/FrameSelection.h (294609 => 294610)


--- trunk/Source/WebCore/editing/FrameSelection.h	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/editing/FrameSelection.h	2022-05-21 06:09:00 UTC (rev 294610)
@@ -245,7 +245,7 @@
     void clearTypingStyle();
 
     enum class ClipToVisibleContent : uint8_t { No, Yes };
-    WEBCORE_EXPORT FloatRect selectionBounds(ClipToVisibleContent = ClipToVisibleContent::Yes) const;
+    WEBCORE_EXPORT FloatRect selectionBounds(ClipToVisibleContent = ClipToVisibleContent::Yes);
 
     enum class TextRectangleHeight { TextHeight, SelectionHeight };
     WEBCORE_EXPORT void getClippedVisibleTextRectangles(Vector<FloatRect>&, TextRectangleHeight = TextRectangleHeight::SelectionHeight) const;
@@ -267,6 +267,7 @@
     void updateFromAssociatedLiveRange();
 
 private:
+    void updateSelectionAppearanceNow();
     void updateAndRevealSelection(const AXTextStateChangeIntent&, ScrollBehavior = ScrollBehavior::Instant, RevealExtentOption = RevealExtentOption::RevealExtent);
     void updateDataDetectorsForSelection();
 

Modified: trunk/Source/WebCore/page/EventHandler.cpp (294609 => 294610)


--- trunk/Source/WebCore/page/EventHandler.cpp	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2022-05-21 06:09:00 UTC (rev 294610)
@@ -444,7 +444,7 @@
 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelection& newSelection)
 {
     if (selection.selection() != newSelection && selection.shouldChangeSelection(newSelection))
-        selection.setSelection(newSelection);
+        selection.setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(UserTriggered));
 }
 
 static inline bool dispatchSelectStart(Node* node)

Modified: trunk/Source/WebCore/page/Page.cpp (294609 => 294610)


--- trunk/Source/WebCore/page/Page.cpp	2022-05-21 05:39:52 UTC (rev 294609)
+++ trunk/Source/WebCore/page/Page.cpp	2022-05-21 06:09:00 UTC (rev 294610)
@@ -1742,6 +1742,10 @@
     });
 
     forEachDocument([] (Document& document) {
+        document.selection().updateAppearanceAfterLayout();
+    });
+
+    forEachDocument([] (Document& document) {
         document.updateHighlightPositions();
     });
 #if ENABLE(APP_HIGHLIGHTS)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to