Changeset 200690 in webkit
- Timestamp:
- May 11, 2016, 9:25:53 AM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r200689 r200690 1 2016-05-11 Chris Dumez <cdumez@apple.com> 2 3 Optimize DataDetection's searchForLinkRemovingExistingDDLinks() 4 https://bugs.webkit.org/show_bug.cgi?id=157561 5 6 Reviewed by Ryosuke Niwa. 7 8 Optimize DataDetection's searchForLinkRemovingExistingDDLinks(): 9 1. The first loop was using Node::childNodes() to iterate over the child 10 elements. Because of the recursive call, we may end up prepending 11 children as we iterate over them. This is an issue because the 12 childCount was cached before the loop and vector it would blow away 13 the cache inside the NodeList. Switch to using ElementTraversal which 14 should be both safer and more efficient. I don't believe we can use 15 our nice ElementChildIterator here unfortunately as we would hit 16 assertions due the the DOM mutations while iterating. 17 2. The second loop was using again Node::childNodes() and kept calling 18 item(0) to get the first child and move it to make it the previous 19 sibling of its old parent. Again, using childNodes() here is super 20 inefficient because we keep modifying the children and childNodes() 21 returns a live NodeList. The call to NodeList::length() would cache 22 all the children in a Vector, only to blow that cache away after 23 removing the first child. Switch to using ContainerNode::firstChild(). 24 3. Drop the parentElement parameter as we can just get it from the child. 25 4. Use tighter typing so we don't end up calling the implementations of 26 insertBefore() / removeChild() that are on Node, thus unnecessarily 27 doing a is<ContainerNode>() check every time. 28 5. Pass element by reference instead of pointer as it cannot be null. 29 30 * editing/cocoa/DataDetection.mm: 31 (WebCore::removeResultLinksFromAnchor): 32 (WebCore::searchForLinkRemovingExistingDDLinks): 33 1 34 2016-05-11 Rawinder Singh <rawinder.singh-webkit@cisra.canon.com.au> 2 35 -
trunk/Source/WebCore/editing/cocoa/DataDetection.mm
r200659 r200690 30 30 #import "CSSStyleDeclaration.h" 31 31 #import "DataDetectorsSPI.h" 32 #import "ElementTraversal.h" 32 33 #import "FrameView.h" 33 34 #import "HTMLAnchorElement.h" … … 249 250 } 250 251 251 static void removeResultLinksFromAnchor( Node* node, Node* nodeParent)252 static void removeResultLinksFromAnchor(Element& element) 252 253 { 253 254 // Perform a depth-first search for anchor nodes, which have the DDURLScheme attribute set to true, 254 // take their children and insert them before the anchor, 255 // and then remove the anchor. 256 257 if (!node) 255 // take their children and insert them before the anchor, and then remove the anchor. 256 257 // Note that this is not using ElementChildIterator because we potentially prepend children as we iterate over them. 258 for (auto* child = ElementTraversal::firstChild(element); child; child = ElementTraversal::nextSibling(*child)) 259 removeResultLinksFromAnchor(*child); 260 261 auto* elementParent = element.parentElement(); 262 if (!elementParent) 258 263 return; 259 264 260 BOOL nodeIsDDAnchor = is<HTMLAnchorElement>(*node) && equalIgnoringASCIICase(downcast<Element>(*node).fastGetAttribute(x_apple_data_detectorsAttr), "true"); 261 262 RefPtr<NodeList> children = node->childNodes(); 263 unsigned childCount = children->length(); 264 for (size_t i = 0; i < childCount; i++) { 265 Node* child = children->item(i); 266 if (is<Element>(*child)) 267 removeResultLinksFromAnchor(child, node); 268 } 269 270 if (nodeIsDDAnchor && nodeParent) { 271 children = node->childNodes(); 272 childCount = children->length(); 273 274 // Iterate over the children and move them all onto the same level as this anchor. 275 // Remove the anchor afterwards. 276 for (size_t i = 0; i < childCount; i++) { 277 Node* child = children->item(0); 278 nodeParent->insertBefore(child, node, ASSERT_NO_EXCEPTION); 279 } 280 nodeParent->removeChild(node, ASSERT_NO_EXCEPTION); 281 } 265 bool elementIsDDAnchor = is<HTMLAnchorElement>(element) && equalIgnoringASCIICase(element.fastGetAttribute(x_apple_data_detectorsAttr), "true"); 266 if (!elementIsDDAnchor) 267 return; 268 269 // Iterate over the children and move them all onto the same level as this anchor. Remove the anchor afterwards. 270 while (auto* child = element.firstChild()) 271 elementParent->insertBefore(*child, &element); 272 273 elementParent->removeChild(element); 282 274 } 283 275 … … 288 280 while (node) { 289 281 if (is<HTMLAnchorElement>(*node)) { 290 if (!equalIgnoringASCIICase(downcast<Element>(*node).fastGetAttribute(x_apple_data_detectorsAttr), "true")) 282 auto& anchor = downcast<HTMLAnchorElement>(*node); 283 if (!equalIgnoringASCIICase(anchor.fastGetAttribute(x_apple_data_detectorsAttr), "true")) 291 284 return true; 292 removeResultLinksFromAnchor( node, node->parentElement());285 removeResultLinksFromAnchor(anchor); 293 286 didModifyDOM = true; 294 287 } … … 300 293 while (node) { 301 294 if (is<HTMLAnchorElement>(*node)) { 302 if (!equalIgnoringASCIICase(downcast<Element>(*node).fastGetAttribute(x_apple_data_detectorsAttr), "true")) 295 auto& anchor = downcast<HTMLAnchorElement>(*node); 296 if (!equalIgnoringASCIICase(anchor.fastGetAttribute(x_apple_data_detectorsAttr), "true")) 303 297 return true; 304 removeResultLinksFromAnchor( node, node->parentElement());298 removeResultLinksFromAnchor(anchor); 305 299 didModifyDOM = true; 306 300 }
Note:
See TracChangeset
for help on using the changeset viewer.