Title: [276131] trunk/Source/WebCore
Revision
276131
Author
[email protected]
Date
2021-04-16 03:21:45 -0700 (Fri, 16 Apr 2021)

Log 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):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (276130 => 276131)


--- trunk/Source/WebCore/ChangeLog	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/ChangeLog	2021-04-16 10:21:45 UTC (rev 276131)
@@ -1,3 +1,55 @@
+2021-04-16  Ryosuke Niwa  <[email protected]>
+
+        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):
+
 2021-04-16  Youenn Fablet  <[email protected]>
 
         Remove a no longer necessary callOnMainThread in Worker::createRTCRtpScriptTransformer

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.cpp (276130 => 276131)


--- trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.cpp	2021-04-16 10:21:45 UTC (rev 276131)
@@ -64,6 +64,7 @@
 #include "ReplaceNodeWithSpanCommand.h"
 #include "ReplaceSelectionCommand.h"
 #include "ScopedEventQueue.h"
+#include "ScriptDisallowedScope.h"
 #include "SetNodeAttributeCommand.h"
 #include "SplitElementCommand.h"
 #include "SplitTextNodeCommand.h"
@@ -151,15 +152,15 @@
 static void postTextStateChangeNotification(AXObjectCache* cache, const VisiblePosition& position, const String& deletedText, const String& insertedText)
 {
     ASSERT(cache);
-    auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole);
+    auto node = makeRefPtr(highestEditableRoot(position.deepEquivalent(), HasEditableAXRole));
     if (!node)
         return;
     if (insertedText.length() && deletedText.length())
-        cache->postTextReplacementNotification(node, AXTextEditTypeDelete, insertedText, AXTextEditTypeInsert, deletedText, position);
+        cache->postTextReplacementNotification(node.get(), AXTextEditTypeDelete, insertedText, AXTextEditTypeInsert, deletedText, position);
     else if (deletedText.length())
-        cache->postTextStateChangeNotification(node, AXTextEditTypeInsert, deletedText, position);
+        cache->postTextStateChangeNotification(node.get(), AXTextEditTypeInsert, deletedText, position);
     else if (insertedText.length())
-        cache->postTextStateChangeNotification(node, AXTextEditTypeDelete, insertedText, position);
+        cache->postTextStateChangeNotification(node.get(), AXTextEditTypeDelete, insertedText, position);
 }
 
 void AccessibilityUndoReplacedText::postTextStateChangeNotificationForUnapply(AXObjectCache* cache)
@@ -441,7 +442,7 @@
 
 EditCommandComposition& CompositeEditCommand::ensureComposition()
 {
-    auto* command = this;
+    auto command = makeRefPtr(this);
     while (auto* parent = command->parent())
         command = parent;
     if (!command->m_composition)
@@ -536,11 +537,12 @@
 bool CompositeEditCommand::isRemovableBlock(const Node* node)
 {
     ASSERT(node);
+    // FIXME: We should support other elements that can be removed.
     if (!is<HTMLDivElement>(*node))
         return false;
 
-    Node* parentNode = node->parentNode();
-    if (parentNode && parentNode->firstChild() != parentNode->lastChild())
+    auto* parentNode = node->parentNode();
+    if (!parentNode || !parentNode->hasOneChild())
         return false;
 
     if (!downcast<HTMLDivElement>(*node).hasAttributes())
@@ -551,7 +553,7 @@
 
 void CompositeEditCommand::insertNodeBefore(Ref<Node>&& insertChild, Node& refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
 {
-    auto* parent = refChild.parentNode();
+    auto parent = makeRefPtr(refChild.parentNode());
     if (!parent || (!parent->hasEditableStyle() && parent->renderer()))
         return;
     applyCommandToComposite(InsertNodeBeforeCommand::create(WTFMove(insertChild), refChild, shouldAssumeContentIsAlwaysEditable, editingAction()));
@@ -559,7 +561,7 @@
 
 void CompositeEditCommand::insertNodeAfter(Ref<Node>&& insertChild, Node& refChild)
 {
-    ContainerNode* parent = refChild.parentNode();
+    auto parent = makeRefPtr(refChild.parentNode());
     if (!parent)
         return;
 
@@ -578,11 +580,11 @@
     // For editing positions like [table, 0], insert before the table,
     // likewise for replaced elements, brs, etc.
     Position p = editingPosition.parentAnchoredEquivalent();
-    Node* refChild = p.deprecatedNode();
+    auto refChild = makeRefPtr(p.deprecatedNode());
     int offset = p.deprecatedEditingOffset();
     
     if (canHaveChildrenForEditing(*refChild)) {
-        Node* child = refChild->firstChild();
+        auto child = makeRefPtr(refChild->firstChild());
         for (int i = 0; child && i < offset; i++)
             child = child->nextSibling();
         if (child)
@@ -611,7 +613,7 @@
 void CompositeEditCommand::removeChildrenInRange(Node& node, unsigned from, unsigned to)
 {
     Vector<Ref<Node>> children;
-    Node* child = node.traverseToChildAt(from);
+    auto child = makeRefPtr(node.traverseToChildAt(from));
     for (unsigned i = from; child && i < to; i++, child = child->nextSibling())
         children.append(*child);
 
@@ -666,13 +668,12 @@
     // as a series of existing smaller edit commands.  Someone who wanted to
     // reduce the number of edit commands could do so here.
     auto command = ReplaceNodeWithSpanCommand::create(element);
-    auto* commandPtr = command.ptr();
-    applyCommandToComposite(WTFMove(command));
+    applyCommandToComposite(command);
     // Returning a raw pointer here is OK because the command is retained by
     // applyCommandToComposite (thus retaining the span), and the span is also
     // in the DOM tree, and thus alive whie it has a parent.
-    ASSERT(commandPtr->spanElement()->isConnected());
-    return commandPtr->spanElement();
+    ASSERT(command->spanElement()->isConnected());
+    return command->spanElement();
 }
 
 void CompositeEditCommand::prune(Node* node)
@@ -822,16 +823,16 @@
         return positionInParentAfterNode(position.anchorNode());
     }
 
-    auto* tabSpan = tabSpanNode(position.containerNode());
+    auto tabSpan = makeRefPtr(tabSpanNode(position.containerNode()));
 
     if (position.offsetInContainerNode() <= caretMinOffset(*position.containerNode()))
-        return positionInParentBeforeNode(tabSpan);
+        return positionInParentBeforeNode(tabSpan.get());
 
     if (position.offsetInContainerNode() >= caretMaxOffset(*position.containerNode()))
-        return positionInParentAfterNode(tabSpan);
+        return positionInParentAfterNode(tabSpan.get());
 
     splitTextNodeContainingElement(downcast<Text>(*position.containerNode()), position.offsetInContainerNode());
-    return positionInParentBeforeNode(tabSpan);
+    return positionInParentBeforeNode(tabSpan.get());
 }
 
 void CompositeEditCommand::insertNodeAtTabSpanPosition(Ref<Node>&& node, const Position& pos)
@@ -886,35 +887,37 @@
     return containsOnlyDeprecatedEditingWhitespace(text);
 }
 
-bool CompositeEditCommand::canRebalance(const Position& position) const
+RefPtr<Text> CompositeEditCommand::textNodeForRebalance(const Position& position) const
 {
-    Node* node = position.containerNode();
+    auto node = makeRefPtr(position.containerNode());
     if (position.anchorType() != Position::PositionIsOffsetInAnchor || !is<Text>(node))
-        return false;
+        return nullptr;
 
-    Text& textNode = downcast<Text>(*node);
-    if (!textNode.length())
-        return false;
+    auto textNode = static_pointer_cast<Text>(std::exchange(node, nullptr));
+    if (!textNode->length())
+        return nullptr;
 
-    node->document().updateStyleIfNeeded();
+    textNode->document().updateStyleIfNeeded();
 
-    RenderObject* renderer = textNode.renderer();
+    ScriptDisallowedScope::InMainThread scriptDisallowedScope;
+
+    RenderObject* renderer = textNode->renderer();
     if (renderer && !renderer->style().collapseWhiteSpace())
-        return false;
+        return nullptr;
 
-    return true;
+    return textNode;
 }
 
 // FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
 void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
 {
-    Node* node = position.containerNode();
-    if (!canRebalance(position))
+    auto textNode = textNodeForRebalance(position);
+    if (!textNode)
         return;
 
     // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
     int offset = position.deprecatedEditingOffset();
-    String text = downcast<Text>(*node).data();
+    String text = textNode->data();
     if (!deprecatedIsEditingWhitespace(text[offset])) {
         offset--;
         if (offset < 0 || !deprecatedIsEditingWhitespace(text[offset]))
@@ -921,7 +924,7 @@
             return;
     }
 
-    rebalanceWhitespaceOnTextSubstring(downcast<Text>(*node), position.offsetInContainerNode(), position.offsetInContainerNode());
+    rebalanceWhitespaceOnTextSubstring(*textNode, position.offsetInContainerNode(), position.offsetInContainerNode());
 }
 
 void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(Text& textNode, int startOffset, int endOffset)
@@ -930,12 +933,12 @@
     ASSERT(!text.isEmpty());
 
     // Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
-    int upstream = startOffset;
+    unsigned upstream = std::max(0, startOffset);
     while (upstream > 0 && deprecatedIsEditingWhitespace(text[upstream - 1]))
         upstream--;
     
-    int downstream = endOffset;
-    while ((unsigned)downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
+    unsigned downstream = std::max(0, endOffset);
+    while (downstream < text.length() && deprecatedIsEditingWhitespace(text[downstream]))
         downstream++;
     
     int length = downstream - upstream;
@@ -946,12 +949,11 @@
     VisiblePosition visibleDownstreamPos(Position(&textNode, downstream));
     
     String string = text.substring(upstream, length);
-    String rebalancedString = stringWithRebalancedWhitespace(string,
     // 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
     // this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
-                                                             isStartOfParagraph(visibleUpstreamPos) || upstream == 0, 
-                                                             isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
-    
+    String rebalancedString = stringWithRebalancedWhitespace(string, isStartOfParagraph(visibleUpstreamPos) || !upstream,
+        isEndOfParagraph(visibleDownstreamPos) || downstream == text.length());
+
     if (string != rebalancedString)
         replaceTextInNodePreservingMarkers(textNode, upstream, length, rebalancedString);
 }
@@ -958,7 +960,7 @@
 
 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& position)
 {
-    Node* node = position.deprecatedNode();
+    auto node = makeRefPtr(position.deprecatedNode());
     if (!is<Text>(node))
         return;
     Text& textNode = downcast<Text>(*node);
@@ -965,9 +967,13 @@
     
     if (!textNode.length())
         return;
-    RenderObject* renderer = textNode.renderer();
-    if (renderer && !renderer->style().collapseWhiteSpace())
-        return;
+    
+    {
+        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
+        RenderObject* renderer = textNode.renderer();
+        if (renderer && !renderer->style().collapseWhiteSpace())
+            return;        
+    }
 
     // Delete collapsed whitespace so that inserting nbsps doesn't uncollapse it.
     Position upstreamPos = position.upstream();
@@ -1002,49 +1008,57 @@
 
     document().updateLayout();
 
-    RenderText* textRenderer = textNode.renderer();
-    if (!textRenderer)
-        return;
+    bool wholeTextNodeIsEmpty = false;
+    String str;
+    auto determineRemovalMode = [&] {
+        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
+        RenderText* textRenderer = textNode.renderer();
+        if (!textRenderer)
+            return;
 
-    auto run = LayoutIntegration::firstTextRunInTextOrderFor(*textRenderer);
-    if (!run) {
-        // whole text node is empty
-        removeNode(textNode);
-        return;    
-    }
-    
-    unsigned length = textNode.length();
-    if (start >= length || end > length)
-        return;
+        auto run = LayoutIntegration::firstTextRunInTextOrderFor(*textRenderer);
+        if (!run) {
+            wholeTextNodeIsEmpty = true;
+            return;
+        }
 
-    unsigned removed = 0;
-    LayoutIntegration::TextRunIterator previousRun;
-    String str;
+        unsigned length = textNode.length();
+        if (start >= length || end > length)
+            return;
 
-    // This loop structure works to process all gaps preceding a box,
-    // and also will look at the gap after the last box.
-    while (previousRun || run) {
-        unsigned gapStart = previousRun ? previousRun->end() : 0;
-        if (end < gapStart)
-            // No more chance for any intersections
-            break;
+        unsigned removed = 0;
+        LayoutIntegration::TextRunIterator previousRun;
 
-        unsigned gapEnd = run ? run->start() : length;
-        bool indicesIntersect = start <= gapEnd && end >= gapStart;
-        int gapLen = gapEnd - gapStart;
-        if (indicesIntersect && gapLen > 0) {
-            gapStart = std::max(gapStart, start);
-            gapEnd = std::min(gapEnd, end);
-            if (str.isNull())
-                str = textNode.data().substring(start, end - start);
-            // remove text in the gap
-            str.remove(gapStart - start - removed, gapLen);
-            removed += gapLen;
+        // This loop structure works to process all gaps preceding a box,
+        // and also will look at the gap after the last box.
+        while (previousRun || run) {
+            unsigned gapStart = previousRun ? previousRun->end() : 0;
+            if (end < gapStart)
+                break; // No more chance for any intersections
+
+            unsigned gapEnd = run ? run->start() : length;
+            bool indicesIntersect = start <= gapEnd && end >= gapStart;
+            int gapLen = gapEnd - gapStart;
+            if (indicesIntersect && gapLen > 0) {
+                gapStart = std::max(gapStart, start);
+                gapEnd = std::min(gapEnd, end);
+                if (str.isNull())
+                    str = textNode.data().substring(start, end - start);
+                // remove text in the gap
+                str.remove(gapStart - start - removed, gapLen);
+                removed += gapLen;
+            }
+
+            previousRun = run;
+            if (run)
+                run.traverseNextTextRunInTextOrder();
         }
-        
-        previousRun = run;
-        if (run)
-            run.traverseNextTextRunInTextOrder();
+    };
+    determineRemovalMode();
+
+    if (wholeTextNodeIsEmpty) {
+        removeNode(textNode);
+        return;
     }
 
     if (!str.isNull()) {
@@ -1119,16 +1133,20 @@
 
     document().updateLayoutIgnorePendingStylesheets();
 
-    auto* renderer = container->renderer();
-    if (!is<RenderBlockFlow>(renderer))
-        return nullptr;
-    
-    // Append the placeholder to make sure it follows any unrendered blocks.
-    auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
-    if (!blockFlow.height() || (blockFlow.isListItem() && !blockFlow.firstChild()))
-        return appendBlockPlaceholder(*container);
+    {
+        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
 
-    return nullptr;
+        auto* renderer = container->renderer();
+        if (!is<RenderBlockFlow>(renderer))
+            return nullptr;
+
+        // Append the placeholder to make sure it follows any unrendered blocks.
+        auto& blockFlow = downcast<RenderBlockFlow>(*renderer);
+        if (blockFlow.height() && (!blockFlow.isListItem() || blockFlow.firstChild()))
+            return nullptr;
+    }
+
+    return appendBlockPlaceholder(*container);
 }
 
 // Assumes that the position is at a placeholder and does the removal without much checking.
@@ -1261,8 +1279,8 @@
         // Clone every node between start.deprecatedNode() and outerBlock.
 
         for (size_t i = ancestors.size(); i != 0; --i) {
-            Node* item = ancestors[i - 1].get();
-            auto child = item->cloneNode(isRenderedTable(item));
+            auto item = std::exchange(ancestors[i - 1], nullptr);
+            auto child = item->cloneNode(isRenderedTable(item.get()));
             appendNode(child.copyRef(), downcast<Element>(*lastNode));
             lastNode = WTFMove(child);
         }
@@ -1552,7 +1570,7 @@
     style->mergeTypingStyle(document());
 
     RefPtr<Element> newBlock;
-    if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
+    if (auto blockEnclosingList = makeRefPtr(listNode->parentNode())) {
         if (is<HTMLLIElement>(*blockEnclosingList)) { // listNode is inside another list item
             if (visiblePositionAfterNode(*blockEnclosingList) == visiblePositionAfterNode(*listNode)) {
                 // If listNode appears at the end of the outer list item, then move listNode outside of this list item
@@ -1607,7 +1625,7 @@
         return false;
         
     VisiblePosition caret(endingSelection().visibleStart());
-    Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote);
+    auto highestBlockquote = makeRefPtr(highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote));
     if (!highestBlockquote)
         return false;
 
@@ -1620,15 +1638,14 @@
         return false;
     
     auto br = HTMLBRElement::create(document());
-    auto* brPtr = br.ptr();
     // We want to replace this quoted paragraph with an unquoted one, so insert a br
     // to hold the caret before the highest blockquote.
-    insertNodeBefore(br.copyRef(), *highestBlockquote);
-    VisiblePosition atBR(positionBeforeNode(brPtr));
+    insertNodeBefore(br, *highestBlockquote);
+    VisiblePosition atBR = positionBeforeNode(br.ptr());
     // If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
     // a second one.
     if (!isStartOfParagraph(atBR))
-        insertNodeBefore(HTMLBRElement::create(document()), *brPtr);
+        insertNodeBefore(HTMLBRElement::create(document()), br.get());
     setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
     
     // If this is an empty paragraph there must be a line break here.
@@ -1664,7 +1681,7 @@
         return original;
         
     VisiblePosition visiblePos(original);
-    Element* enclosingAnchor = enclosingAnchorElement(original);
+    auto enclosingAnchor = makeRefPtr(enclosingAnchorElement(original));
     Position result = original;
 
     if (!enclosingAnchor)
@@ -1671,9 +1688,9 @@
         return result;
 
     // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
-    if (enclosingAnchor && !isBlock(enclosingAnchor)) {
-        VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
-        VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
+    if (enclosingAnchor && !isBlock(enclosingAnchor.get())) {
+        VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor.get()));
+        VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor.get()));
         // If visually just after the anchor, insert *inside* the anchor unless it's the last
         // VisiblePosition in the document, to match NSTextView.
         if (visiblePos == lastInAnchor) {
@@ -1688,10 +1705,10 @@
             // Don't insert outside an anchor if doing so would skip over a line break.  It would
             // probably be safe to move the line break so that we could still avoid the anchor here.
             Position downstream(visiblePos.deepEquivalent().downstream());
-            if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor))
+            if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.deprecatedNode()->isDescendantOf(enclosingAnchor.get()))
                 return original;
             
-            result = positionInParentAfterNode(enclosingAnchor);
+            result = positionInParentAfterNode(enclosingAnchor.get());
         }
         // If visually just before an anchor, insert *outside* the anchor unless it's the first
         // VisiblePosition in a paragraph, to match NSTextView.
@@ -1705,7 +1722,7 @@
             if (!enclosingAnchor)
                 return original;
 
-            result = positionInParentBeforeNode(enclosingAnchor);
+            result = positionInParentBeforeNode(enclosingAnchor.get());
         }
     }
         

Modified: trunk/Source/WebCore/editing/CompositeEditCommand.h (276130 => 276131)


--- trunk/Source/WebCore/editing/CompositeEditCommand.h	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.h	2021-04-16 10:21:45 UTC (rev 276131)
@@ -30,6 +30,7 @@
 #include "CSSPropertyNames.h"
 #include "UndoStep.h"
 #include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
@@ -103,7 +104,7 @@
     EditAction m_editAction;
 };
 
-class CompositeEditCommand : public EditCommand {
+class CompositeEditCommand : public EditCommand, public CanMakeWeakPtr<CompositeEditCommand> {
 public:
     virtual ~CompositeEditCommand();
 
@@ -163,7 +164,7 @@
     void rebalanceWhitespaceAt(const Position&);
     void rebalanceWhitespaceOnTextSubstring(Text&, int startOffset, int endOffset);
     void prepareWhitespaceAtPositionForSplit(Position&);
-    bool canRebalance(const Position&) const;
+    RefPtr<Text> textNodeForRebalance(const Position&) const;
     bool shouldRebalanceLeadingWhitespaceFor(const String&) const;
     void removeNodeAttribute(Element&, const QualifiedName& attribute);
     void removeChildrenInRange(Node&, unsigned from, unsigned to);
@@ -221,11 +222,4 @@
     RefPtr<EditCommandComposition> m_composition;
 };
 
-inline CompositeEditCommand* toCompositeEditCommand(EditCommand* command)
-{
-    ASSERT(command);
-    ASSERT_WITH_SECURITY_IMPLICATION(command->isCompositeEditCommand());
-    return static_cast<CompositeEditCommand*>(command);
-}
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/EditCommand.cpp (276130 => 276131)


--- trunk/Source/WebCore/editing/EditCommand.cpp	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/editing/EditCommand.cpp	2021-04-16 10:21:45 UTC (rev 276131)
@@ -32,8 +32,7 @@
 #include "Editing.h"
 #include "Editor.h"
 #include "Element.h"
-#include "HTMLInputElement.h"
-#include "HTMLTextAreaElement.h"
+#include "HTMLTextFormControlElement.h"
 #include "NodeTraversal.h"
 
 namespace WebCore {
@@ -123,18 +122,18 @@
 }
 
 EditCommand::EditCommand(Document& document, EditAction editingAction)
-    : m_document(document)
-    , m_editingAction(editingAction)
+    : m_document { document }
+    , m_startingSelection { m_document->selection().selection() }
+    , m_endingSelection { m_startingSelection }
+    , m_editingAction { editingAction }
 {
-    setStartingSelection(m_document->selection().selection());
-    setEndingSelection(m_startingSelection);
 }
 
 EditCommand::EditCommand(Document& document, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection)
-    : m_document(document)
+    : m_document { document }
+    , m_startingSelection { startingSelection }
+    , m_endingSelection { endingSelection }
 {
-    setStartingSelection(startingSelection);
-    setEndingSelection(endingSelection);
 }
 
 EditCommand::~EditCommand() = default;
@@ -144,43 +143,35 @@
     return m_editingAction;
 }
 
-static inline EditCommandComposition* compositionIfPossible(EditCommand* command)
+static RefPtr<EditCommandComposition> compositionIfPossible(EditCommand& command)
 {
-    if (!command->isCompositeEditCommand())
-        return 0;
-    return toCompositeEditCommand(command)->composition();
+    if (!command.isCompositeEditCommand())
+        return nullptr;
+    return static_cast<CompositeEditCommand&>(command).composition();
 }
 
 bool EditCommand::isEditingTextAreaOrTextInput() const
 {
-    auto* container = m_document->selection().selection().start().containerNode();
-    if (!container)
-        return false;
-
-    auto* ancestor = container->shadowHost();
-    if (!ancestor)
-        return false;
-
-    return is<HTMLTextAreaElement>(*ancestor) || (is<HTMLInputElement>(*ancestor) && downcast<HTMLInputElement>(*ancestor).isText());
+    return enclosingTextFormControl(m_document->selection().selection().start());
 }
 
-void EditCommand::setStartingSelection(const VisibleSelection& s)
+void EditCommand::setStartingSelection(const VisibleSelection& selection)
 {
-    for (EditCommand* cmd = this; ; cmd = cmd->m_parent) {
-        if (auto* composition = compositionIfPossible(cmd))
-            composition->setStartingSelection(s);
-        cmd->m_startingSelection = s;
-        if (!cmd->m_parent || cmd->m_parent->isFirstCommand(cmd))
+    for (auto command = makeRefPtr(this); ; command = command->m_parent.get()) {
+        if (auto composition = compositionIfPossible(*command))
+            composition->setStartingSelection(selection);
+        command->m_startingSelection = selection;
+        if (!command->m_parent || command->m_parent->isFirstCommand(command.get()))
             break;
     }
 }
 
-void EditCommand::setEndingSelection(const VisibleSelection &s)
+void EditCommand::setEndingSelection(const VisibleSelection& selection)
 {
-    for (EditCommand* cmd = this; cmd; cmd = cmd->m_parent) {
-        if (auto* composition = compositionIfPossible(cmd))
-            composition->setEndingSelection(s);
-        cmd->m_endingSelection = s;
+    for (auto command = makeRefPtr(this); command; command = command->m_parent.get()) {
+        if (auto composition = compositionIfPossible(*command))
+            composition->setEndingSelection(selection);
+        command->m_endingSelection = selection;
     }
 }
 
@@ -187,7 +178,7 @@
 void EditCommand::setParent(CompositeEditCommand* parent)
 {
     ASSERT((parent && !m_parent) || (!parent && m_parent));
-    m_parent = parent;
+    m_parent = makeWeakPtr(parent);
     if (parent) {
         m_startingSelection = parent->m_endingSelection;
         m_endingSelection = parent->m_endingSelection;
@@ -210,8 +201,8 @@
     auto* cache = document().existingAXObjectCache();
     if (!cache)
         return;
-    auto* node = highestEditableRoot(position.deepEquivalent(), HasEditableAXRole);
-    cache->postTextStateChangeNotification(node, type, text, position);
+    auto node = makeRefPtr(highestEditableRoot(position.deepEquivalent(), HasEditableAXRole));
+    cache->postTextStateChangeNotification(node.get(), type, text, position);
 }
 
 SimpleEditCommand::SimpleEditCommand(Document& document, EditAction editingAction)

Modified: trunk/Source/WebCore/editing/EditCommand.h (276130 => 276131)


--- trunk/Source/WebCore/editing/EditCommand.h	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/editing/EditCommand.h	2021-04-16 10:21:45 UTC (rev 276131)
@@ -28,6 +28,7 @@
 #include "AXTextStateChangeIntent.h"
 #include "EditAction.h"
 #include "VisibleSelection.h"
+#include <wtf/WeakPtr.h>
 
 #ifndef NDEBUG
 #include <wtf/HashSet.h>
@@ -65,7 +66,7 @@
 
     const Document& document() const { return m_document; }
     Document& document() { return m_document; }
-    CompositeEditCommand* parent() const { return m_parent; }
+    CompositeEditCommand* parent() const { return m_parent.get(); }
     void setStartingSelection(const VisibleSelection&);
     WEBCORE_EXPORT void setEndingSelection(const VisibleSelection&);
 
@@ -78,7 +79,7 @@
     Ref<Document> m_document;
     VisibleSelection m_startingSelection;
     VisibleSelection m_endingSelection;
-    CompositeEditCommand* m_parent { nullptr };
+    WeakPtr<CompositeEditCommand> m_parent;
     EditAction m_editingAction { EditAction::Unspecified };
 };
 

Modified: trunk/Source/WebCore/editing/InsertTextCommand.cpp (276130 => 276131)


--- trunk/Source/WebCore/editing/InsertTextCommand.cpp	2021-04-16 10:13:22 UTC (rev 276130)
+++ trunk/Source/WebCore/editing/InsertTextCommand.cpp	2021-04-16 10:21:45 UTC (rev 276131)
@@ -214,8 +214,12 @@
                 rebalanceWhitespaceAt(startPosition);
         } else {
             ASSERT(m_rebalanceType == RebalanceAllWhitespaces);
-            if (canRebalance(startPosition) && canRebalance(endPosition))
+            ASSERT(textNodeForRebalance(startPosition) == textNodeForRebalance(endPosition));
+            if (auto textForRebalance = textNodeForRebalance(startPosition)) {
+                ASSERT(textForRebalance == textNode);
                 rebalanceWhitespaceOnTextSubstring(*textNode, startPosition.offsetInContainerNode(), endPosition.offsetInContainerNode());
+            }
+
         }
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to