Changeset 212151 in webkit
- Timestamp:
- Feb 10, 2017 2:36:12 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/PerformanceTests/ChangeLog
r212129 r212151 1 2017-02-10 Zalan Bujtas <zalan@apple.com> 2 3 Mail hangs when removing multiple rows from large table. 4 https://bugs.webkit.org/show_bug.cgi?id=168103 5 <rdar://problem/30090186> 6 7 Reviewed by Ryosuke Niwa. 8 9 * DOM/large-table-edit.html: Added. 10 1 11 2017-02-05 Filip Pizlo <fpizlo@apple.com> 2 12 -
trunk/Source/WebCore/ChangeLog
r212150 r212151 1 2017-02-10 Zalan Bujtas <zalan@apple.com> 2 3 Mail hangs when removing multiple rows from large table. 4 https://bugs.webkit.org/show_bug.cgi?id=168103 5 <rdar://problem/30090186> 6 7 Reviewed by Ryosuke Niwa. 8 9 DeleteSelectionCommand::removeNode doesn't actually destroy table structure items, 10 but instead it removes their content. In order to be able to continue editing the table after 11 the delete, we need to ensure that its cells' width and height are > 0. Currently we issue layout on 12 each table item recursively. 13 This patch delays the layout until after we've finished with the entire subtree delete (10x progression). 14 15 Performance test added. 16 17 * editing/DeleteSelectionCommand.cpp: 18 (WebCore::DeleteSelectionCommand::insertBlockPlaceholderForTableCellIfNeeded): 19 (WebCore::DeleteSelectionCommand::removeNodeUpdatingStates): 20 (WebCore::shouldRemoveContentOnly): 21 (WebCore::DeleteSelectionCommand::removeNode): 22 * editing/DeleteSelectionCommand.h: 23 1 24 2017-02-10 Joseph Pecoraro <pecoraro@apple.com> 2 25 -
trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp
r211591 r212151 31 31 #include "Editor.h" 32 32 #include "EditorClient.h" 33 #include "ElementIterator.h" 33 34 #include "Frame.h" 34 35 #include "HTMLBRElement.h" … … 343 344 next = NodeTraversal::next(*next, node); 344 345 return next ? firstPositionInOrBeforeNode(next) : Position(); 346 } 347 348 void DeleteSelectionCommand::insertBlockPlaceholderForTableCellIfNeeded(Element& element) 349 { 350 // Make sure empty cell has some height. 351 auto* renderer = element.renderer(); 352 if (!is<RenderTableCell>(renderer)) 353 return; 354 if (downcast<RenderTableCell>(*renderer).contentHeight() > 0) 355 return; 356 insertBlockPlaceholder(firstEditablePositionInNode(&element)); 357 } 358 359 void DeleteSelectionCommand::removeNodeUpdatingStates(Node& node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) 360 { 361 if (&node == m_startBlock && !isEndOfBlock(VisiblePosition(firstPositionInNode(m_startBlock.get())).previous())) 362 m_needPlaceholder = true; 363 else if (&node == m_endBlock && !isStartOfBlock(VisiblePosition(lastPositionInNode(m_startBlock.get())).next())) 364 m_needPlaceholder = true; 365 366 // FIXME: Update the endpoints of the range being deleted. 367 updatePositionForNodeRemoval(m_endingPosition, node); 368 updatePositionForNodeRemoval(m_leadingWhitespace, node); 369 updatePositionForNodeRemoval(m_trailingWhitespace, node); 370 371 CompositeEditCommand::removeNode(&node, shouldAssumeContentIsAlwaysEditable); 372 } 373 374 static inline bool shouldRemoveContentOnly(const Node& node) 375 { 376 return isTableStructureNode(&node) || node.isRootEditableElement(); 345 377 } 346 378 … … 372 404 } 373 405 374 if ( isTableStructureNode(node.get()) || node->isRootEditableElement()) {406 if (shouldRemoveContentOnly(*node)) { 375 407 // Do not remove an element of table structure; remove its contents. 376 408 // Likewise for the root editable element. 377 Node* child = node->firstChild();409 auto* child = NodeTraversal::next(*node, node.get()); 378 410 while (child) { 379 Node* remove = child; 380 child = child->nextSibling(); 381 removeNode(remove, shouldAssumeContentIsAlwaysEditable); 382 } 383 384 // Make sure empty cell has some height, if a placeholder can be inserted. 411 if (shouldRemoveContentOnly(*child)) { 412 child = NodeTraversal::next(*child, node.get()); 413 continue; 414 } 415 auto* remove = child; 416 child = NodeTraversal::nextSkippingChildren(*child, node.get()); 417 removeNodeUpdatingStates(*remove, shouldAssumeContentIsAlwaysEditable); 418 } 419 420 ASSERT(is<Element>(*node)); 421 auto& element = downcast<Element>(*node); 385 422 document().updateLayoutIgnorePendingStylesheets(); 386 RenderObject* renderer = node->renderer(); 387 if (is<RenderTableCell>(renderer) && downcast<RenderTableCell>(*renderer).contentHeight() <= 0) { 388 Position firstEditablePosition = firstEditablePositionInNode(node.get()); 389 if (firstEditablePosition.isNotNull()) 390 insertBlockPlaceholder(firstEditablePosition); 391 } 392 return; 393 } 394 395 if (node == m_startBlock && !isEndOfBlock(VisiblePosition(firstPositionInNode(m_startBlock.get())).previous())) 396 m_needPlaceholder = true; 397 else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(lastPositionInNode(m_startBlock.get())).next())) 398 m_needPlaceholder = true; 399 400 // FIXME: Update the endpoints of the range being deleted. 401 updatePositionForNodeRemoval(m_endingPosition, *node); 402 updatePositionForNodeRemoval(m_leadingWhitespace, *node); 403 updatePositionForNodeRemoval(m_trailingWhitespace, *node); 404 405 CompositeEditCommand::removeNode(node, shouldAssumeContentIsAlwaysEditable); 423 // Check if we need to insert a placeholder for descendant table cells. 424 auto* descendant = ElementTraversal::next(element, &element); 425 while (descendant) { 426 auto* placeholderCandidate = descendant; 427 descendant = ElementTraversal::next(*descendant, &element); 428 insertBlockPlaceholderForTableCellIfNeeded(*placeholderCandidate); 429 } 430 insertBlockPlaceholderForTableCellIfNeeded(element); 431 return; 432 } 433 removeNodeUpdatingStates(*node, shouldAssumeContentIsAlwaysEditable); 406 434 } 407 435 -
trunk/Source/WebCore/editing/DeleteSelectionCommand.h
r209871 r212151 74 74 String originalStringForAutocorrectionAtBeginningOfSelection(); 75 75 76 void removeNodeUpdatingStates(Node&, ShouldAssumeContentIsAlwaysEditable); 77 void insertBlockPlaceholderForTableCellIfNeeded(Element&); 78 76 79 bool m_hasSelectionToDelete; 77 80 bool m_smartDelete;
Note: See TracChangeset
for help on using the changeset viewer.