⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 276131 in webkit


Ignore:
Timestamp:
Apr 16, 2021, 3:21:45 AM (5 years ago)
Author:
rniwa@webkit.org
Message:

Deploy Ref/RefPtr/WeakPtr in EditCommand and CompositeEditCommand
https://bugs.webkit.org/show_bug.cgi?id=224659

Reviewed by Antti Koivisto.

Deployed Ref/RefPtr/WeakPtr across CompositeEditCommand and EditCommand.

Also wrapped sections of code that access render tree with ScriptDisallowedScope.

  • editing/CompositeEditCommand.cpp:

(WebCore::postTextStateChangeNotification):
(WebCore::CompositeEditCommand::ensureComposition):
(WebCore::CompositeEditCommand::isRemovableBlock): Let a raw pointer to the parent node here
since the only thing we do is to call hasOneChild on it.
(WebCore::CompositeEditCommand::insertNodeBefore):
(WebCore::CompositeEditCommand::insertNodeAfter):
(WebCore::CompositeEditCommand::insertNodeAt):
(WebCore::CompositeEditCommand::removeChildrenInRange):
(WebCore::CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes):
(WebCore::CompositeEditCommand::positionOutsideTabSpan):
(WebCore::CompositeEditCommand::textNodeForRebalance const): Renamed from canRebalance and
now returns the text node after downcasting so that rebalanceWhitespaceAt doesn't need to have
a lone downcast without a type check.
(WebCore::CompositeEditCommand::rebalanceWhitespaceAt):
(WebCore::CompositeEditCommand::rebalanceWhitespaceOnTextSubstring):
(WebCore::CompositeEditCommand::prepareWhitespaceAtPositionForSplit):
(WebCore::CompositeEditCommand::deleteInsignificantText):
(WebCore::CompositeEditCommand::addBlockPlaceholderIfNeeded):
(WebCore::CompositeEditCommand::cloneParagraphUnderNewElement):
(WebCore::CompositeEditCommand::moveParagraphs):

  • editing/CompositeEditCommand.h:

(WebCore::CompositeEditCommand): Now inherits from CanMakeWeakPtr.
(WebCore::toCompositeEditCommand): Deleted.

  • editing/EditCommand.cpp:

(WebCore::EditCommand::EditCommand): Initialize m_startingSelection and m_endingSelection directly
since setStartingSelection and setEndingSelection now stores "this" pointer in RefPtr.
There is no behavior difference since m_parent and CompositeEditCommand::m_composition if applicable
are both nullptr at this point.
(WebCore::compositionIfPossible):
(WebCore::EditCommand::isEditingTextAreaOrTextInput const): Use enclosingTextFormControl instead
of duplicating the code here.
(WebCore::EditCommand::setStartingSelection):
(WebCore::EditCommand::setEndingSelection):
(WebCore::EditCommand::setParent):
(WebCore::EditCommand::postTextStateChangeNotification):

  • editing/EditCommand.h:

(WebCore::EditCommand::parent const):

  • editing/InsertTextCommand.cpp:

(WebCore::InsertTextCommand::doApply):

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r276124 r276131  
     12021-04-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Deploy Ref/RefPtr/WeakPtr in EditCommand and CompositeEditCommand
     4        https://bugs.webkit.org/show_bug.cgi?id=224659
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Deployed Ref/RefPtr/WeakPtr across CompositeEditCommand and EditCommand.
     9
     10        Also wrapped sections of code that access render tree with ScriptDisallowedScope.
     11
     12        * editing/CompositeEditCommand.cpp:
     13        (WebCore::postTextStateChangeNotification):
     14        (WebCore::CompositeEditCommand::ensureComposition):
     15        (WebCore::CompositeEditCommand::isRemovableBlock): Let a raw pointer to the parent node here
     16        since the only thing we do is to call hasOneChild on it.
     17        (WebCore::CompositeEditCommand::insertNodeBefore):
     18        (WebCore::CompositeEditCommand::insertNodeAfter):
     19        (WebCore::CompositeEditCommand::insertNodeAt):
     20        (WebCore::CompositeEditCommand::removeChildrenInRange):
     21        (WebCore::CompositeEditCommand::replaceElementWithSpanPreservingChildrenAndAttributes):
     22        (WebCore::CompositeEditCommand::positionOutsideTabSpan):
     23        (WebCore::CompositeEditCommand::textNodeForRebalance const): Renamed from canRebalance and
     24        now returns the text node after downcasting so that rebalanceWhitespaceAt doesn't need to have
     25        a lone downcast without a type check.
     26        (WebCore::CompositeEditCommand::rebalanceWhitespaceAt):
     27        (WebCore::CompositeEditCommand::rebalanceWhitespaceOnTextSubstring):
     28        (WebCore::CompositeEditCommand::prepareWhitespaceAtPositionForSplit):
     29        (WebCore::CompositeEditCommand::deleteInsignificantText):
     30        (WebCore::CompositeEditCommand::addBlockPlaceholderIfNeeded):
     31        (WebCore::CompositeEditCommand::cloneParagraphUnderNewElement):
     32        (WebCore::CompositeEditCommand::moveParagraphs):
     33        * editing/CompositeEditCommand.h:
     34        (WebCore::CompositeEditCommand): Now inherits from CanMakeWeakPtr.
     35        (WebCore::toCompositeEditCommand): Deleted.
     36        * editing/EditCommand.cpp:
     37        (WebCore::EditCommand::EditCommand): Initialize m_startingSelection and m_endingSelection directly
     38        since setStartingSelection and setEndingSelection now stores "this" pointer in RefPtr.
     39        There is no behavior difference since m_parent and CompositeEditCommand::m_composition if applicable
     40        are both nullptr at this point.
     41        (WebCore::compositionIfPossible):
     42        (WebCore::EditCommand::isEditingTextAreaOrTextInput const): Use enclosingTextFormControl instead
     43        of duplicating the code here.
     44        (WebCore::EditCommand::setStartingSelection):
     45        (WebCore::EditCommand::setEndingSelection):
     46        (WebCore::EditCommand::setParent):
     47        (WebCore::EditCommand::postTextStateChangeNotification):
     48        * editing/EditCommand.h:
     49        (WebCore::EditCommand::parent const):
     50        * editing/InsertTextCommand.cpp:
     51        (WebCore::InsertTextCommand::doApply):
     52
    1532021-04-16  Youenn Fablet  <youenn@apple.com>
    254
  • trunk/Source/WebCore/editing/CompositeEditCommand.cpp

    r275657 r276131  
    6565#include "ReplaceSelectionCommand.h"
    6666#include "ScopedEventQueue.h"
     67#include "ScriptDisallowedScope.h"
    6768#include "SetNodeAttributeCommand.h"
    6869#include "SplitElementCommand.h"
     
    152153{
    153154    ASSERT(cache);
    154     auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole);
     155    auto node = makeRefPtr(highestEditableRoot(position.deepEquivalent(), HasEditableAXRole));
    155156    if (!node)
    156157        return;
    157158    if (insertedText.length() && deletedText.length())
    158         cache->postTextReplacementNotification(node, AXTextEditTypeDelete, insertedText, AXTextEditTypeInsert, deletedText, position);
     159        cache->postTextReplacementNotification(node.get(), AXTextEditTypeDelete, insertedText, AXTextEditTypeInsert, deletedText, position);
    159160    else if (deletedText.length())
    160         cache->postTextStateChangeNotification(node, AXTextEditTypeInsert, deletedText, position);
     161        cache->postTextStateChangeNotification(node.get(), AXTextEditTypeInsert, deletedText, position);
    161162    else if (insertedText.length())
    162         cache->postTextStateChangeNotification(node, AXTextEditTypeDelete, insertedText, position);
     163        cache->postTextStateChangeNotification(node.get(), AXTextEditTypeDelete, insertedText, position);
    163164}
    164165
     
    442443EditCommandComposition& CompositeEditCommand::ensureComposition()
    443444{
    444     auto* command = this;
     445    auto command = makeRefPtr(this);
    445446    while (auto* parent = command->parent())
    446447        command = parent;
     
    537538{
    538539    ASSERT(node);
     540    // FIXME: We should support other elements that can be removed.
    539541    if (!is<HTMLDivElement>(*node))
    540542        return false;
    541543
    542     Node* parentNode = node->parentNode();
    543     if (parentNode && parentNode->firstChild() != parentNode->lastChild())
     544    auto* parentNode = node->parentNode();
     545    if (!parentNode || !parentNode->hasOneChild())
    544546        return false;
    545547
     
    552554void CompositeEditCommand::insertNodeBefore(Ref<Node>&& insertChild, Node& refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
    553555{
    554     auto* parent = refChild.parentNode();
     556    auto parent = makeRefPtr(refChild.parentNode());
    555557    if (!parent || (!parent->hasEditableStyle() && parent->renderer()))
    556558        return;
     
    560562void CompositeEditCommand::insertNodeAfter(Ref<Node>&& insertChild, Node& refChild)
    561563{
    562     ContainerNode* parent = refChild.parentNode();
     564    auto parent = makeRefPtr(refChild.parentNode());
    563565    if (!parent)
    564566        return;
     
    579581    // likewise for replaced elements, brs, etc.
    580582    Position p = editingPosition.parentAnchoredEquivalent();
    581     Node* refChild = p.deprecatedNode();
     583    auto refChild = makeRefPtr(p.deprecatedNode());
    582584    int offset = p.deprecatedEditingOffset();
    583585   
    584586    if (canHaveChildrenForEditing(*refChild)) {
    585         Node* child = refChild->firstChild();
     587        auto child = makeRefPtr(refChild->firstChild());
    586588        for (int i = 0; child && i < offset; i++)
    587589            child = child->nextSibling();
     
    612614{
    613615    Vector<Ref<Node>> children;
    614     Node* child = node.traverseToChildAt(from);
     616    auto child = makeRefPtr(node.traverseToChildAt(from));
    615617    for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
    616618        children.append(*child);
     
    667669    // reduce the number of edit commands could do so here.
    668670    auto command = ReplaceNodeWithSpanCommand::create(element);
    669     auto* commandPtr = command.ptr();
    670     applyCommandToComposite(WTFMove(command));
     671    applyCommandToComposite(command);
    671672    // Returning a raw pointer here is OK because the command is retained by
    672673    // applyCommandToComposite (thus retaining the span), and the span is also
    673674    // in the DOM tree, and thus alive whie it has a parent.
    674     ASSERT(commandPtr->spanElement()->isConnected());
    675     return commandPtr->spanElement();
     675    ASSERT(command->spanElement()->isConnected());
     676    return command->spanElement();
    676677}
    677678
     
    823824    }
    824825
    825     auto* tabSpan = tabSpanNode(position.containerNode());
     826    auto tabSpan = makeRefPtr(tabSpanNode(position.containerNode()));
    826827
    827828    if (position.offsetInContainerNode() <= caretMinOffset(*position.containerNode()))
    828         return positionInParentBeforeNode(tabSpan);
     829        return positionInParentBeforeNode(tabSpan.get());
    829830
    830831    if (position.offsetInContainerNode() >= caretMaxOffset(*position.containerNode()))
    831         return positionInParentAfterNode(tabSpan);
     832        return positionInParentAfterNode(tabSpan.get());
    832833
    833834    splitTextNodeContainingElement(downcast<Text>(*position.containerNode()), position.offsetInContainerNode());
    834     return positionInParentBeforeNode(tabSpan);
     835    return positionInParentBeforeNode(tabSpan.get());
    835836}
    836837
     
    887888}
    888889
    889 bool CompositeEditCommand::canRebalance(const Position& position) const
    890 {
    891     Node* node = position.containerNode();
     890RefPtr<Text> CompositeEditCommand::textNodeForRebalance(const Position& position) const
     891{
     892    auto node = makeRefPtr(position.containerNode());
    892893    if (position.anchorType() != Position::PositionIsOffsetInAnchor || !is<Text>(node))
    893         return false;
    894 
    895     Text& textNode = downcast<Text>(*node);
    896     if (!textNode.length())
    897         return false;
    898 
    899     node->document().updateStyleIfNeeded();
    900 
    901     RenderObject* renderer = textNode.renderer();
     894        return nullptr;
     895
     896    auto textNode = static_pointer_cast<Text>(std::exchange(node, nullptr));
     897    if (!textNode->length())
     898        return nullptr;
     899
     900    textNode->document().updateStyleIfNeeded();
     901
     902    ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     903
     904    RenderObject* renderer = textNode->renderer();
    902905    if (renderer && !renderer->style().collapseWhiteSpace())
    903         return false;
    904 
    905     return true;
     906        return nullptr;
     907
     908    return textNode;
    906909}
    907910
     
    909912void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
    910913{
    911     Node* node = position.containerNode();
    912     if (!canRebalance(position))
     914    auto textNode = textNodeForRebalance(position);
     915    if (!textNode)
    913916        return;
    914917
    915918    // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
    916919    int offset = position.deprecatedEditingOffset();
    917     String text = downcast<Text>(*node).data();
     920    String text = textNode->data();
    918921    if (!deprecatedIsEditingWhitespace(text[offset])) {
    919922        offset--;
     
    922925    }
    923926
    924     rebalanceWhitespaceOnTextSubstring(downcast<Text>(*node), position.offsetInContainerNode(), position.offsetInContainerNode());
     927    rebalanceWhitespaceOnTextSubstring(*textNode, position.offsetInContainerNode(), position.offsetInContainerNode());
    925928}
    926929
     
    931934
    932935    // Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
    933     int upstream = startOffset;
     936    unsigned upstream = std::max(0, startOffset);
    934937    while (upstream > 0 && deprecatedIsEditingWhitespace(text[upstream - 1]))
    935938        upstream--;
    936939   
    937     int downstream = endOffset;
    938     while ((unsigned)downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
     940    unsigned downstream = std::max(0, endOffset);
     941    while (downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
    939942        downstream++;
    940943   
     
    947950   
    948951    String string = text.substring(upstream, length);
    949     String rebalancedString = stringWithRebalancedWhitespace(string,
    950952    // FIXME: Because of the problem mentioned at the top of this function, we must also use nbsps at the start/end of the string because
    951953    // this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
    952                                                              isStartOfParagraph(visibleUpstreamPos) || upstream == 0,
    953                                                              isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
    954    
     954    String rebalancedString = stringWithRebalancedWhitespace(string, isStartOfParagraph(visibleUpstreamPos) || !upstream,
     955        isEndOfParagraph(visibleDownstreamPos) || downstream == text.length());
     956
    955957    if (string != rebalancedString)
    956958        replaceTextInNodePreservingMarkers(textNode, upstream, length, rebalancedString);
     
    959961void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& position)
    960962{
    961     Node* node = position.deprecatedNode();
     963    auto node = makeRefPtr(position.deprecatedNode());
    962964    if (!is<Text>(node))
    963965        return;
     
    966968    if (!textNode.length())
    967969        return;
    968     RenderObject* renderer = textNode.renderer();
    969     if (renderer && !renderer->style().collapseWhiteSpace())
    970         return;
     970   
     971    {
     972        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     973        RenderObject* renderer = textNode.renderer();
     974        if (renderer && !renderer->style().collapseWhiteSpace())
     975            return;       
     976    }
    971977
    972978    // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
     
    10031009    document().updateLayout();
    10041010
    1005     RenderText* textRenderer = textNode.renderer();
    1006     if (!textRenderer)
    1007         return;
    1008 
    1009     auto run = LayoutIntegration::firstTextRunInTextOrderFor(*textRenderer);
    1010     if (!run) {
    1011         // whole text node is empty
     1011    bool wholeTextNodeIsEmpty = false;
     1012    String str;
     1013    auto determineRemovalMode = [&] {
     1014        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     1015        RenderText* textRenderer = textNode.renderer();
     1016        if (!textRenderer)
     1017            return;
     1018
     1019        auto run = LayoutIntegration::firstTextRunInTextOrderFor(*textRenderer);
     1020        if (!run) {
     1021            wholeTextNodeIsEmpty = true;
     1022            return;
     1023        }
     1024
     1025        unsigned length = textNode.length();
     1026        if (start >= length || end > length)
     1027            return;
     1028
     1029        unsigned removed = 0;
     1030        LayoutIntegration::TextRunIterator previousRun;
     1031
     1032        // This loop structure works to process all gaps preceding a box,
     1033        // and also will look at the gap after the last box.
     1034        while (previousRun || run) {
     1035            unsigned gapStart = previousRun ? previousRun->end() : 0;
     1036            if (end < gapStart)
     1037                break; // No more chance for any intersections
     1038
     1039            unsigned gapEnd = run ? run->start() : length;
     1040            bool indicesIntersect = start <= gapEnd && end >= gapStart;
     1041            int gapLen = gapEnd - gapStart;
     1042            if (indicesIntersect && gapLen > 0) {
     1043                gapStart = std::max(gapStart, start);
     1044                gapEnd = std::min(gapEnd, end);
     1045                if (str.isNull())
     1046                    str = textNode.data().substring(start, end - start);
     1047                // remove text in the gap
     1048                str.remove(gapStart - start - removed, gapLen);
     1049                removed += gapLen;
     1050            }
     1051
     1052            previousRun = run;
     1053            if (run)
     1054                run.traverseNextTextRunInTextOrder();
     1055        }
     1056    };
     1057    determineRemovalMode();
     1058
     1059    if (wholeTextNodeIsEmpty) {
    10121060        removeNode(textNode);
    1013         return;   
    1014     }
    1015    
    1016     unsigned length = textNode.length();
    1017     if (start >= length || end > length)
    1018         return;
    1019 
    1020     unsigned removed = 0;
    1021     LayoutIntegration::TextRunIterator previousRun;
    1022     String str;
    1023 
    1024     // This loop structure works to process all gaps preceding a box,
    1025     // and also will look at the gap after the last box.
    1026     while (previousRun || run) {
    1027         unsigned gapStart = previousRun ? previousRun->end() : 0;
    1028         if (end < gapStart)
    1029             // No more chance for any intersections
    1030             break;
    1031 
    1032         unsigned gapEnd = run ? run->start() : length;
    1033         bool indicesIntersect = start <= gapEnd && end >= gapStart;
    1034         int gapLen = gapEnd - gapStart;
    1035         if (indicesIntersect && gapLen > 0) {
    1036             gapStart = std::max(gapStart, start);
    1037             gapEnd = std::min(gapEnd, end);
    1038             if (str.isNull())
    1039                 str = textNode.data().substring(start, end - start);
    1040             // remove text in the gap
    1041             str.remove(gapStart - start - removed, gapLen);
    1042             removed += gapLen;
    1043         }
    1044        
    1045         previousRun = run;
    1046         if (run)
    1047             run.traverseNextTextRunInTextOrder();
     1061        return;
    10481062    }
    10491063
     
    11201134    document().updateLayoutIgnorePendingStylesheets();
    11211135
    1122     auto* renderer = container->renderer();
    1123     if (!is<RenderBlockFlow>(renderer))
    1124         return nullptr;
    1125    
    1126     // Append the placeholder to make sure it follows any unrendered blocks.
    1127     auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
    1128     if (!blockFlow.height() || (blockFlow.isListItem() && !blockFlow.firstChild()))
    1129         return appendBlockPlaceholder(*container);
    1130 
    1131     return nullptr;
     1136    {
     1137        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     1138
     1139        auto* renderer = container->renderer();
     1140        if (!is<RenderBlockFlow>(renderer))
     1141            return nullptr;
     1142
     1143        // Append the placeholder to make sure it follows any unrendered blocks.
     1144        auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
     1145        if (blockFlow.height() && (!blockFlow.isListItem() || blockFlow.firstChild()))
     1146            return nullptr;
     1147    }
     1148
     1149    return appendBlockPlaceholder(*container);
    11321150}
    11331151
     
    12621280
    12631281        for (size_t i = ancestors.size(); i != 0; --i) {
    1264             Node* item = ancestors[i - 1].get();
    1265             auto child = item->cloneNode(isRenderedTable(item));
     1282            auto item = std::exchange(ancestors[i - 1], nullptr);
     1283            auto child = item->cloneNode(isRenderedTable(item.get()));
    12661284            appendNode(child.copyRef(), downcast<Element>(*lastNode));
    12671285            lastNode = WTFMove(child);
     
    15531571
    15541572    RefPtr<Element> newBlock;
    1555     if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
     1573    if (auto blockEnclosingList = makeRefPtr(listNode->parentNode())) {
    15561574        if (is<HTMLLIElement>(*blockEnclosingList)) { // listNode is inside another list item
    15571575            if (visiblePositionAfterNode(*blockEnclosingList) == visiblePositionAfterNode(*listNode)) {
     
    16081626       
    16091627    VisiblePosition caret(endingSelection().visibleStart());
    1610     Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
     1628    auto highestBlockquote = makeRefPtr(highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote));
    16111629    if (!highestBlockquote)
    16121630        return false;
     
    16211639   
    16221640    auto br = HTMLBRElement::create(document());
    1623     auto* brPtr = br.ptr();
    16241641    // We want to replace this quoted paragraph with an unquoted one, so insert a br
    16251642    // to hold the caret before the highest blockquote.
    1626     insertNodeBefore(br.copyRef(), *highestBlockquote);
    1627     VisiblePosition atBR(positionBeforeNode(brPtr));
     1643    insertNodeBefore(br, *highestBlockquote);
     1644    VisiblePosition atBR = positionBeforeNode(br.ptr());
    16281645    // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
    16291646    // a second one.
    16301647    if (!isStartOfParagraph(atBR))
    1631         insertNodeBefore(HTMLBRElement::create(document()), *brPtr);
     1648        insertNodeBefore(HTMLBRElement::create(document()), br.get());
    16321649    setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
    16331650   
     
    16651682       
    16661683    VisiblePosition visiblePos(original);
    1667     Element* enclosingAnchor = enclosingAnchorElement(original);
     1684    auto enclosingAnchor = makeRefPtr(enclosingAnchorElement(original));
    16681685    Position result = original;
    16691686
     
    16721689
    16731690    // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
    1674     if (enclosingAnchor && !isBlock(enclosingAnchor)) {
    1675         VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
    1676         VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
     1691    if (enclosingAnchor && !isBlock(enclosingAnchor.get())) {
     1692        VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor.get()));
     1693        VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor.get()));
    16771694        // If visually just after the anchor, insert *inside* the anchor unless it's the last
    16781695        // VisiblePosition in the document, to match NSTextView.
     
    16891706            // probably be safe to move the line break so that we could still avoid the anchor here.
    16901707            Position downstream(visiblePos.deepEquivalent().downstream());
    1691             if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
     1708            if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor.get()))
    16921709                return original;
    16931710           
    1694             result = positionInParentAfterNode(enclosingAnchor);
     1711            result = positionInParentAfterNode(enclosingAnchor.get());
    16951712        }
    16961713        // If visually just before an anchor, insert *outside* the anchor unless it's the first
     
    17061723                return original;
    17071724
    1708             result = positionInParentBeforeNode(enclosingAnchor);
     1725            result = positionInParentBeforeNode(enclosingAnchor.get());
    17091726        }
    17101727    }
  • trunk/Source/WebCore/editing/CompositeEditCommand.h

    r275498 r276131  
    3131#include "UndoStep.h"
    3232#include <wtf/Vector.h>
     33#include <wtf/WeakPtr.h>
    3334
    3435namespace WebCore {
     
    104105};
    105106
    106 class CompositeEditCommand : public EditCommand {
     107class CompositeEditCommand : public EditCommand, public CanMakeWeakPtr<CompositeEditCommand> {
    107108public:
    108109    virtual ~CompositeEditCommand();
     
    164165    void rebalanceWhitespaceOnTextSubstring(Text&, int startOffset, int endOffset);
    165166    void prepareWhitespaceAtPositionForSplit(Position&);
    166     bool canRebalance(const Position&) const;
     167    RefPtr<Text> textNodeForRebalance(const Position&) const;
    167168    bool shouldRebalanceLeadingWhitespaceFor(const String&) const;
    168169    void removeNodeAttribute(Element&, const QualifiedName& attribute);
     
    222223};
    223224
    224 inline CompositeEditCommand* toCompositeEditCommand(EditCommand* command)
    225 {
    226     ASSERT(command);
    227     ASSERT_WITH_SECURITY_IMPLICATION(command->isCompositeEditCommand());
    228     return static_cast<CompositeEditCommand*>(command);
    229 }
    230 
    231225} // namespace WebCore
  • trunk/Source/WebCore/editing/EditCommand.cpp

    r260831 r276131  
    3333#include "Editor.h"
    3434#include "Element.h"
    35 #include "HTMLInputElement.h"
    36 #include "HTMLTextAreaElement.h"
     35#include "HTMLTextFormControlElement.h"
    3736#include "NodeTraversal.h"
    3837
     
    124123
    125124EditCommand::EditCommand(Document& document, EditAction editingAction)
    126     : m_document(document)
    127     , m_editingAction(editingAction)
    128 {
    129     setStartingSelection(m_document->selection().selection());
    130     setEndingSelection(m_startingSelection);
     125    : m_document { document }
     126    , m_startingSelection { m_document->selection().selection() }
     127    , m_endingSelection { m_startingSelection }
     128    , m_editingAction { editingAction }
     129{
    131130}
    132131
    133132EditCommand::EditCommand(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection)
    134     : m_document(document)
    135 {
    136     setStartingSelection(startingSelection);
    137     setEndingSelection(endingSelection);
     133    : m_document { document }
     134    , m_startingSelection { startingSelection }
     135    , m_endingSelection { endingSelection }
     136{
    138137}
    139138
     
    145144}
    146145
    147 static inline EditCommandComposition* compositionIfPossible(EditCommand* command)
    148 {
    149     if (!command->isCompositeEditCommand())
    150         return 0;
    151     return toCompositeEditCommand(command)->composition();
     146static RefPtr<EditCommandComposition> compositionIfPossible(EditCommand& command)
     147{
     148    if (!command.isCompositeEditCommand())
     149        return nullptr;
     150    return static_cast<CompositeEditCommand&>(command).composition();
    152151}
    153152
    154153bool EditCommand::isEditingTextAreaOrTextInput() const
    155154{
    156     auto* container = m_document->selection().selection().start().containerNode();
    157     if (!container)
    158         return false;
    159 
    160     auto* ancestor = container->shadowHost();
    161     if (!ancestor)
    162         return false;
    163 
    164     return is<HTMLTextAreaElement>(*ancestor) || (is<HTMLInputElement>(*ancestor) && downcast<HTMLInputElement>(*ancestor).isText());
    165 }
    166 
    167 void EditCommand::setStartingSelection(const VisibleSelection& s)
    168 {
    169     for (EditCommand* cmd = this; ; cmd = cmd->m_parent) {
    170         if (auto* composition = compositionIfPossible(cmd))
    171             composition->setStartingSelection(s);
    172         cmd->m_startingSelection = s;
    173         if (!cmd->m_parent || cmd->m_parent->isFirstCommand(cmd))
     155    return enclosingTextFormControl(m_document->selection().selection().start());
     156}
     157
     158void EditCommand::setStartingSelection(const VisibleSelection& selection)
     159{
     160    for (auto command = makeRefPtr(this); ; command = command->m_parent.get()) {
     161        if (auto composition = compositionIfPossible(*command))
     162            composition->setStartingSelection(selection);
     163        command->m_startingSelection = selection;
     164        if (!command->m_parent || command->m_parent->isFirstCommand(command.get()))
    174165            break;
    175166    }
    176167}
    177168
    178 void EditCommand::setEndingSelection(const VisibleSelection &s)
    179 {
    180     for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) {
    181         if (auto* composition = compositionIfPossible(cmd))
    182             composition->setEndingSelection(s);
    183         cmd->m_endingSelection = s;
     169void EditCommand::setEndingSelection(const VisibleSelection& selection)
     170{
     171    for (auto command = makeRefPtr(this); command; command = command->m_parent.get()) {
     172        if (auto composition = compositionIfPossible(*command))
     173            composition->setEndingSelection(selection);
     174        command->m_endingSelection = selection;
    184175    }
    185176}
     
    188179{
    189180    ASSERT((parent && !m_parent) || (!parent && m_parent));
    190     m_parent = parent;
     181    m_parent = makeWeakPtr(parent);
    191182    if (parent) {
    192183        m_startingSelection = parent->m_endingSelection;
     
    211202    if (!cache)
    212203        return;
    213     auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole);
    214     cache->postTextStateChangeNotification(node, type, text, position);
     204    auto node = makeRefPtr(highestEditableRoot(position.deepEquivalent(), HasEditableAXRole));
     205    cache->postTextStateChangeNotification(node.get(), type, text, position);
    215206}
    216207
  • trunk/Source/WebCore/editing/EditCommand.h

    r260831 r276131  
    2929#include "EditAction.h"
    3030#include "VisibleSelection.h"
     31#include <wtf/WeakPtr.h>
    3132
    3233#ifndef NDEBUG
     
    6667    const Document& document() const { return m_document; }
    6768    Document& document() { return m_document; }
    68     CompositeEditCommand* parent() const { return m_parent; }
     69    CompositeEditCommand* parent() const { return m_parent.get(); }
    6970    void setStartingSelection(const VisibleSelection&);
    7071    WEBCORE_EXPORT void setEndingSelection(const VisibleSelection&);
     
    7980    VisibleSelection m_startingSelection;
    8081    VisibleSelection m_endingSelection;
    81     CompositeEditCommand* m_parent { nullptr };
     82    WeakPtr<CompositeEditCommand> m_parent;
    8283    EditAction m_editingAction { EditAction::Unspecified };
    8384};
  • trunk/Source/WebCore/editing/InsertTextCommand.cpp

    r266557 r276131  
    215215        } else {
    216216            ASSERT(m_rebalanceType == RebalanceAllWhitespaces);
    217             if (canRebalance(startPosition) && canRebalance(endPosition))
     217            ASSERT(textNodeForRebalance(startPosition) == textNodeForRebalance(endPosition));
     218            if (auto textForRebalance = textNodeForRebalance(startPosition)) {
     219                ASSERT(textForRebalance == textNode);
    218220                rebalanceWhitespaceOnTextSubstring(*textNode, startPosition.offsetInContainerNode(), endPosition.offsetInContainerNode());
     221            }
     222
    219223        }
    220224    }
Note: See TracChangeset for help on using the changeset viewer.