Changeset 225613 in webkit
- Timestamp:
- Dec 6, 2017 4:55:01 PM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r225610 r225613 1 2017-12-06 Zalan Bujtas <zalan@apple.com> 2 3 Remove nodes from AXObjectCache when the associated subframe document is getting destroyed. 4 https://bugs.webkit.org/show_bug.cgi?id=180503 5 <rdar://problem/35891328 6 7 Reviewed by Chris Fleizach. 8 9 While AXObjectCache lives on the mainframe's document, it caches nodes from every subframe document. 10 When a node is being destroyed, we deregister it from the AX cache through the Node's destructor. 11 Soon after the document is detached from the frame/frame is detached from the frame tree, this codepath 12 is no longer available (no access to the AXObjectCache object) and from this point we are unable to deregister 13 nodes associated with the current document. 14 In AXObjectCache::prepareForDocumentDestruction(), we preemptively remove all the cached nodes associated 15 with the about-to-be-destroyed document. 16 17 Covered by existing tests. 18 19 * accessibility/AXObjectCache.cpp: 20 (WebCore::AXObjectCache::remove): 21 (WebCore::filterForRemoval): 22 (WebCore::AXObjectCache::prepareForDocumentDestruction): Collecting the nodes and removing them later is 23 not the most performant way but in order to have a single code path for the de-registration (AXObjectCache::remove) 24 I think it's worth going down the slower path -which should not really be that slower anyway since those 25 lists tend to stay small. 26 (WebCore::AXObjectCache::clearTextMarkerNodesInUse): Deleted. 27 * accessibility/AXObjectCache.h: 28 (WebCore::AXObjectCache::removeNodeForUse): 29 (WebCore::AXObjectCache::remove): 30 * dom/Document.cpp: 31 (WebCore::Document::prepareForDestruction): 32 * dom/Node.cpp: 33 (WebCore::Node::willBeDeletedFrom): 34 (WebCore::Node::moveNodeToNewDocument): 35 1 36 2017-12-06 Brady Eidson <beidson@apple.com> 2 37 -
trunk/Source/WebCore/accessibility/AXObjectCache.cpp
r225142 r225613 717 717 } 718 718 719 void AXObjectCache::remove(Node* node) 720 { 721 if (!node) 722 return; 723 724 if (is<Element>(*node)) { 725 m_deferredRecomputeIsIgnoredList.remove(downcast<Element>(node)); 726 m_deferredSelectedChildredChangedList.remove(downcast<Element>(node)); 727 } 728 m_deferredTextChangedList.remove(node); 719 void AXObjectCache::remove(Node& node) 720 { 721 if (is<Element>(node)) { 722 m_deferredRecomputeIsIgnoredList.remove(downcast<Element>(&node)); 723 m_deferredSelectedChildredChangedList.remove(downcast<Element>(&node)); 724 } 725 m_deferredTextChangedList.remove(&node); 729 726 removeNodeForUse(node); 730 727 731 remove(m_nodeObjectMapping.take( node));732 733 if (m_currentModalNode == node)728 remove(m_nodeObjectMapping.take(&node)); 729 730 if (m_currentModalNode == &node) 734 731 m_currentModalNode = nullptr; 735 m_modalNodesSet.remove( node);736 737 remove(node ->renderer());732 m_modalNodesSet.remove(&node); 733 734 remove(node.renderer()); 738 735 } 739 736 … … 2729 2726 } 2730 2727 2731 void AXObjectCache::clearTextMarkerNodesInUse(Document* document) 2732 { 2733 if (!document) 2734 return; 2735 2736 // Check each node to see if it's inside the document being deleted, of if it no longer belongs to a document. 2737 HashSet<Node*> nodesToDelete; 2738 for (const auto& node : m_textMarkerNodes) { 2739 if (!node->isConnected() || &(node)->document() == document) 2740 nodesToDelete.add(node); 2741 } 2742 2743 for (const auto& node : nodesToDelete) 2744 m_textMarkerNodes.remove(node); 2728 template<typename T> 2729 static void filterForRemoval(const ListHashSet<T>& list, const Document& document, HashSet<Node*>& nodesToRemove) 2730 { 2731 for (auto* node : list) { 2732 if (node->isConnected() && &node->document() != &document) 2733 continue; 2734 nodesToRemove.add(node); 2735 } 2736 } 2737 2738 void AXObjectCache::prepareForDocumentDestruction(const Document& document) 2739 { 2740 HashSet<Node*> nodesToRemove; 2741 filterForRemoval(m_textMarkerNodes, document, nodesToRemove); 2742 filterForRemoval(m_modalNodesSet, document, nodesToRemove); 2743 filterForRemoval(m_deferredRecomputeIsIgnoredList, document, nodesToRemove); 2744 filterForRemoval(m_deferredTextChangedList, document, nodesToRemove); 2745 filterForRemoval(m_deferredSelectedChildredChangedList, document, nodesToRemove); 2746 2747 for (auto* node : nodesToRemove) 2748 remove(*node); 2745 2749 } 2746 2750 -
trunk/Source/WebCore/accessibility/AXObjectCache.h
r225037 r225613 159 159 160 160 void remove(RenderObject*); 161 void remove(Node *);161 void remove(Node&); 162 162 void remove(Widget*); 163 163 void remove(AXID); … … 321 321 void frameLoadingEventNotification(Frame*, AXLoadingEvent); 322 322 323 void clearTextMarkerNodesInUse(Document*);323 void prepareForDocumentDestruction(const Document&); 324 324 325 325 void startCachingComputedObjectAttributesUntilTreeMutates(); … … 362 362 // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid. 363 363 void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); } 364 void removeNodeForUse(Node * n) { m_textMarkerNodes.remove(n); }364 void removeNodeForUse(Node& n) { m_textMarkerNodes.remove(&n); } 365 365 bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); } 366 366 … … 420 420 HashMap<Widget*, AXID> m_widgetObjectMapping; 421 421 HashMap<Node*, AXID> m_nodeObjectMapping; 422 HashSet<Node*> m_textMarkerNodes;422 ListHashSet<Node*> m_textMarkerNodes; 423 423 std::unique_ptr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache; 424 424 WEBCORE_EXPORT static bool gAccessibilityEnabled; … … 529 529 inline void AXObjectCache::remove(AXID) { } 530 530 inline void AXObjectCache::remove(RenderObject*) { } 531 inline void AXObjectCache::remove(Node *) { }531 inline void AXObjectCache::remove(Node&) { } 532 532 inline void AXObjectCache::remove(Widget*) { } 533 533 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { } -
trunk/Source/WebCore/dom/Document.cpp
r225583 r225613 2340 2340 2341 2341 #if HAVE(ACCESSIBILITY) 2342 // Sub-frames need to cleanup Nodes in the text marker cache when the Document disappears.2343 2342 if (this != &topDocument()) { 2344 if (AXObjectCache* cache = existingAXObjectCache()) 2345 cache->clearTextMarkerNodesInUse(this); 2343 // Let the ax cache know that this subframe goes out of scope. 2344 if (auto* cache = existingAXObjectCache()) 2345 cache->prepareForDocumentDestruction(*this); 2346 2346 } 2347 2347 #endif -
trunk/Source/WebCore/dom/Node.cpp
r225524 r225613 327 327 #endif 328 328 329 if ( AXObjectCache* cache = document.existingAXObjectCache())330 cache->remove( this);329 if (auto* cache = document.existingAXObjectCache()) 330 cache->remove(*this); 331 331 } 332 332 … … 2010 2010 if (AXObjectCache::accessibilityEnabled()) { 2011 2011 if (auto* cache = oldDocument.existingAXObjectCache()) 2012 cache->remove( this);2012 cache->remove(*this); 2013 2013 } 2014 2014
Note: See TracChangeset
for help on using the changeset viewer.