Changeset 276563 in webkit
- Timestamp:
- Apr 24, 2021, 10:59:59 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
editing/DeleteSelectionCommand.cpp (modified) (27 diffs)
-
editing/Editing.cpp (modified) (2 diffs)
-
editing/Editing.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r276562 r276563 1 2021-04-24 Ryosuke Niwa <rniwa@webkit.org> 2 3 Deploy Ref/RefPtr in DeleteSelectionCommand 4 https://bugs.webkit.org/show_bug.cgi?id=225028 5 6 Reviewed by Wenson Hsieh. 7 8 Deployed smart pointers in DeleteSelectionCommand. 9 10 Also deployed ScriptDisallowedScope around the code which accesses the render tree. 11 12 No new tests since there should be no observable behavioral differences. 13 14 * editing/DeleteSelectionCommand.cpp: 15 (WebCore::isTableRowEmpty): 16 (WebCore::isSpecialHTMLElement): Moved from Editing.cpp. 17 (WebCore::firstInSpecialElement): Ditto. 18 (WebCore::lastInSpecialElement): Ditto. 19 (WebCore::positionBeforeContainingSpecialElement): Ditto. Now returns a pair instead of returning 20 Position and "returning" the special element via an out argument. 21 (WebCore::positionAfterContainingSpecialElement): Ditto. 22 (WebCore::DeleteSelectionCommand::initializeStartEnd): 23 (WebCore::DeleteSelectionCommand::initializePositionData): 24 (WebCore::DeleteSelectionCommand::handleSpecialCaseBRDelete): 25 (WebCore::firstEditablePositionInNode): 26 (WebCore::DeleteSelectionCommand::insertBlockPlaceholderForTableCellIfNeeded): 27 (WebCore::DeleteSelectionCommand::removeNode): 28 (WebCore::DeleteSelectionCommand::handleGeneralDelete): 29 (WebCore::DeleteSelectionCommand::mergeParagraphs): 30 (WebCore::DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows): 31 (WebCore::DeleteSelectionCommand::originalStringForAutocorrectionAtBeginningOfSelection): 32 (WebCore::DeleteSelectionCommand::doApply): 33 * editing/Editing.cpp: 34 (WebCore::isRenderedTable): Return false when the node is not a HTMLElement for consistency. 35 (WebCore::isSpecialHTMLElement): Moved to DeleteSelectionCommand.cpp. 36 (WebCore::firstInSpecialElement): Ditto. 37 (WebCore::lastInSpecialElement): Ditto. 38 (WebCore::positionBeforeContainingSpecialElement): Ditto. 39 (WebCore::positionAfterContainingSpecialElement): Ditto. 40 * editing/Editing.h: 41 1 42 2021-04-24 Tim Horton <timothy_horton@apple.com> 2 43 -
trunk/Source/WebCore/editing/DeleteSelectionCommand.cpp
r276317 r276563 44 44 #include "RenderText.h" 45 45 #include "RenderedDocumentMarker.h" 46 #include "ScriptDisallowedScope.h" 46 47 #include "Text.h" 47 48 #include "VisibleUnits.h" … … 66 67 if (!isTableRow(row)) 67 68 return false; 68 69 for ( Node* child = row->firstChild(); child; child = child->nextSibling())70 if (isTableCell(child ) && !isTableCellEmpty(child))69 70 for (auto child = makeRefPtr(row->firstChild()); child; child = child->nextSibling()) { 71 if (isTableCell(child.get()) && !isTableCellEmpty(child.get())) 71 72 return false; 72 73 } 74 73 75 return true; 76 } 77 78 static bool isSpecialHTMLElement(const Node& node) 79 { 80 ScriptDisallowedScope scriptDisallowedScope; 81 82 if (!is<HTMLElement>(node)) 83 return false; 84 85 if (downcast<HTMLElement>(node).isLink()) 86 return true; 87 88 auto* renderer = downcast<HTMLElement>(node).renderer(); 89 if (!renderer) 90 return false; 91 92 if (renderer->style().display() == DisplayType::Table || renderer->style().display() == DisplayType::InlineTable) 93 return true; 94 95 if (renderer->style().isFloating()) 96 return true; 97 98 if (renderer->style().position() != PositionType::Static) 99 return true; 100 101 return false; 102 } 103 104 static RefPtr<HTMLElement> firstInSpecialElement(const Position& position) 105 { 106 auto rootEditableElement = makeRefPtr(position.rootEditableElement()); 107 for (auto node = makeRefPtr(position.deprecatedNode()); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) { 108 if (!isSpecialHTMLElement(*node)) 109 continue; 110 VisiblePosition visiblePosition = position; 111 VisiblePosition firstInElement = firstPositionInOrBeforeNode(node.get()); 112 if ((isRenderedTable(node.get()) && visiblePosition == firstInElement.next()) || visiblePosition == firstInElement) { 113 RELEASE_ASSERT(is<HTMLElement>(node)); 114 return static_pointer_cast<HTMLElement>(node); 115 } 116 } 117 return nullptr; 118 } 119 120 static RefPtr<HTMLElement> lastInSpecialElement(const Position& position) 121 { 122 auto rootEditableElement = makeRefPtr(position.rootEditableElement()); 123 for (auto node = makeRefPtr(position.deprecatedNode()); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) { 124 if (!isSpecialHTMLElement(*node)) 125 continue; 126 VisiblePosition visiblePosition = position; 127 VisiblePosition lastInElement = lastPositionInOrAfterNode(node.get()); 128 if ((isRenderedTable(node.get()) && visiblePosition == lastInElement.previous()) || visiblePosition == lastInElement) { 129 RELEASE_ASSERT(is<HTMLElement>(node)); 130 return static_pointer_cast<HTMLElement>(node); 131 } 132 } 133 return nullptr; 134 } 135 136 static std::pair<Position, RefPtr<HTMLElement>> positionBeforeContainingSpecialElement(const Position& position) 137 { 138 auto element = firstInSpecialElement(position); 139 if (!element) 140 return { position, nullptr }; 141 auto result = positionInParentBeforeNode(element.get()); 142 if (result.isNull() || result.containerNode()->rootEditableElement() != position.containerNode()->rootEditableElement()) 143 return { position, nullptr }; 144 return { result, WTFMove(element) }; 145 } 146 147 static std::pair<Position, RefPtr<HTMLElement>> positionAfterContainingSpecialElement(const Position& position) 148 { 149 auto element = lastInSpecialElement(position); 150 if (!element) 151 return { position, nullptr }; 152 auto result = positionInParentAfterNode(element.get()); 153 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != position.containerNode()->rootEditableElement()) 154 return { position, nullptr }; 155 return { result, WTFMove(element) }; 74 156 } 75 157 … … 104 186 105 187 void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end) 106 { 107 HTMLElement* startSpecialContainer = nullptr; 108 HTMLElement* endSpecialContainer = nullptr; 109 188 { 110 189 start = m_selectionToDelete.start(); 111 190 end = m_selectionToDelete.end(); … … 123 202 124 203 while (1) { 125 startSpecialContainer = nullptr; 126 endSpecialContainer = nullptr; 127 128 Position s = positionBeforeContainingSpecialElement(start, &startSpecialContainer); 129 Position e = positionAfterContainingSpecialElement(end, &endSpecialContainer); 130 204 auto [startBeforeSpecialElement, startSpecialContainer] = positionBeforeContainingSpecialElement(start); 205 auto [endAfterSpecialElement, endSpecialContainer] = positionAfterContainingSpecialElement(end); 206 131 207 if (!startSpecialContainer && !endSpecialContainer) 132 208 break; … … 138 214 139 215 // If we're going to expand to include the startSpecialContainer, it must be fully selected. 140 if (startSpecialContainer && !endSpecialContainer && positionInParentAfterNode(startSpecialContainer ) >= end)216 if (startSpecialContainer && !endSpecialContainer && positionInParentAfterNode(startSpecialContainer.get()) >= end) 141 217 break; 142 218 143 219 // If we're going to expand to include the endSpecialContainer, it must be fully selected. 144 if (endSpecialContainer && !startSpecialContainer && start >= positionInParentBeforeNode(endSpecialContainer ))220 if (endSpecialContainer && !startSpecialContainer && start >= positionInParentBeforeNode(endSpecialContainer.get())) 145 221 break; 146 222 147 if (startSpecialContainer && startSpecialContainer->isDescendantOf(endSpecialContainer ))223 if (startSpecialContainer && startSpecialContainer->isDescendantOf(endSpecialContainer.get())) { 148 224 // Don't adjust the end yet, it is the end of a special element that contains the start 149 225 // special element (which may or may not be fully selected). 150 start = s ;151 else if (endSpecialContainer && endSpecialContainer->isDescendantOf(startSpecialContainer))226 start = startBeforeSpecialElement; 227 } else if (endSpecialContainer && endSpecialContainer->isDescendantOf(startSpecialContainer.get())) { 152 228 // Don't adjust the start yet, it is the start of a special element that contains the end 153 229 // special element (which may or may not be fully selected). 154 end = e ;155 else {156 start = s ;157 end = e ;230 end = endAfterSpecialElement; 231 } else { 232 start = startBeforeSpecialElement; 233 end = endAfterSpecialElement; 158 234 } 159 235 } … … 246 322 // If the cell is non-editable, enclosingNodeOfType won't return it by default, so 247 323 // tell that function that we don't care if it returns non-editable nodes. 248 Node* startCell = enclosingNodeOfType(m_upstreamStart, &isTableCell, CanCrossEditingBoundary);249 Node* endCell = enclosingNodeOfType(m_downstreamEnd, &isTableCell, CanCrossEditingBoundary);324 auto startCell = makeRefPtr(enclosingNodeOfType(m_upstreamStart, &isTableCell, CanCrossEditingBoundary)); 325 auto endCell = makeRefPtr(enclosingNodeOfType(m_downstreamEnd, &isTableCell, CanCrossEditingBoundary)); 250 326 // FIXME: This isn't right. A borderless table with two rows and a single column would appear as two paragraphs. 251 327 if (endCell && endCell != startCell) … … 359 435 bool DeleteSelectionCommand::handleSpecialCaseBRDelete() 360 436 { 361 Node* nodeAfterUpstreamStart = m_upstreamStart.computeNodeAfterPosition();362 Node* nodeAfterDownstreamStart = m_downstreamStart.computeNodeAfterPosition();437 auto nodeAfterUpstreamStart = makeRefPtr(m_upstreamStart.computeNodeAfterPosition()); 438 auto nodeAfterDownstreamStart = makeRefPtr(m_downstreamStart.computeNodeAfterPosition()); 363 439 // Upstream end will appear before BR due to canonicalization 364 Node* nodeAfterUpstreamEnd = m_upstreamEnd.computeNodeAfterPosition();440 auto nodeAfterUpstreamEnd = makeRefPtr(m_upstreamEnd.computeNodeAfterPosition()); 365 441 366 442 if (!nodeAfterUpstreamStart || !nodeAfterDownstreamStart) … … 382 458 // We detect the case where the start is an empty line consisting of BR not wrapped in a block element. 383 459 if (upstreamStartIsBR && downstreamStartIsBR 384 && !(isStartOfBlock(positionBeforeNode(nodeAfterUpstreamStart )) && isEndOfBlock(positionAfterNode(nodeAfterDownstreamStart)))460 && !(isStartOfBlock(positionBeforeNode(nodeAfterUpstreamStart.get())) && isEndOfBlock(positionAfterNode(nodeAfterDownstreamStart.get()))) 385 461 && (!nodeAfterUpstreamEnd || nodeAfterUpstreamEnd->hasTagName(brTag) || nodeAfterUpstreamEnd->previousSibling() != nodeAfterUpstreamStart)) { 386 462 m_startsAtEmptyLine = true; … … 394 470 { 395 471 ASSERT(node); 396 Node* next = node;472 auto next = makeRefPtr(node); 397 473 while (next && !next->hasEditableStyle()) 398 474 next = NodeTraversal::next(*next, node); 399 return next ? firstPositionInOrBeforeNode(next ) : Position();475 return next ? firstPositionInOrBeforeNode(next.get()) : Position(); 400 476 } 401 477 … … 403 479 { 404 480 // Make sure empty cell has some height. 405 auto* renderer = element.renderer(); 406 if (!is<RenderTableCell>(renderer)) 407 return; 408 if (downcast<RenderTableCell>(*renderer).contentHeight() > 0) 409 return; 481 { 482 ScriptDisallowedScope scriptDisallowedScope; 483 auto* renderer = element.renderer(); 484 if (!is<RenderTableCell>(renderer)) 485 return; 486 if (downcast<RenderTableCell>(*renderer).contentHeight() > 0) 487 return; 488 } 410 489 insertBlockPlaceholder(firstEditablePositionInNode(&element)); 411 490 } … … 441 520 return; 442 521 // Search this non-editable region for editable regions to empty. 443 RefPtr<Node> child = node.firstChild();522 auto child = makeRefPtr(node.firstChild()); 444 523 while (child) { 445 RefPtr<Node> nextChild = child->nextSibling();524 auto nextChild = makeRefPtr(child->nextSibling()); 446 525 removeNode(*child, shouldAssumeContentIsAlwaysEditable); 447 526 // Bail if nextChild is no longer node's child. 448 527 if (nextChild && nextChild->parentNode() != &node) 449 528 return; 450 child = nextChild;529 child = WTFMove(nextChild); 451 530 } 452 531 … … 459 538 // Do not remove an element of table structure; remove its contents. 460 539 // Likewise for the root editable element. 461 auto * child = NodeTraversal::next(node, &node);540 auto child = makeRefPtr(NodeTraversal::next(node, &node)); 462 541 while (child) { 463 542 if (shouldRemoveContentOnly(*child)) { … … 465 544 continue; 466 545 } 467 auto * remove = child;468 child = NodeTraversal::nextSkippingChildren(*child, &node);469 removeNodeUpdatingStates(*remove, shouldAssumeContentIsAlwaysEditable);546 auto nextChild = makeRefPtr(NodeTraversal::nextSkippingChildren(*child, &node)); 547 removeNodeUpdatingStates(*child, shouldAssumeContentIsAlwaysEditable); 548 child = WTFMove(nextChild); 470 549 } 471 550 … … 474 553 document().updateLayoutIgnorePendingStylesheets(); 475 554 // Check if we need to insert a placeholder for descendant table cells. 476 auto * descendant = ElementTraversal::next(element, &element);555 auto descendant = makeRefPtr(ElementTraversal::next(element, &element)); 477 556 while (descendant) { 478 auto * placeholderCandidate = descendant;479 descendant = ElementTraversal::next(*descendant, &element);480 insertBlockPlaceholderForTableCellIfNeeded(*placeholderCandidate);557 auto nextDescendant = makeRefPtr(ElementTraversal::next(*descendant, &element)); 558 insertBlockPlaceholderForTableCellIfNeeded(*descendant); 559 descendant = WTFMove(nextDescendant); 481 560 } 482 561 insertBlockPlaceholderForTableCellIfNeeded(element); … … 536 615 537 616 int startOffset = m_upstreamStart.deprecatedEditingOffset(); 538 Node* startNode = m_upstreamStart.deprecatedNode();539 617 auto startNode = makeRefPtr(m_upstreamStart.deprecatedNode()); 618 540 619 makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(); 541 620 … … 583 662 bool startNodeWasDescendantOfEndNode = m_upstreamStart.deprecatedNode()->isDescendantOf(m_downstreamEnd.deprecatedNode()); 584 663 // The selection to delete spans more than one node. 585 RefPtr<Node> node(startNode);664 auto node = startNode.copyRef(); 586 665 587 666 if (startOffset > 0) { 588 if (is<Text>(* startNode)) {667 if (is<Text>(*node)) { 589 668 // in a text node that needs to be trimmed 590 Text& text = downcast<Text>(* node);669 Text& text = downcast<Text>(*startNode); 591 670 deleteTextFromNode(text, startOffset, text.length() - startOffset); 592 node = NodeTraversal::next(* node);671 node = NodeTraversal::next(*startNode); 593 672 } else { 594 673 node = startNode->traverseToChildAt(startOffset); 595 674 } 596 675 } else if (startNode == m_upstreamEnd.deprecatedNode() && is<Text>(*startNode)) { 597 Text& text = downcast<Text>(* m_upstreamEnd.deprecatedNode());676 Text& text = downcast<Text>(*startNode); 598 677 deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset()); 599 678 } … … 612 691 node = nextNode.get(); 613 692 } else { 614 Node* n = node->lastDescendant();615 if (m_downstreamEnd.deprecatedNode() == n && m_downstreamEnd.deprecatedEditingOffset() >= caretMaxOffset(*n)) {693 auto lastDescendant = makeRefPtr(node->lastDescendant()); 694 if (m_downstreamEnd.deprecatedNode() == lastDescendant && m_downstreamEnd.deprecatedEditingOffset() >= caretMaxOffset(*lastDescendant)) { 616 695 removeNode(*node); 617 696 node = nullptr; … … 631 710 // in a text node that needs to be trimmed 632 711 Text& text = downcast<Text>(*m_downstreamEnd.deprecatedNode()); 633 if (m_downstreamEnd.deprecatedEditingOffset() > 0) {712 if (m_downstreamEnd.deprecatedEditingOffset() > 0) 634 713 deleteTextFromNode(text, 0, m_downstreamEnd.deprecatedEditingOffset()); 635 }636 714 // Remove children of m_downstreamEnd.deprecatedNode() that come after m_upstreamStart. 637 715 // Don't try to remove children if m_upstreamStart was inside m_downstreamEnd.deprecatedNode() … … 643 721 unsigned offset = 0; 644 722 if (m_upstreamStart.deprecatedNode()->isDescendantOf(m_downstreamEnd.deprecatedNode())) { 645 Node* n = m_upstreamStart.deprecatedNode();723 auto n = makeRefPtr(m_upstreamStart.deprecatedNode()); 646 724 while (n && n->parentNode() != m_downstreamEnd.deprecatedNode()) 647 725 n = n->parentNode(); … … 703 781 // m_downstreamEnd's block has been emptied out by deletion. There is no content inside of it to 704 782 // move, so just remove it. 705 Element* endBlock = enclosingBlock(m_downstreamEnd.deprecatedNode());783 auto endBlock = makeRefPtr(enclosingBlock(m_downstreamEnd.deprecatedNode())); 706 784 if (!endBlock) 707 785 return; … … 730 808 if (!m_startsAtEmptyLine && isStartOfParagraph(mergeDestination) && startOfParagraphToMove.absoluteCaretBounds().x() > mergeDestination.absoluteCaretBounds().x()) { 731 809 if (mergeDestination.deepEquivalent().downstream().deprecatedNode()->hasTagName(brTag)) { 732 removeNodeAndPruneAncestors(*mergeDestination.deepEquivalent().downstream().deprecatedNode()); 810 auto nodeToRemove = makeRefPtr(mergeDestination.deepEquivalent().downstream().deprecatedNode()); 811 removeNodeAndPruneAncestors(*nodeToRemove); 733 812 m_endingPosition = startOfParagraphToMove.deepEquivalent(); 734 813 return; … … 769 848 { 770 849 if (m_endTableRow && m_endTableRow->isConnected() && m_endTableRow != m_startTableRow) { 771 Node* row = m_endTableRow->previousSibling();850 auto row = makeRefPtr(m_endTableRow->previousSibling()); 772 851 while (row && row != m_startTableRow) { 773 RefPtr<Node> previousRow = row->previousSibling();774 if (isTableRowEmpty(row ))852 auto previousRow = makeRefPtr(row->previousSibling()); 853 if (isTableRowEmpty(row.get())) { 775 854 // Use a raw removeNode, instead of DeleteSelectionCommand's, because 776 855 // that won't remove rows, it only empties them in preparation for this function. 777 856 CompositeEditCommand::removeNode(*row); 778 row = previousRow.get(); 857 } 858 row = WTFMove(previousRow); 779 859 } 780 860 } … … 782 862 // Remove empty rows after the start row. 783 863 if (m_startTableRow && m_startTableRow->isConnected() && m_startTableRow != m_endTableRow) { 784 Node* row = m_startTableRow->nextSibling();864 auto row = makeRefPtr(m_startTableRow->nextSibling()); 785 865 while (row && row != m_endTableRow) { 786 RefPtr<Node> nextRow = row->nextSibling();787 if (isTableRowEmpty(row ))866 auto nextRow = makeRefPtr(row->nextSibling()); 867 if (isTableRowEmpty(row.get())) 788 868 CompositeEditCommand::removeNode(*row); 789 row = nextRow.get();869 row = WTFMove(nextRow); 790 870 } 791 871 } … … 855 935 return String(); 856 936 937 ScriptDisallowedScope scriptDisallowedScope; 857 938 for (auto* marker : document().markers().markersInRange(*rangeOfFirstCharacter, DocumentMarker::Autocorrected)) { 858 939 int startOffset = marker->startOffset(); … … 897 978 // If the deletion is occurring in a text field, and we're not deleting to replace the selection, then let the frame call across the bridge to notify the form delegate. 898 979 if (!m_replace) { 899 Element* textControl = enclosingTextFormControl(m_selectionToDelete.start()); 900 if (textControl && textControl->focused()) 901 document().editor().textWillBeDeletedInTextField(textControl); 980 if (auto textControl = makeRefPtr(enclosingTextFormControl(m_selectionToDelete.start())); textControl && textControl->focused()) 981 document().editor().textWillBeDeletedInTextField(textControl.get()); 902 982 } 903 983 … … 913 993 // and ends inside it (we do need placeholders to hold open empty cells, but that's 914 994 // handled elsewhere). 915 if (auto * table = isLastPositionBeforeTable(m_selectionToDelete.visibleStart())) {995 if (auto table = makeRefPtr(isLastPositionBeforeTable(m_selectionToDelete.visibleStart()))) { 916 996 if (m_selectionToDelete.end().deprecatedNode()->isDescendantOf(*table)) 917 997 m_needPlaceholder = false; … … 962 1042 bool shouldRebalaceWhiteSpace = true; 963 1043 if (!document().editor().behavior().shouldRebalanceWhiteSpacesInSecureField()) { 964 Node* node = m_endingPosition.deprecatedNode();965 if (is<Text>(node)) {966 Text& textNode = downcast<Text>(*node);1044 if (auto endNode = makeRefPtr(m_endingPosition.deprecatedNode()); is<Text>(endNode)) { 1045 auto& textNode = downcast<Text>(*endNode); 1046 ScriptDisallowedScope scriptDisallowedScope; 967 1047 if (textNode.length() && textNode.renderer()) 968 1048 shouldRebalaceWhiteSpace = textNode.renderer()->style().textSecurity() == TextSecurity::None; -
trunk/Source/WebCore/editing/Editing.cpp
r274626 r276563 404 404 } 405 405 406 static bool isSpecialHTMLElement(const Node* node)407 {408 if (!is<HTMLElement>(node))409 return false;410 411 if (downcast<HTMLElement>(*node).isLink())412 return true;413 414 auto* renderer = downcast<HTMLElement>(*node).renderer();415 if (!renderer)416 return false;417 418 if (renderer->style().display() == DisplayType::Table || renderer->style().display() == DisplayType::InlineTable)419 return true;420 421 if (renderer->style().isFloating())422 return true;423 424 if (renderer->style().position() != PositionType::Static)425 return true;426 427 return false;428 }429 430 static HTMLElement* firstInSpecialElement(const Position& position)431 {432 auto* rootEditableElement = position.containerNode()->rootEditableElement();433 for (Node* node = position.deprecatedNode(); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) {434 if (!isSpecialHTMLElement(node))435 continue;436 VisiblePosition vPos(position);437 VisiblePosition firstInElement(firstPositionInOrBeforeNode(node));438 if ((isRenderedTable(node) && vPos == firstInElement.next()) || vPos == firstInElement)439 return &downcast<HTMLElement>(*node);440 }441 return nullptr;442 }443 444 static HTMLElement* lastInSpecialElement(const Position& position)445 {446 auto* rootEditableElement = position.containerNode()->rootEditableElement();447 for (Node* node = position.deprecatedNode(); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) {448 if (!isSpecialHTMLElement(node))449 continue;450 VisiblePosition vPos(position);451 VisiblePosition lastInElement(lastPositionInOrAfterNode(node));452 if ((isRenderedTable(node) && vPos == lastInElement.previous()) || vPos == lastInElement)453 return &downcast<HTMLElement>(*node);454 }455 return nullptr;456 }457 458 Position positionBeforeContainingSpecialElement(const Position& position, HTMLElement** containingSpecialElement)459 {460 auto* element = firstInSpecialElement(position);461 if (!element)462 return position;463 Position result = positionInParentBeforeNode(element);464 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != position.deprecatedNode()->rootEditableElement())465 return position;466 if (containingSpecialElement)467 *containingSpecialElement = element;468 return result;469 }470 471 Position positionAfterContainingSpecialElement(const Position& position, HTMLElement** containingSpecialElement)472 {473 auto* element = lastInSpecialElement(position);474 if (!element)475 return position;476 Position result = positionInParentAfterNode(element);477 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != position.deprecatedNode()->rootEditableElement())478 return position;479 if (containingSpecialElement)480 *containingSpecialElement = element;481 return result;482 }483 484 406 Element* isFirstPositionAfterTable(const VisiblePosition& position) 485 407 { … … 811 733 bool isRenderedTable(const Node* node) 812 734 { 813 if (!is< Element>(node))735 if (!is<HTMLElement>(node)) 814 736 return false; 815 auto* renderer = downcast< Element>(*node).renderer();737 auto* renderer = downcast<HTMLElement>(*node).renderer(); 816 738 return renderer && renderer->isTable(); 817 739 } -
trunk/Source/WebCore/editing/Editing.h
r266487 r276563 119 119 Position previousVisuallyDistinctCandidate(const Position&); 120 120 121 Position positionBeforeContainingSpecialElement(const Position&, HTMLElement** containingSpecialElement = nullptr);122 Position positionAfterContainingSpecialElement(const Position&, HTMLElement** containingSpecialElement = nullptr);123 124 121 Position firstPositionInOrBeforeNode(Node*); 125 122 Position lastPositionInOrAfterNode(Node*);
Note:
See TracChangeset
for help on using the changeset viewer.