Title: [225855] trunk/Source/WebCore
Revision
225855
Author
[email protected]
Date
2017-12-13 10:43:05 -0800 (Wed, 13 Dec 2017)

Log Message

ASSERT(LayoutDisallowedScope::isLayoutAllowed()) whenever hitting Enter in Web Inspector console
https://bugs.webkit.org/show_bug.cgi?id=180690

Reviewed by Simon Fraser.

Defer text replacement notification until after layout is done to avoid unexpected forced layouts.

Covered by existing tests.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::disableAccessibility):
(WebCore::AXObjectCache::remove):
(WebCore::filterMapForRemoval):
(WebCore::filterListForRemoval):
(WebCore::AXObjectCache::prepareForDocumentDestruction):
(WebCore::AXObjectCache::performDeferredCacheUpdate):
(WebCore::AXObjectCache::deferTextReplacementNotificationForTextControl):
(WebCore::filterForRemoval): Deleted.
* accessibility/AXObjectCache.h: Need to use the base (Element) class since
we can't call is<HTMLTextFormControlElement> in Node d'tor.
(WebCore::AXObjectCache::deferTextReplacementNotificationForTextControl):
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::setInnerTextValue):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (225854 => 225855)


--- trunk/Source/WebCore/ChangeLog	2017-12-13 18:36:26 UTC (rev 225854)
+++ trunk/Source/WebCore/ChangeLog	2017-12-13 18:43:05 UTC (rev 225855)
@@ -1,3 +1,29 @@
+2017-12-13  Zalan Bujtas  <[email protected]>
+
+        ASSERT(LayoutDisallowedScope::isLayoutAllowed()) whenever hitting Enter in Web Inspector console
+        https://bugs.webkit.org/show_bug.cgi?id=180690
+
+        Reviewed by Simon Fraser.
+
+        Defer text replacement notification until after layout is done to avoid unexpected forced layouts.
+
+        Covered by existing tests.
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::disableAccessibility):
+        (WebCore::AXObjectCache::remove):
+        (WebCore::filterMapForRemoval):
+        (WebCore::filterListForRemoval):
+        (WebCore::AXObjectCache::prepareForDocumentDestruction):
+        (WebCore::AXObjectCache::performDeferredCacheUpdate):
+        (WebCore::AXObjectCache::deferTextReplacementNotificationForTextControl):
+        (WebCore::filterForRemoval): Deleted.
+        * accessibility/AXObjectCache.h: Need to use the base (Element) class since
+        we can't call is<HTMLTextFormControlElement> in Node d'tor.
+        (WebCore::AXObjectCache::deferTextReplacementNotificationForTextControl):
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::setInnerTextValue):
+
 2017-12-13  Ryan Haddad  <[email protected]>
 
         Unreviewed, rolling out r225836.

Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (225854 => 225855)


--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp	2017-12-13 18:36:26 UTC (rev 225854)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp	2017-12-13 18:43:05 UTC (rev 225855)
@@ -721,6 +721,7 @@
     if (is<Element>(node)) {
         m_deferredRecomputeIsIgnoredList.remove(downcast<Element>(&node));
         m_deferredSelectedChildredChangedList.remove(downcast<Element>(&node));
+        m_deferredTextFormControlValue.remove(downcast<Element>(&node));
     }
     m_deferredTextChangedList.remove(&node);
     removeNodeForUse(node);
@@ -2725,8 +2726,19 @@
     return result;
 }
 
+template<typename T, typename U>
+static void filterMapForRemoval(const HashMap<T, U>& list, const Document& document, HashSet<Node*>& nodesToRemove)
+{
+    for (auto& entry : list) {
+        auto* node = entry.key;
+        if (node->isConnected() && &node->document() != &document)
+            continue;
+        nodesToRemove.add(node);
+    }
+}
+
 template<typename T>
-static void filterForRemoval(const ListHashSet<T>& list, const Document& document, HashSet<Node*>& nodesToRemove)
+static void filterListForRemoval(const ListHashSet<T>& list, const Document& document, HashSet<Node*>& nodesToRemove)
 {
     for (auto* node : list) {
         if (node->isConnected() && &node->document() != &document)
@@ -2738,11 +2750,12 @@
 void AXObjectCache::prepareForDocumentDestruction(const Document& document)
 {
     HashSet<Node*> nodesToRemove;
-    filterForRemoval(m_textMarkerNodes, document, nodesToRemove);
-    filterForRemoval(m_modalNodesSet, document, nodesToRemove);
-    filterForRemoval(m_deferredRecomputeIsIgnoredList, document, nodesToRemove);
-    filterForRemoval(m_deferredTextChangedList, document, nodesToRemove);
-    filterForRemoval(m_deferredSelectedChildredChangedList, document, nodesToRemove);
+    filterListForRemoval(m_textMarkerNodes, document, nodesToRemove);
+    filterListForRemoval(m_modalNodesSet, document, nodesToRemove);
+    filterListForRemoval(m_deferredRecomputeIsIgnoredList, document, nodesToRemove);
+    filterListForRemoval(m_deferredTextChangedList, document, nodesToRemove);
+    filterListForRemoval(m_deferredSelectedChildredChangedList, document, nodesToRemove);
+    filterMapForRemoval(m_deferredTextFormControlValue, document, nodesToRemove);
 
     for (auto* node : nodesToRemove)
         remove(*node);
@@ -2776,6 +2789,12 @@
     for (auto* selectElement : m_deferredSelectedChildredChangedList)
         selectedChildrenChanged(selectElement);
     m_deferredSelectedChildredChangedList.clear();
+
+    for (auto& deferredFormControlContext : m_deferredTextFormControlValue) {
+        auto& textFormControlElement = downcast<HTMLTextFormControlElement>(*deferredFormControlContext.key);
+        postTextReplacementNotificationForTextControl(textFormControlElement, deferredFormControlContext.value, textFormControlElement.innerTextValue());
+    }
+    m_deferredTextFormControlValue.clear();
 }
 
 static bool rendererNeedsDeferredUpdate(RenderObject& renderer)
@@ -2841,6 +2860,14 @@
     selectedChildrenChanged(&selectElement);
 }
 
+void AXObjectCache::deferTextReplacementNotificationForTextControl(HTMLTextFormControlElement& formControlElement, const String& previousValue)
+{
+    auto* renderer = formControlElement.renderer();
+    if (!renderer)
+        return;
+    m_deferredTextFormControlValue.add(&formControlElement, previousValue);
+}
+
 bool isNodeAriaVisible(Node* node)
 {
     if (!node)

Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (225854 => 225855)


--- trunk/Source/WebCore/accessibility/AXObjectCache.h	2017-12-13 18:36:26 UTC (rev 225854)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h	2017-12-13 18:43:05 UTC (rev 225855)
@@ -337,7 +337,8 @@
     void deferTextChangedIfNeeded(Node*);
     void deferSelectedChildrenChangedIfNeeded(Element&);
     void performDeferredCacheUpdate();
-    
+    void deferTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String& previousValue);
+
     RefPtr<Range> rangeMatchesTextNearRange(RefPtr<Range>, const String&);
     
 
@@ -444,6 +445,7 @@
     ListHashSet<Element*> m_deferredRecomputeIsIgnoredList;
     ListHashSet<Node*> m_deferredTextChangedList;
     ListHashSet<Element*> m_deferredSelectedChildredChangedList;
+    HashMap<Element*, String> m_deferredTextFormControlValue;
     bool m_isSynchronizingSelection { false };
     bool m_performingDeferredCacheUpdate { false };
 };
@@ -496,6 +498,7 @@
 inline void AXObjectCache::deferRecomputeIsIgnored(Element*) { }
 inline void AXObjectCache::deferTextChangedIfNeeded(Node*) { }
 inline void AXObjectCache::deferSelectedChildrenChangedIfNeeded(Element&) { }
+inline void AXObjectCache::deferTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String&) { }
 inline void AXObjectCache::detachWrapper(AccessibilityObject*, AccessibilityDetachmentType) { }
 inline void AXObjectCache::focusModalNodeTimerFired() { }
 inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp (225854 => 225855)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2017-12-13 18:36:26 UTC (rev 225854)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2017-12-13 18:43:05 UTC (rev 225855)
@@ -576,7 +576,7 @@
 #if HAVE(ACCESSIBILITY) && PLATFORM(COCOA)
         if (textIsChanged && renderer()) {
             if (AXObjectCache* cache = document().existingAXObjectCache())
-                cache->postTextReplacementNotificationForTextControl(*this, previousValue, value);
+                cache->deferTextReplacementNotificationForTextControl(*this, previousValue);
         }
 #endif
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to