Title: [242000] releases/WebKitGTK/webkit-2.22
Revision
242000
Author
ape...@igalia.com
Date
2019-02-23 17:06:03 -0800 (Sat, 23 Feb 2019)

Log Message

Merged r241289 - AXObjectCache::childrenChanged shouldn't update layout or style during another style recalc
https://bugs.webkit.org/show_bug.cgi?id=182280
<rdar://problem/37018386>

Reviewed by Alan Bujtas.

Source/WebCore:

Remove the possibility that changing children calls back into updating layout by
handling children changes in a deferred manner.

This follows the same architecture as many other deferred changes, but also requires us to check deferred changes
in updateBackingStore, because things like aria-hidden changes won't trigger a layout, but will require us to update children.

A few tests had to be modified to no longer change the tree and then check the children immediately.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::remove):
(WebCore::AXObjectCache::childrenChanged):
(WebCore::AXObjectCache::prepareForDocumentDestruction):
(WebCore::AXObjectCache::performDeferredCacheUpdate):
* accessibility/AXObjectCache.h:
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::updateBackingStore):
* accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
(convertToNSArray):
(-[WebAccessibilityObjectWrapperBase updateObjectBackingStore]):

LayoutTests:

* accessibility/aria-hidden-update.html:
* accessibility/aria-hidden-updates-alldescendants.html:
* accessibility/image-load-on-delay.html:
* accessibility/mac/aria-hidden-changes-for-non-ignored-elements.html:
* accessibility/removed-anonymous-block-child-causes-crash.html:

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/ChangeLog (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/ChangeLog	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/ChangeLog	2019-02-24 01:06:03 UTC (rev 242000)
@@ -1,3 +1,17 @@
+2019-02-08  Chris Fleizach  <cfleiz...@apple.com>
+
+        AXObjectCache::childrenChanged shouldn't update layout or style during another style recalc
+        https://bugs.webkit.org/show_bug.cgi?id=182280
+        <rdar://problem/37018386>
+
+        Reviewed by Alan Bujtas.
+
+        * accessibility/aria-hidden-update.html:
+        * accessibility/aria-hidden-updates-alldescendants.html:
+        * accessibility/image-load-on-delay.html:
+        * accessibility/mac/aria-hidden-changes-for-non-ignored-elements.html:
+        * accessibility/removed-anonymous-block-child-causes-crash.html:
+
 2019-01-18  Ali Juma  <aj...@chromium.org>
 
         FetchResponse::url should return the empty string for tainted responses

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-update.html (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-update.html	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-update.html	2019-02-24 01:06:03 UTC (rev 242000)
@@ -18,6 +18,7 @@
      
     <script>
         if (window.accessibilityController) {
+            jsTestIsAsync = true;
             description("This test makes sure that when aria-hidden changes, the AX hierarchy is updated.");
 
             // Get the parent element.
@@ -39,18 +40,24 @@
 
             // Make the 2nd button hidden. Only 1 and 3 should be present.
             document.getElementById("button2").setAttribute("aria-hidden", "true");
-            shouldBeTrue("parent.childAtIndex(0).isEqual(button1)");
-            shouldBeTrue("parent.childAtIndex(1).isEqual(button3)");
+            setTimeout(function() {
+                shouldBeTrue("parent.childAtIndex(0).isEqual(button1)");
+                shouldBeTrue("parent.childAtIndex(1).isEqual(button3)");
            
-            // Make the 1st button hidden. Only 3 should be present.
-            document.getElementById("button1").setAttribute("aria-hidden", "true");
-            shouldBeTrue("parent.childAtIndex(0).isEqual(button3)");
+                // Make the 1st button hidden. Only 3 should be present.
+                document.getElementById("button1").setAttribute("aria-hidden", "true");
+                setTimeout(function() {
+                    shouldBeTrue("parent.childAtIndex(0).isEqual(button3)");
 
-            // Make the 2nd button not hidden. 2 and 3 should be present.
-            document.getElementById("button2").setAttribute("aria-hidden", "false");
-            shouldBeTrue("parent.childAtIndex(0).isEqual(button2)");
-            shouldBeTrue("parent.childAtIndex(1).isEqual(button3)");
-
+                    // Make the 2nd button not hidden. 2 and 3 should be present.
+                    document.getElementById("button2").setAttribute("aria-hidden", "false");
+                    setTimeout(function() {
+                        shouldBeTrue("parent.childAtIndex(0).isEqual(button2)");
+                        shouldBeTrue("parent.childAtIndex(1).isEqual(button3)");
+                        finishJSTest();
+                    }, 0);
+                }, 0);
+            }, 0);
         }
     </script>
 

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-updates-alldescendants.html (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-updates-alldescendants.html	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/aria-hidden-updates-alldescendants.html	2019-02-24 01:06:03 UTC (rev 242000)
@@ -26,6 +26,7 @@
     description("This tests that if aria-hidden changes on an element, all it's existing children will update their children caches");
 
     if (window.accessibilityController) {
+          jsTestIsAsync = true;
           document.getElementById("main").focus();
           
           var main = accessibilityController.focusedElement;
@@ -37,12 +38,14 @@
           var group = document.getElementsByTagName('main')[0];
           var items = group.getElementsByTagName('div');          
           items[0].removeAttribute('aria-hidden');
-
-          // After removing aria-hidden, the new count should be 2.
-          shouldBe("main.childrenCount", "2");          
+          setTimeout(function() {
+              // After removing aria-hidden, the new count should be 2.
+              shouldBe("main.childrenCount", "2");          
           
-          // And most importantly, the DIV that was made non-hidden should have one child now.
-          shouldBe("main.childAtIndex(1).childrenCount", "1");
+              // And most importantly, the DIV that was made non-hidden should have one child now.
+              shouldBe("main.childAtIndex(1).childrenCount", "1");
+              finishJSTest();
+          }, 0);
     }
 
 </script>

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/image-load-on-delay.html (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/image-load-on-delay.html	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/image-load-on-delay.html	2019-02-24 01:06:03 UTC (rev 242000)
@@ -25,8 +25,10 @@
 
           document.getElementById("image")._onload_ = function() {
               document.body.offsetHeight;
-              debug("AFTER: Group count: " + content.childrenCount);
-              finishJSTest();
+              setTimeout(function() {
+                  debug("AFTER: Group count: " + content.childrenCount);
+                  finishJSTest();
+              }, 0);
           };
 
           setTimeout(function() { 

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/mac/aria-hidden-changes-for-non-ignored-elements.html (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/mac/aria-hidden-changes-for-non-ignored-elements.html	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/mac/aria-hidden-changes-for-non-ignored-elements.html	2019-02-24 01:06:03 UTC (rev 242000)
@@ -25,7 +25,7 @@
     description("This tests that when aria-hidden is toggled, it will clear out the cached children for non-ignored elements that are descendants.");
 
     if (window.accessibilityController) {
-
+        jsTestIsAsync = true;
         document.getElementById("body").focus();
         var body = accessibilityController.focusedElement;
 
@@ -34,11 +34,16 @@
 
         // Toggle aria-hidden, and we should not be able to access the same elements anymore.
         document.getElementById("main").setAttribute("aria-hidden", "true");
-        shouldBe("body.childAtIndex(0).role", "'AXRole: AXCheckBox'");
+        setTimeout(function() {
+            shouldBe("body.childAtIndex(0).role", "'AXRole: AXCheckBox'");
 
-        // Toggle aria-hidden off again and we should again be able to access elements inside the tab panel.
-        document.getElementById("main").setAttribute("aria-hidden", "false");
-        shouldBe("body.childAtIndex(3).childAtIndex(0).role", "'AXRole: AXButton'");
+            // Toggle aria-hidden off again and we should again be able to access elements inside the tab panel.
+            document.getElementById("main").setAttribute("aria-hidden", "false");
+            setTimeout(function() {
+                shouldBe("body.childAtIndex(3).childAtIndex(0).role", "'AXRole: AXButton'");
+                finishJSTest();
+            }, 0);
+        }, 0);
 
     }
 

Modified: releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/LayoutTests/accessibility/removed-anonymous-block-child-causes-crash.html	2019-02-24 01:06:03 UTC (rev 242000)
@@ -8,6 +8,8 @@
     }
 
     function queryIsEnabledOnDecendants(accessibilityObject) {
+        if (!accessibilityObject)
+            return;
         accessibilityObject.isEnabled
 
         var count = accessibilityObject.childrenCount;

Modified: releases/WebKitGTK/webkit-2.22/Source/WebCore/ChangeLog (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/Source/WebCore/ChangeLog	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/Source/WebCore/ChangeLog	2019-02-24 01:06:03 UTC (rev 242000)
@@ -1,3 +1,31 @@
+2019-02-08  Chris Fleizach  <cfleiz...@apple.com>
+
+        AXObjectCache::childrenChanged shouldn't update layout or style during another style recalc
+        https://bugs.webkit.org/show_bug.cgi?id=182280
+        <rdar://problem/37018386>
+
+        Reviewed by Alan Bujtas.
+
+        Remove the possibility that changing children calls back into updating layout by
+        handling children changes in a deferred manner.
+
+        This follows the same architecture as many other deferred changes, but also requires us to check deferred changes
+        in updateBackingStore, because things like aria-hidden changes won't trigger a layout, but will require us to update children.
+
+        A few tests had to be modified to no longer change the tree and then check the children immediately. 
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::remove):
+        (WebCore::AXObjectCache::childrenChanged):
+        (WebCore::AXObjectCache::prepareForDocumentDestruction):
+        (WebCore::AXObjectCache::performDeferredCacheUpdate):
+        * accessibility/AXObjectCache.h:
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::updateBackingStore):
+        * accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
+        (convertToNSArray):
+        (-[WebAccessibilityObjectWrapperBase updateObjectBackingStore]):
+
 2019-02-13  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [FreeType] Unable to render some Hebrew characters

Modified: releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.cpp (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.cpp	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.cpp	2019-02-24 01:06:03 UTC (rev 242000)
@@ -739,6 +739,7 @@
     if (is<Element>(node)) {
         m_deferredRecomputeIsIgnoredList.remove(downcast<Element>(&node));
         m_deferredSelectedChildredChangedList.remove(downcast<Element>(&node));
+        m_deferredChildrenChangedNodeList.remove(&node);
         m_deferredTextFormControlValue.remove(downcast<Element>(&node));
         m_deferredAttributeChange.remove(downcast<Element>(&node));
     }
@@ -851,10 +852,8 @@
     
 void AXObjectCache::childrenChanged(Node* node, Node* newChild)
 {
-    if (newChild) {
-        handleMenuOpened(newChild);
-        handleLiveRegionCreated(newChild);
-    }
+    if (newChild)
+        m_deferredChildrenChangedNodeList.add(newChild);
 
     childrenChanged(get(node));
 }
@@ -864,14 +863,9 @@
     if (!renderer)
         return;
 
-    // FIXME: Refactor the code to avoid calling updateLayout in this call stack.
-    ScriptDisallowedScope::LayoutAssertionDisableScope disableScope;
-    
-    if (newChild) {
-        handleMenuOpened(newChild->node());
-        handleLiveRegionCreated(newChild->node());
-    }
-    
+    if (newChild && newChild->node())
+        m_deferredChildrenChangedNodeList.add(newChild->node());
+
     childrenChanged(get(renderer));
 }
 
@@ -880,7 +874,7 @@
     if (!obj)
         return;
 
-    obj->childrenChanged();
+    m_deferredChildredChangedList.add(obj);
 }
     
 void AXObjectCache::notificationPostTimerFired()
@@ -2846,6 +2840,7 @@
     filterListForRemoval(m_deferredRecomputeIsIgnoredList, document, nodesToRemove);
     filterListForRemoval(m_deferredTextChangedList, document, nodesToRemove);
     filterListForRemoval(m_deferredSelectedChildredChangedList, document, nodesToRemove);
+    filterListForRemoval(m_deferredChildrenChangedNodeList, document, nodesToRemove);
     filterMapForRemoval(m_deferredTextFormControlValue, document, nodesToRemove);
     filterMapForRemoval(m_deferredAttributeChange, document, nodesToRemove);
     filterVectorPairForRemoval(m_deferredFocusedNodeChange, document, nodesToRemove);
@@ -2878,6 +2873,17 @@
         return;
 
     SetForScope<bool> performingDeferredCacheUpdate(m_performingDeferredCacheUpdate, true);
+
+    for (auto* nodeChild : m_deferredChildrenChangedNodeList) {
+        handleMenuOpened(nodeChild);
+        handleLiveRegionCreated(nodeChild);
+    }
+    m_deferredChildrenChangedNodeList.clear();
+
+    for (auto& child : m_deferredChildredChangedList)
+        child->childrenChanged();
+    m_deferredChildredChangedList.clear();
+
     for (auto* node : m_deferredTextChangedList)
         textChanged(node);
     m_deferredTextChangedList.clear();

Modified: releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.h (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.h	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AXObjectCache.h	2019-02-24 01:06:03 UTC (rev 242000)
@@ -452,6 +452,8 @@
     ListHashSet<Element*> m_deferredRecomputeIsIgnoredList;
     ListHashSet<Node*> m_deferredTextChangedList;
     ListHashSet<Element*> m_deferredSelectedChildredChangedList;
+    ListHashSet<RefPtr<AccessibilityObject>> m_deferredChildredChangedList;
+    ListHashSet<Node*> m_deferredChildrenChangedNodeList;
     HashMap<Element*, String> m_deferredTextFormControlValue;
     HashMap<Element*, QualifiedName> m_deferredAttributeChange;
     Vector<std::pair<Node*, Node*>> m_deferredFocusedNodeChange;

Modified: releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AccessibilityObject.cpp (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AccessibilityObject.cpp	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/AccessibilityObject.cpp	2019-02-24 01:06:03 UTC (rev 242000)
@@ -1786,6 +1786,10 @@
         if (!document->view()->layoutContext().isInRenderTreeLayout() && !document->inRenderTreeUpdate() && !document->inStyleRecalc())
             document->updateLayoutIgnorePendingStylesheets();
     }
+
+    if (auto cache = axObjectCache())
+        cache->performDeferredCacheUpdate();
+    
     updateChildrenIfNecessary();
 }
 #endif

Modified: releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm (241999 => 242000)


--- releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2019-02-24 01:05:52 UTC (rev 241999)
+++ releases/WebKitGTK/webkit-2.22/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2019-02-24 01:06:03 UTC (rev 242000)
@@ -250,15 +250,15 @@
     NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
     for (const auto& child : vector) {
         auto wrapper = (WebAccessibilityObjectWrapperBase *)child->wrapper();
-        ASSERT(wrapper);
-        if (wrapper) {
-            // We want to return the attachment view instead of the object representing the attachment,
-            // otherwise, we get palindrome errors in the AX hierarchy.
-            if (child->isAttachment() && [wrapper attachmentView])
-                [array addObject:[wrapper attachmentView]];
-            else
-                [array addObject:wrapper];
-        }
+        if (!wrapper)
+            continue;
+
+        // We want to return the attachment view instead of the object representing the attachment,
+        // otherwise, we get palindrome errors in the AX hierarchy.
+        if (child->isAttachment() && [wrapper attachmentView])
+            [array addObject:[wrapper attachmentView]];
+        else
+            [array addObject:wrapper];
     }
     return [[array copy] autorelease];
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to