Editing: Make the |EditingState*| argument of CompositeEditCommand::removeNode mandatory.
This CL doesn't introduce new ASSERT_NO_EDITING_ABORTs except cases where node
removal won't dispatch synchronous events.
This CL has no tests. We're not sure if this CL makes user-visible behavior
changes. The purpose of this CL is to reduce ClusterFuzz crashes in the future.
BUG=586846
Review URL: https://codereview.chromium.org/1695153002
Cr-Commit-Position: refs/heads/master@{#375417}
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 3720339..46f8df6 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -636,24 +636,36 @@
styleWithoutEmbedding = style->copy();
embeddingStyle = styleWithoutEmbedding->extractAndRemoveTextDirection();
- if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0)
- removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, embeddingRemoveEnd);
+ if (comparePositions(embeddingRemoveStart, embeddingRemoveEnd) <= 0) {
+ removeInlineStyle(embeddingStyle.get(), embeddingRemoveStart, embeddingRemoveEnd, editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
}
- removeInlineStyle(styleWithoutEmbedding ? styleWithoutEmbedding.get() : style, removeStart, end);
+ removeInlineStyle(styleWithoutEmbedding ? styleWithoutEmbedding.get() : style, removeStart, end, editingState);
+ if (editingState->isAborted())
+ return;
start = startPosition();
end = endPosition();
if (start.isNull() || start.isOrphan() || end.isNull() || end.isOrphan())
return;
- if (splitStart && mergeStartWithPreviousIfIdentical(start, end)) {
- start = startPosition();
- end = endPosition();
+ if (splitStart) {
+ bool mergeResult = mergeStartWithPreviousIfIdentical(start, end, editingState);
+ if (editingState->isAborted())
+ return;
+ if (splitStart && mergeResult) {
+ start = startPosition();
+ end = endPosition();
+ }
}
if (splitEnd) {
- mergeEndWithNextIfIdentical(start, end);
+ mergeEndWithNextIfIdentical(start, end, editingState);
+ if (editingState->isAborted())
+ return;
start = startPosition();
end = endPosition();
}
@@ -1033,7 +1045,7 @@
return result;
}
-void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style)
+void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style, EditingState* editingState)
{
ASSERT(node);
@@ -1061,10 +1073,10 @@
// We can't wrap node with the styled element here because new styled element will never be removed if we did.
// If we modified the child pointer in pushDownInlineStyleAroundNode to point to new style element
// then we fall into an infinite loop where we keep removing and adding styled element wrapping node.
- addInlineStyleIfNeeded(newInlineStyle.get(), node, node, DoNotAddStyledElement);
+ addInlineStyleIfNeeded(newInlineStyle.get(), node, node, editingState, DoNotAddStyledElement);
}
-void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node* targetNode)
+void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node* targetNode, EditingState* editingState)
{
HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(style, targetNode);
if (!highestAncestor)
@@ -1108,8 +1120,11 @@
// Apply style to all nodes containing targetNode and their siblings but NOT to targetNode
// But if we've removed styledElement then go ahead and always apply the style.
- if (child != targetNode || styledElement)
- applyInlineStyleToPushDown(child, styleToPushDown.get());
+ if (child != targetNode || styledElement) {
+ applyInlineStyleToPushDown(child, styleToPushDown.get(), editingState);
+ if (editingState->isAborted())
+ return;
+ }
// We found the next node for the outer loop (contains targetNode)
// When reached targetNode, stop the outer loop upon the completion of the current inner loop
@@ -1119,7 +1134,7 @@
}
}
-void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &start, const Position &end)
+void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &start, const Position &end, EditingState* editingState)
{
ASSERT(start.isNotNull());
ASSERT(end.isNotNull());
@@ -1144,8 +1159,12 @@
if (pushDownEndContainer && pushDownEndContainer->isTextNode() && !pushDownEnd.computeOffsetInContainerNode())
pushDownEnd = previousVisuallyDistinctCandidate(pushDownEnd);
- pushDownInlineStyleAroundNode(style, pushDownStart.anchorNode());
- pushDownInlineStyleAroundNode(style, pushDownEnd.anchorNode());
+ pushDownInlineStyleAroundNode(style, pushDownStart.anchorNode(), editingState);
+ if (editingState->isAborted())
+ return;
+ pushDownInlineStyleAroundNode(style, pushDownEnd.anchorNode(), editingState);
+ if (editingState->isAborted())
+ return;
// The s and e variables store the positions used to set the ending selection after style removal
// takes place. This will help callers to recognize when either the start node or the end node
@@ -1198,8 +1217,11 @@
}
if (styleToPushDown) {
- for (; childNode; childNode = childNode->nextSibling())
- applyInlineStyleToPushDown(childNode.get(), styleToPushDown.get());
+ for (; childNode; childNode = childNode->nextSibling()) {
+ applyInlineStyleToPushDown(childNode.get(), styleToPushDown.get(), editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
}
if (node == end.anchorNode())
@@ -1301,7 +1323,7 @@
return offsetInText > caretMinOffset(node) && offsetInText < caretMaxOffset(node);
}
-bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end)
+bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState* editingState)
{
Node* startNode = start.computeContainerNode();
int startOffset = start.computeOffsetInContainerNode();
@@ -1327,7 +1349,9 @@
Element* element = toElement(startNode);
Node* startChild = element->firstChild();
ASSERT(startChild);
- mergeIdenticalElements(previousElement, element);
+ mergeIdenticalElements(previousElement, element, editingState);
+ if (editingState->isAborted())
+ return false;
int startOffsetAdjustment = startChild->nodeIndex();
int endOffsetAdjustment = startNode == end.anchorNode() ? startOffsetAdjustment : 0;
@@ -1339,7 +1363,7 @@
return false;
}
-bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end)
+bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const Position& end, EditingState* editingState)
{
Node* endNode = end.computeContainerNode();
@@ -1363,7 +1387,9 @@
Element* element = toElement(endNode);
Node* nextChild = nextElement->firstChild();
- mergeIdenticalElements(element, nextElement);
+ mergeIdenticalElements(element, nextElement, editingState);
+ if (editingState->isAborted())
+ return false;
bool shouldUpdateStart = start.computeContainerNode() == endNode;
int endOffset = nextChild ? nextChild->nodeIndex() : nextElement->childNodes()->length();
@@ -1403,14 +1429,20 @@
RefPtrWillBeRawPtr<Node> nextSibling = element->nextSibling();
RefPtrWillBeRawPtr<Node> previousSibling = element->previousSibling();
if (nextSibling && nextSibling->isElementNode() && nextSibling->hasEditableStyle()
- && areIdenticalElements(*element, toElement(*nextSibling)))
- mergeIdenticalElements(element.get(), toElement(nextSibling));
+ && areIdenticalElements(*element, toElement(*nextSibling))) {
+ mergeIdenticalElements(element.get(), toElement(nextSibling), editingState);
+ if (editingState->isAborted())
+ return;
+ }
if (previousSibling && previousSibling->isElementNode() && previousSibling->hasEditableStyle()) {
Node* mergedElement = previousSibling->nextSibling();
if (mergedElement->isElementNode() && mergedElement->hasEditableStyle()
- && areIdenticalElements(toElement(*previousSibling), toElement(*mergedElement)))
- mergeIdenticalElements(toElement(previousSibling), toElement(mergedElement));
+ && areIdenticalElements(toElement(*previousSibling), toElement(*mergedElement))) {
+ mergeIdenticalElements(toElement(previousSibling), toElement(mergedElement), editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
// FIXME: We should probably call updateStartEnd if the start or end was in the node
@@ -1436,7 +1468,7 @@
setNodeAttribute(block, styleAttr, cssText.toAtomicString());
}
-void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWillBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EAddStyledElement addStyledElement)
+void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWillBeRawPtr<Node> passedStart, PassRefPtrWillBeRawPtr<Node> passedEnd, EditingState* editingState, EAddStyledElement addStyledElement)
{
if (!passedStart || !passedEnd || !passedStart->inDocument() || !passedEnd->inDocument())
return;
@@ -1445,10 +1477,13 @@
RefPtrWillBeMember<HTMLSpanElement> dummyElement = nullptr;
StyleChange styleChange(style, positionToComputeInlineStyleChange(start, dummyElement));
- if (dummyElement)
- removeNode(dummyElement);
+ if (dummyElement) {
+ removeNode(dummyElement, editingState);
+ if (editingState->isAborted())
+ return;
+ }
- applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement, ASSERT_NO_EDITING_ABORT);
+ applyInlineStyleChange(start, passedEnd, styleChange, addStyledElement, editingState);
}
Position ApplyStyleCommand::positionToComputeInlineStyleChange(PassRefPtrWillBeRawPtr<Node> startNode, RefPtrWillBeMember<HTMLSpanElement>& dummyElement)
@@ -1617,7 +1652,8 @@
newEnd = Position(childText, childText->length() + end.offsetInContainerNode());
String textToMove = nextText->data();
insertTextIntoNode(childText, childText->length(), textToMove);
- removeNode(next);
+ // Removing a Text node doesn't dispatch synchronous events.
+ removeNode(next, ASSERT_NO_EDITING_ABORT);
// don't move child node pointer. it may want to merge with more text nodes.
}
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
index 42452e74..2bbc56d 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.h
@@ -86,9 +86,9 @@
bool removeImplicitlyStyledElement(EditingStyle*, HTMLElement*, InlineStyleRemovalMode, EditingStyle* extractedStyle);
bool removeCSSStyle(EditingStyle*, HTMLElement*, InlineStyleRemovalMode = RemoveIfNeeded, EditingStyle* extractedStyle = nullptr);
HTMLElement* highestAncestorWithConflictingInlineStyle(EditingStyle*, Node*);
- void applyInlineStyleToPushDown(Node*, EditingStyle*);
- void pushDownInlineStyleAroundNode(EditingStyle*, Node*);
- void removeInlineStyle(EditingStyle* , const Position& start, const Position& end);
+ void applyInlineStyleToPushDown(Node*, EditingStyle*, EditingState*);
+ void pushDownInlineStyleAroundNode(EditingStyle*, Node*, EditingState*);
+ void removeInlineStyle(EditingStyle* , const Position& start, const Position& end, EditingState*);
bool elementFullySelected(HTMLElement&, const Position& start, const Position& end) const;
// style-application helpers
@@ -98,7 +98,9 @@
void fixRangeAndApplyInlineStyle(EditingStyle*, const Position& start, const Position& end, EditingState*);
void applyInlineStyleToNodeRange(EditingStyle*, PassRefPtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> pastEndNode, EditingState*);
void addBlockStyle(const StyleChange&, HTMLElement*);
- void addInlineStyleIfNeeded(EditingStyle*, PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, EAddStyledElement = AddStyledElement);
+ // TODO(tkent): Remove the EAddStyledElement argument. It's always
+ // DoNotAddStyledElement.
+ void addInlineStyleIfNeeded(EditingStyle*, PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, EditingState*, EAddStyledElement = AddStyledElement);
Position positionToComputeInlineStyleChange(PassRefPtrWillBeRawPtr<Node>, RefPtrWillBeMember<HTMLSpanElement>& dummyElement);
void applyInlineStyleChange(PassRefPtrWillBeRawPtr<Node> startNode, PassRefPtrWillBeRawPtr<Node> endNode, StyleChange&, EAddStyledElement, EditingState*);
void splitTextAtStart(const Position& start, const Position& end);
@@ -107,8 +109,8 @@
void splitTextElementAtEnd(const Position& start, const Position& end);
bool shouldSplitTextElement(Element*, EditingStyle*);
bool isValidCaretPositionInTextNode(const Position&);
- bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end);
- bool mergeEndWithNextIfIdentical(const Position& start, const Position& end);
+ bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end, EditingState*);
+ bool mergeEndWithNextIfIdentical(const Position& start, const Position& end, EditingState*);
void cleanupUnstyledAppleStyleSpans(ContainerNode* dummySpanAncestor);
void surroundNodeRangeWithElement(PassRefPtrWillBeRawPtr<Node> start, PassRefPtrWillBeRawPtr<Node> end, PassRefPtrWillBeRawPtr<Element>, EditingState*);
diff --git a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
index cea7493..b7bc276 100644
--- a/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/BreakBlockquoteCommand.cpp
@@ -72,14 +72,17 @@
{
}
-void BreakBlockquoteCommand::doApply(EditingState*)
+void BreakBlockquoteCommand::doApply(EditingState* editingState)
{
if (endingSelection().isNone())
return;
// Delete the current selection.
- if (endingSelection().isRange())
- deleteSelection(ASSERT_NO_EDITING_ABORT, false, false);
+ if (endingSelection().isRange()) {
+ deleteSelection(editingState, false, false);
+ if (editingState->isAborted())
+ return;
+ }
// This is a scenario that should never happen, but we want to
// make sure we don't dereference a null pointer below.
@@ -191,11 +194,15 @@
setNodeAttribute(clonedChild, startAttr, AtomicString::number(toLayoutListItem(listChildNode->layoutObject())->value()));
}
- appendNode(clonedChild.get(), clonedAncestor.get());
+ appendNode(clonedChild.get(), clonedAncestor.get(), editingState);
+ if (editingState->isAborted())
+ return;
clonedAncestor = clonedChild;
}
- moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor);
+ moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor, editingState);
+ if (editingState->isAborted())
+ return;
if (!ancestors.isEmpty()) {
// Split the tree up the ancestor chain until the topBlockquote
@@ -206,13 +213,19 @@
RefPtrWillBeRawPtr<Element> clonedParent = nullptr;
for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parentElement();
ancestor && ancestor != topBlockquote;
- ancestor = ancestor->parentElement(), clonedParent = clonedParent->parentElement())
- moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedParent);
+ ancestor = ancestor->parentElement(), clonedParent = clonedParent->parentElement()) {
+ moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedParent, editingState);
+ if (editingState->isAborted())
+ return;
+ }
// If the startNode's original parent is now empty, remove it
Element* originalParent = ancestors.first().get();
- if (!originalParent->hasChildren())
- removeNode(originalParent);
+ if (!originalParent->hasChildren()) {
+ removeNode(originalParent, editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
// Make sure the cloned block quote renders.
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
index 9968645..34eb4d88 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -388,7 +388,7 @@
applyCommandToComposite(AppendNodeCommand::create(parent, node));
}
-void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> node, unsigned from, unsigned to)
+void CompositeEditCommand::removeChildrenInRange(PassRefPtrWillBeRawPtr<Node> node, unsigned from, unsigned to, EditingState* editingState)
{
WillBeHeapVector<RefPtrWillBeMember<Node>> children;
Node* child = NodeTraversal::childAt(*node, from);
@@ -396,8 +396,11 @@
children.append(child);
size_t size = children.size();
- for (size_t i = 0; i < size; ++i)
- removeNode(children[i].release());
+ for (size_t i = 0; i < size; ++i) {
+ removeNode(children[i].release(), editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
void CompositeEditCommand::removeNode(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
@@ -414,15 +417,17 @@
applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, shouldAssumeContentIsAlwaysEditable), editingState);
}
-void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, Node* excludeNode)
{
ASSERT(node.get() != excludeNode);
RefPtrWillBeRawPtr<ContainerNode> parent = node->parentNode();
- removeNode(node);
- prune(parent.release(), excludeNode);
+ removeNode(node, editingState);
+ if (editingState->isAborted())
+ return;
+ prune(parent.release(), editingState, excludeNode);
}
-void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent)
+void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent, EditingState* editingState)
{
NodeVector nodesToRemove;
RefPtrWillBeRawPtr<Element> newParent = prpNewParent;
@@ -431,8 +436,12 @@
nodesToRemove.append(node);
for (unsigned i = 0; i < nodesToRemove.size(); i++) {
- removeNode(nodesToRemove[i]);
- appendNode(nodesToRemove[i], newParent);
+ removeNode(nodesToRemove[i], editingState);
+ if (editingState->isAborted())
+ return;
+ appendNode(nodesToRemove[i], newParent, editingState);
+ if (editingState->isAborted())
+ return;
}
}
@@ -459,10 +468,10 @@
return command->spanElement();
}
-void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, Node* excludeNode)
+void CompositeEditCommand::prune(PassRefPtrWillBeRawPtr<Node> node, EditingState* editingState, Node* excludeNode)
{
if (RefPtrWillBeRawPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get(), excludeNode))
- removeNode(highestNodeToRemove.release());
+ removeNode(highestNodeToRemove.release(), editingState);
}
void CompositeEditCommand::splitTextNode(PassRefPtrWillBeRawPtr<Text> node, unsigned offset)
@@ -475,16 +484,18 @@
applyCommandToComposite(SplitElementCommand::create(element, atChild));
}
-void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond)
+void CompositeEditCommand::mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element> prpFirst, PassRefPtrWillBeRawPtr<Element> prpSecond, EditingState* editingState)
{
RefPtrWillBeRawPtr<Element> first = prpFirst;
RefPtrWillBeRawPtr<Element> second = prpSecond;
ASSERT(!first->isDescendantOf(second.get()) && second != first);
if (first->nextSibling() != second) {
- removeNode(second);
+ removeNode(second, editingState);
+ if (editingState->isAborted())
+ return;
insertNodeAfter(second, first);
}
- applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second));
+ applyCommandToComposite(MergeIdenticalElementsCommand::create(first, second), editingState);
}
void CompositeEditCommand::wrapContentsInDummySpan(PassRefPtrWillBeRawPtr<Element> element)
@@ -776,7 +787,8 @@
if (!box) {
// whole text node is empty
- removeNode(textNode);
+ // Removing a Text node won't dispatch synchronous events.
+ removeNode(textNode, ASSERT_NO_EDITING_ABORT);
return;
}
@@ -917,7 +929,8 @@
// We are certain that the position is at a line break, but it may be a br or a preserved newline.
if (isHTMLBRElement(*p.anchorNode())) {
- removeNode(p.anchorNode());
+ // Removing a BR element won't dispatch synchronous events.
+ removeNode(p.anchorNode(), ASSERT_NO_EDITING_ABORT);
return;
}
@@ -1107,7 +1120,7 @@
// Deleting a paragraph will leave a placeholder. Remove it (and prune
// empty or unrendered parents).
-void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination)
+void CompositeEditCommand::cleanupAfterDeletion(EditingState* editingState, VisiblePosition destination)
{
VisiblePosition caretAfterDelete = endingSelection().visibleStart();
Node* destinationNode = destination.deepEquivalent().anchorNode();
@@ -1122,7 +1135,7 @@
// Normally deletion will leave a br as a placeholder.
if (isHTMLBRElement(*node)) {
- removeNodeAndPruneAncestors(node, destinationNode);
+ removeNodeAndPruneAncestors(node, editingState, destinationNode);
// If the selection to move was empty and in an empty block that
// doesn't require a placeholder to prop itself open (like a bordered
@@ -1132,16 +1145,16 @@
// If caret position after deletion and destination position coincides,
// node should not be removed.
if (!rendersInDifferentPosition(position, destination.deepEquivalent())) {
- prune(node, destinationNode);
+ prune(node, editingState, destinationNode);
return;
}
- removeNodeAndPruneAncestors(node, destinationNode);
+ removeNodeAndPruneAncestors(node, editingState, destinationNode);
} else if (lineBreakExistsAtPosition(position)) {
// There is a preserved '\n' at caretAfterDelete.
// We can safely assume this is a text node.
Text* textNode = toText(node);
if (textNode->length() == 1)
- removeNodeAndPruneAncestors(node, destinationNode);
+ removeNodeAndPruneAncestors(node, editingState, destinationNode);
else
deleteTextFromNode(textNode, position.computeOffsetInContainerNode(), 1);
}
@@ -1180,7 +1193,9 @@
// It expands and removes the entire table/list, but will let content
// before and after the table/list collapse onto one line.
- cleanupAfterDeletion();
+ cleanupAfterDeletion(editingState);
+ if (editingState->isAborted())
+ return;
// Add a br if pruning an empty block level element caused a collapse. For example:
// foo^
@@ -1269,7 +1284,9 @@
return;
ASSERT(destination.deepEquivalent().inDocument());
- cleanupAfterDeletion(destination);
+ cleanupAfterDeletion(editingState, destination);
+ if (editingState->isAborted())
+ return;
ASSERT(destination.deepEquivalent().inDocument());
// Add a br if pruning an empty block level element caused a collapse. For example:
@@ -1326,7 +1343,7 @@
}
// FIXME: Send an appropriate shouldDeleteRange call.
-bool CompositeEditCommand::breakOutOfEmptyListItem()
+bool CompositeEditCommand::breakOutOfEmptyListItem(EditingState* editingState)
{
RefPtrWillBeRawPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibleStart());
if (!emptyListItem)
@@ -1373,13 +1390,19 @@
// If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
// Because we have splitted the element, emptyListItem is the first element in the list node.
// i.e. insert newBlock before ul or ol whose first element is emptyListItem
- insertNodeBefore(newBlock, listNode);
- removeNode(emptyListItem);
+ insertNodeBefore(newBlock, listNode, editingState);
+ if (editingState->isAborted())
+ return false;
+ removeNode(emptyListItem, editingState);
+ if (editingState->isAborted())
+ return false;
} else {
// When emptyListItem does not follow any list item or nested list, insert newBlock after the enclosing list node.
// Remove the enclosing node if emptyListItem is the only child; otherwise just remove emptyListItem.
insertNodeAfter(newBlock, listNode);
- removeNode(isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get());
+ removeNode(isListItem(previousListNode.get()) || isHTMLListElement(previousListNode.get()) ? emptyListItem.get() : listNode.get(), editingState);
+ if (editingState->isAborted())
+ return false;
}
appendBlockPlaceholder(newBlock);
@@ -1394,7 +1417,7 @@
// If the caret is in an empty quoted paragraph, and either there is nothing before that
// paragraph, or what is before is unquoted, and the user presses delete, unquote that paragraph.
-bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
+bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph(EditingState* editingState)
{
if (!endingSelection().isCaret())
return false;
@@ -1415,12 +1438,17 @@
RefPtrWillBeRawPtr<HTMLBRElement> br = HTMLBRElement::create(document());
// 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, highestBlockquote);
+ insertNodeBefore(br, highestBlockquote, editingState);
+ if (editingState->isAborted())
+ return false;
VisiblePosition atBR = createVisiblePosition(positionBeforeNode(br.get()));
// If the br we inserted collapsed, for example foo<br><blockquote>...</blockquote>, insert
// a second one.
- if (!isStartOfParagraph(atBR))
- insertNodeBefore(HTMLBRElement::create(document()), br);
+ if (!isStartOfParagraph(atBR)) {
+ insertNodeBefore(HTMLBRElement::create(document()), br, editingState);
+ if (editingState->isAborted())
+ return false;
+ }
setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()));
// If this is an empty paragraph there must be a line break here.
@@ -1432,7 +1460,9 @@
ASSERT(isHTMLBRElement(caretPos.anchorNode()) || (caretPos.anchorNode()->isTextNode() && caretPos.anchorNode()->layoutObject()->style()->preserveNewline()));
if (isHTMLBRElement(*caretPos.anchorNode())) {
- removeNodeAndPruneAncestors(caretPos.anchorNode());
+ removeNodeAndPruneAncestors(caretPos.anchorNode(), editingState);
+ if (editingState->isAborted())
+ return false;
} else if (caretPos.anchorNode()->isTextNode()) {
ASSERT(caretPos.computeOffsetInContainerNode() == 0);
Text* textNode = toText(caretPos.anchorNode());
@@ -1440,7 +1470,9 @@
// The preserved newline must be the first thing in the node, since otherwise the previous
// paragraph would be quoted, and we verified that it wasn't above.
deleteTextFromNode(textNode, 0, 1);
- prune(parentNode);
+ prune(parentNode, editingState);
+ if (editingState->isAborted())
+ return false;
}
return true;
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
index 7bcefc8..141ad34 100644
--- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.h
@@ -114,7 +114,7 @@
void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, PassRefPtrWillBeRawPtr<Node> refChild, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
void insertParagraphSeparator(bool useDefaultParagraphElement = false, bool pasteBlockqutoeIntoUnquotedArea = false);
void insertTextIntoNode(PassRefPtrWillBeRawPtr<Text>, unsigned offset, const String& text);
- void mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element>);
+ void mergeIdenticalElements(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element>, EditingState*);
void rebalanceWhitespace();
void rebalanceWhitespaceAt(const Position&);
void rebalanceWhitespaceOnTextSubstring(PassRefPtrWillBeRawPtr<Text>, int startOffset, int endOffset);
@@ -124,14 +124,14 @@
bool shouldRebalanceLeadingWhitespaceFor(const String&) const;
void removeCSSProperty(PassRefPtrWillBeRawPtr<Element>, CSSPropertyID);
void removeElementAttribute(PassRefPtrWillBeRawPtr<Element>, const QualifiedName& attribute);
- void removeChildrenInRange(PassRefPtrWillBeRawPtr<Node>, unsigned from, unsigned to);
- virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
+ void removeChildrenInRange(PassRefPtrWillBeRawPtr<Node>, unsigned from, unsigned to, EditingState*);
+ virtual void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState*, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
HTMLSpanElement* replaceElementWithSpanPreservingChildrenAndAttributes(PassRefPtrWillBeRawPtr<HTMLElement>);
void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable);
- void removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node>, Node* excludeNode = nullptr);
- void moveRemainingSiblingsToNewParent(Node*, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent);
+ void removeNodeAndPruneAncestors(PassRefPtrWillBeRawPtr<Node>, EditingState*, Node* excludeNode = nullptr);
+ void moveRemainingSiblingsToNewParent(Node*, Node* pastLastNodeToMove, PassRefPtrWillBeRawPtr<Element> prpNewParent, EditingState*);
void updatePositionForNodeRemovalPreservingChildren(Position&, Node&);
- void prune(PassRefPtrWillBeRawPtr<Node>, Node* excludeNode = nullptr);
+ void prune(PassRefPtrWillBeRawPtr<Node>, EditingState*, Node* excludeNode = nullptr);
void replaceTextInNode(PassRefPtrWillBeRawPtr<Text>, unsigned offset, unsigned count, const String& replacementText);
Position replaceSelectedTextInNode(const String&);
void replaceTextInNodePreservingMarkers(PassRefPtrWillBeRawPtr<Text>, unsigned offset, unsigned count, const String& replacementText);
@@ -162,10 +162,10 @@
void moveParagraphs(const VisiblePosition&, const VisiblePosition&, const VisiblePosition&, EditingState*, bool preserveSelection = false, bool preserveStyle = true, Node* constrainingAncestor = nullptr);
void moveParagraphWithClones(const VisiblePosition& startOfParagraphToMove, const VisiblePosition& endOfParagraphToMove, HTMLElement* blockElement, Node* outerNode, EditingState* = ASSERT_NO_EDITING_ABORT);
void cloneParagraphUnderNewElement(const Position& start, const Position& end, Node* outerNode, Element* blockElement, EditingState*);
- void cleanupAfterDeletion(VisiblePosition destination = VisiblePosition());
+ void cleanupAfterDeletion(EditingState*, VisiblePosition destination = VisiblePosition());
- bool breakOutOfEmptyListItem();
- bool breakOutOfEmptyMailBlockquotedParagraph();
+ bool breakOutOfEmptyListItem(EditingState*);
+ bool breakOutOfEmptyMailBlockquotedParagraph(EditingState*);
Position positionAvoidingSpecialElementBoundary(const Position&, EditingState*);
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index cd8700f7..da914f1 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -300,7 +300,7 @@
m_deleteIntoBlockquoteStyle = nullptr;
}
-bool DeleteSelectionCommand::handleSpecialCaseBRDelete()
+bool DeleteSelectionCommand::handleSpecialCaseBRDelete(EditingState* editingState)
{
Node* nodeAfterUpstreamStart = m_upstreamStart.computeNodeAfterPosition();
Node* nodeAfterDownstreamStart = m_downstreamStart.computeNodeAfterPosition();
@@ -315,7 +315,7 @@
bool downstreamStartIsBR = isHTMLBRElement(*nodeAfterDownstreamStart);
bool isBROnLineByItself = upstreamStartIsBR && downstreamStartIsBR && nodeAfterDownstreamStart == nodeAfterUpstreamEnd;
if (isBROnLineByItself) {
- removeNode(nodeAfterDownstreamStart);
+ removeNode(nodeAfterDownstreamStart, editingState);
return true;
}
@@ -431,7 +431,7 @@
CompositeEditCommand::deleteTextFromNode(node, offset, count);
}
-void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss()
+void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(EditingState* editingState)
{
RefPtrWillBeRawPtr<Range> range = createRange(m_selectionToDelete.toNormalizedEphemeralRange());
RefPtrWillBeRawPtr<Node> node = range->firstNode();
@@ -441,8 +441,12 @@
nextNode = NodeTraversal::nextSkippingChildren(*node);
RefPtrWillBeRawPtr<Element> rootEditableElement = node->rootEditableElement();
if (rootEditableElement.get()) {
- removeNode(node);
- appendNode(node, rootEditableElement);
+ removeNode(node, editingState);
+ if (editingState->isAborted())
+ return;
+ appendNode(node, rootEditableElement, editingState);
+ if (editingState->isAborted())
+ return;
}
}
node = nextNode;
@@ -458,7 +462,9 @@
Node* startNode = m_upstreamStart.anchorNode();
ASSERT(startNode);
- makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss();
+ makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(editingState);
+ if (editingState->isAborted())
+ return;
// Never remove the start block unless it's a table, in which case we won't merge content in.
if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChildrenForEditing(startNode) && !isHTMLTableElement(*startNode)) {
@@ -490,7 +496,9 @@
Text* text = toText(startNode);
deleteTextFromNode(text, startOffset, m_downstreamEnd.computeOffsetInContainerNode() - startOffset);
} else {
- removeChildrenInRange(startNode, startOffset, m_downstreamEnd.computeEditingOffset());
+ removeChildrenInRange(startNode, startOffset, m_downstreamEnd.computeEditingOffset(), editingState);
+ if (editingState->isAborted())
+ return;
m_endingPosition = m_upstreamStart;
}
}
@@ -573,7 +581,9 @@
if (n)
offset = n->nodeIndex() + 1;
}
- removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset());
+ removeChildrenInRange(m_downstreamEnd.anchorNode(), offset, m_downstreamEnd.computeEditingOffset(), editingState);
+ if (editingState->isAborted())
+ return;
m_downstreamEnd = Position::editingPositionOf(m_downstreamEnd.anchorNode(), offset);
}
}
@@ -601,12 +611,14 @@
// If a selection starts in one block and ends in another, we have to merge to bring content before the
// start together with content after the end.
-void DeleteSelectionCommand::mergeParagraphs()
+void DeleteSelectionCommand::mergeParagraphs(EditingState* editingState)
{
if (!m_mergeBlocksAfterDelete) {
if (m_pruneStartBlockIfNecessary) {
// We aren't going to merge into the start block, so remove it if it's empty.
- prune(m_startBlock);
+ prune(m_startBlock, editingState);
+ if (editingState->isAborted())
+ return;
// Removing the start block during a deletion is usually an indication that we need
// a placeholder, but not in this case.
m_needPlaceholder = false;
@@ -636,13 +648,15 @@
// move, so just remove it.
Element* endBlock = enclosingBlock(m_downstreamEnd.anchorNode());
if (!endBlock || !endBlock->contains(startOfParagraphToMove.deepEquivalent().anchorNode()) || !startOfParagraphToMove.deepEquivalent().anchorNode()) {
- removeNode(enclosingBlock(m_downstreamEnd.anchorNode()));
+ removeNode(enclosingBlock(m_downstreamEnd.anchorNode()), editingState);
return;
}
// We need to merge into m_upstreamStart's block, but it's been emptied out and collapsed by deletion.
if (!mergeDestination.deepEquivalent().anchorNode() || (!mergeDestination.deepEquivalent().anchorNode()->isDescendantOf(enclosingBlock(m_upstreamStart.computeContainerNode())) && (!mergeDestination.deepEquivalent().anchorNode()->hasChildren() || !m_upstreamStart.computeContainerNode()->hasChildren())) || (m_startsAtEmptyLine && mergeDestination.deepEquivalent() != startOfParagraphToMove.deepEquivalent())) {
- insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart);
+ insertNodeAt(HTMLBRElement::create(document()).get(), m_upstreamStart, editingState);
+ if (editingState->isAborted())
+ return;
mergeDestination = createVisiblePosition(m_upstreamStart);
}
@@ -660,7 +674,9 @@
if (listItemInFirstParagraph && listItemInSecondParagraph
&& listItemInFirstParagraph->parentElement() != listItemInSecondParagraph->parentElement()
&& canMergeLists(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement())) {
- mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement());
+ mergeIdenticalElements(listItemInFirstParagraph->parentElement(), listItemInSecondParagraph->parentElement(), editingState);
+ if (editingState->isAborted())
+ return;
m_endingPosition = mergeDestination.deepEquivalent();
return;
}
@@ -669,7 +685,9 @@
// FIXME: Consider RTL.
if (!m_startsAtEmptyLine && isStartOfParagraph(mergeDestination) && absoluteCaretBoundsOf(startOfParagraphToMove).x() > absoluteCaretBoundsOf(mergeDestination).x()) {
if (isHTMLBRElement(*mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode())) {
- removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode());
+ removeNodeAndPruneAncestors(mostForwardCaretPosition(mergeDestination.deepEquivalent()).anchorNode(), editingState);
+ if (editingState->isAborted())
+ return;
m_endingPosition = startOfParagraphToMove.deepEquivalent();
return;
}
@@ -687,13 +705,15 @@
// removals that it does cause the insertion of *another* placeholder.
bool needPlaceholder = m_needPlaceholder;
bool paragraphToMergeIsEmpty = startOfParagraphToMove.deepEquivalent() == endOfParagraphToMove.deepEquivalent();
- moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, ASSERT_NO_EDITING_ABORT, false, !paragraphToMergeIsEmpty);
+ moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, editingState, false, !paragraphToMergeIsEmpty);
+ if (editingState->isAborted())
+ return;
m_needPlaceholder = needPlaceholder;
// The endingPosition was likely clobbered by the move, so recompute it (moveParagraph selects the moved paragraph).
m_endingPosition = endingSelection().start();
}
-void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows()
+void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows(EditingState* editingState)
{
if (m_endTableRow && m_endTableRow->inDocument() && m_endTableRow != m_startTableRow) {
Node* row = m_endTableRow->previousSibling();
@@ -703,7 +723,9 @@
// Use a raw removeNode, instead of DeleteSelectionCommand's,
// because that won't remove rows, it only empties them in
// preparation for this function.
- CompositeEditCommand::removeNode(row);
+ CompositeEditCommand::removeNode(row, editingState);
+ if (editingState->isAborted())
+ return;
}
row = previousRow.get();
}
@@ -714,8 +736,11 @@
Node* row = m_startTableRow->nextSibling();
while (row && row != m_endTableRow) {
RefPtrWillBeRawPtr<Node> nextRow = row->nextSibling();
- if (isTableRowEmpty(row))
- CompositeEditCommand::removeNode(row);
+ if (isTableRowEmpty(row)) {
+ CompositeEditCommand::removeNode(row, editingState);
+ if (editingState->isAborted())
+ return;
+ }
row = nextRow.get();
}
}
@@ -729,7 +754,9 @@
// fully selected, even if it is empty. We'll need to start
// adjusting the selection endpoints during deletion to know
// whether or not m_endTableRow was fully selected here.
- CompositeEditCommand::removeNode(m_endTableRow.get());
+ CompositeEditCommand::removeNode(m_endTableRow.get(), editingState);
+ if (editingState->isAborted())
+ return;
}
}
}
@@ -842,7 +869,10 @@
// deleting just a BR is handled specially, at least because we do not
// want to replace it with a placeholder BR!
- if (handleSpecialCaseBRDelete()) {
+ bool brResult = handleSpecialCaseBRDelete(editingState);
+ if (editingState->isAborted())
+ return;
+ if (brResult) {
calculateTypingStyleAfterDelete();
setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSelection().isDirectional()));
clearTransientState();
@@ -856,9 +886,13 @@
fixupWhitespace();
- mergeParagraphs();
+ mergeParagraphs(editingState);
+ if (editingState->isAborted())
+ return;
- removePreviouslySelectedEmptyTableRows();
+ removePreviouslySelectedEmptyTableRows(editingState);
+ if (editingState->isAborted())
+ return;
if (!m_needPlaceholder && rootWillStayOpenWithoutPlaceholder) {
VisiblePosition visualEnding = createVisiblePosition(m_endingPosition);
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
index 6e8ea714..af4e2c70b 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.h
@@ -59,15 +59,15 @@
void setStartingSelectionOnSmartDelete(const Position&, const Position&);
void initializePositionData();
void saveTypingStyleState();
- bool handleSpecialCaseBRDelete();
+ bool handleSpecialCaseBRDelete(EditingState*);
void handleGeneralDelete(EditingState*);
void fixupWhitespace();
- void mergeParagraphs();
- void removePreviouslySelectedEmptyTableRows();
+ void mergeParagraphs(EditingState*);
+ void removePreviouslySelectedEmptyTableRows(EditingState*);
void calculateTypingStyleAfterDelete();
void clearTransientState();
- void makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss();
- void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState* = ASSERT_NO_EDITING_ABORT, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override;
+ void makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(EditingState*);
+ void removeNode(PassRefPtrWillBeRawPtr<Node>, EditingState*, ShouldAssumeContentIsAlwaysEditable = DoNotAssumeContentIsAlwaysEditable) override;
void deleteTextFromNode(PassRefPtrWillBeRawPtr<Text>, unsigned, unsigned) override;
void removeRedundantBlocks(EditingState*);
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
index 6101908..b1145df 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.cpp
@@ -66,7 +66,7 @@
{
}
-bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const Position& end)
+bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const Position& end, EditingState* editingState)
{
// If our selection is not inside a list, bail out.
RefPtrWillBeRawPtr<Node> lastNodeInSelectedParagraph = start.anchorNode();
@@ -89,22 +89,34 @@
// list element will change visibility of list item, e.g. :first-child
// CSS selector.
RefPtrWillBeRawPtr<HTMLElement> newList = toHTMLElement(document().createElement(listElement->tagQName(), false).get());
- insertNodeBefore(newList, selectedListItem.get());
+ insertNodeBefore(newList, selectedListItem.get(), editingState);
+ if (editingState->isAborted())
+ return false;
// We should clone all the children of the list item for indenting purposes. However, in case the current
// selection does not encompass all its children, we need to explicitally handle the same. The original
// list item too would require proper deletion in that case.
if (end.anchorNode() == selectedListItem.get() || end.anchorNode()->isDescendantOf(selectedListItem->lastChild())) {
- moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(end), newList.get(), selectedListItem.get());
+ moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(end), newList.get(), selectedListItem.get(), editingState);
} else {
- moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(positionAfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get());
- removeNode(selectedListItem.get());
+ moveParagraphWithClones(createVisiblePosition(start), createVisiblePosition(positionAfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get(), editingState);
+ if (editingState->isAborted())
+ return false;
+ removeNode(selectedListItem.get(), editingState);
}
+ if (editingState->isAborted())
+ return false;
- if (canMergeLists(previousList.get(), newList.get()))
- mergeIdenticalElements(previousList.get(), newList.get());
- if (canMergeLists(newList.get(), nextList.get()))
- mergeIdenticalElements(newList.get(), nextList.get());
+ if (canMergeLists(previousList.get(), newList.get())) {
+ mergeIdenticalElements(previousList.get(), newList.get(), editingState);
+ if (editingState->isAborted())
+ return false;
+ }
+ if (canMergeLists(newList.get(), nextList.get())) {
+ mergeIdenticalElements(newList.get(), nextList.get(), editingState);
+ if (editingState->isAborted())
+ return false;
+ }
return true;
}
@@ -261,7 +273,10 @@
void IndentOutdentCommand::formatRange(const Position& start, const Position& end, const Position&, RefPtrWillBeRawPtr<HTMLElement>& blockquoteForNextIndent, EditingState* editingState)
{
- if (tryIndentingAsListItem(start, end))
+ bool indentingAsListItemResult = tryIndentingAsListItem(start, end, editingState);
+ if (editingState->isAborted())
+ return;
+ if (indentingAsListItemResult)
blockquoteForNextIndent = nullptr;
else
indentIntoBlockquote(start, end, blockquoteForNextIndent, editingState);
diff --git a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
index 227aa6cf..da5ceab 100644
--- a/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/IndentOutdentCommand.h
@@ -48,7 +48,7 @@
void outdentRegion(const VisiblePosition&, const VisiblePosition&);
void outdentParagraph();
- bool tryIndentingAsListItem(const Position&, const Position&);
+ bool tryIndentingAsListItem(const Position&, const Position&, EditingState*);
void indentIntoBlockquote(const Position&, const Position&, RefPtrWillBeRawPtr<HTMLElement>&, EditingState*);
void formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection, EditingState*) override;
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index bdfaddb..76c69cd 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -50,21 +50,30 @@
return listChild;
}
-HTMLUListElement* InsertListCommand::fixOrphanedListChild(Node* node)
+HTMLUListElement* InsertListCommand::fixOrphanedListChild(Node* node, EditingState* editingState)
{
RefPtrWillBeRawPtr<HTMLUListElement> listElement = HTMLUListElement::create(document());
- insertNodeBefore(listElement, node);
- removeNode(node);
- appendNode(node, listElement);
+ insertNodeBefore(listElement, node, editingState);
+ if (editingState->isAborted())
+ return nullptr;
+ removeNode(node, editingState);
+ if (editingState->isAborted())
+ return nullptr;
+ appendNode(node, listElement, editingState);
+ if (editingState->isAborted())
+ return nullptr;
return listElement.get();
}
-PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement> passedList)
+PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement> passedList, EditingState* editingState)
{
RefPtrWillBeRawPtr<HTMLElement> list = passedList;
Element* previousList = ElementTraversal::previousSibling(*list);
- if (canMergeLists(previousList, list.get()))
- mergeIdenticalElements(previousList, list);
+ if (canMergeLists(previousList, list.get())) {
+ mergeIdenticalElements(previousList, list, editingState);
+ if (editingState->isAborted())
+ return nullptr;
+ }
if (!list)
return nullptr;
@@ -75,7 +84,9 @@
RefPtrWillBeRawPtr<HTMLElement> nextList = toHTMLElement(nextSibling);
if (canMergeLists(list.get(), nextList.get())) {
- mergeIdenticalElements(list, nextList);
+ mergeIdenticalElements(list, nextList, editingState);
+ if (editingState->isAborted())
+ return nullptr;
return nextList.release();
}
return list.release();
@@ -237,8 +248,12 @@
}
}
if (!listElement) {
- listElement = fixOrphanedListChild(listChildNode);
- listElement = mergeWithNeighboringLists(listElement);
+ listElement = fixOrphanedListChild(listChildNode, editingState);
+ if (editingState->isAborted())
+ return false;
+ listElement = mergeWithNeighboringLists(listElement, editingState);
+ if (editingState->isAborted())
+ return false;
}
ASSERT(listElement->hasEditableStyle());
ASSERT(listElement->parentNode()->hasEditableStyle());
@@ -259,20 +274,29 @@
bool rangeEndIsInList = visiblePositionAfterNode(*listElement).deepEquivalent() == createVisiblePosition(currentSelection.endPosition()).deepEquivalent();
RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document(), listTag);
- insertNodeBefore(newList, listElement);
+ insertNodeBefore(newList, listElement, editingState);
+ if (editingState->isAborted())
+ return false;
Node* firstChildInList = enclosingListChild(createVisiblePosition(firstPositionInNode(listElement.get())).deepEquivalent().anchorNode(), listElement.get());
Element* outerBlock = firstChildInList && isBlockFlowElement(*firstChildInList) ? toElement(firstChildInList) : listElement.get();
- moveParagraphWithClones(createVisiblePosition(firstPositionInNode(listElement.get())), createVisiblePosition(lastPositionInNode(listElement.get())), newList.get(), outerBlock);
+ moveParagraphWithClones(createVisiblePosition(firstPositionInNode(listElement.get())), createVisiblePosition(lastPositionInNode(listElement.get())), newList.get(), outerBlock, editingState);
+ if (editingState->isAborted())
+ return false;
// Manually remove listNode because moveParagraphWithClones sometimes leaves it behind in the document.
// See the bug 33668 and editing/execCommand/insert-list-orphaned-item-with-nested-lists.html.
// FIXME: This might be a bug in moveParagraphWithClones or deleteSelection.
- if (listElement && listElement->inDocument())
- removeNode(listElement);
+ if (listElement && listElement->inDocument()) {
+ removeNode(listElement, editingState);
+ if (editingState->isAborted())
+ return false;
+ }
- newList = mergeWithNeighboringLists(newList);
+ newList = mergeWithNeighboringLists(newList, editingState);
+ if (editingState->isAborted())
+ return false;
// Restore the start and the end of current selection if they started inside listNode
// because moveParagraphWithClones could have removed them.
@@ -401,7 +425,7 @@
return;
if (canMergeLists(previousList, nextList))
- mergeIdenticalElements(previousList, nextList);
+ mergeIdenticalElements(previousList, nextList, editingState);
return;
}
@@ -448,7 +472,7 @@
if (editingState->isAborted())
return;
- mergeWithNeighboringLists(listElement);
+ mergeWithNeighboringLists(listElement, editingState);
}
void InsertListCommand::moveParagraphOverPositionIntoEmptyListItem(const VisiblePosition& pos, PassRefPtrWillBeRawPtr<HTMLLIElement> listItemElement, EditingState* editingState)
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
index c70b5c8..6981ad0 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.h
@@ -52,9 +52,9 @@
void doApply(EditingState*) override;
EditAction editingAction() const override { return EditActionInsertList; }
- HTMLUListElement* fixOrphanedListChild(Node*);
+ HTMLUListElement* fixOrphanedListChild(Node*, EditingState*);
bool selectionHasListOfType(const VisibleSelection&, const HTMLQualifiedName&);
- PassRefPtrWillBeRawPtr<HTMLElement> mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement>);
+ PassRefPtrWillBeRawPtr<HTMLElement> mergeWithNeighboringLists(PassRefPtrWillBeRawPtr<HTMLElement>, EditingState*);
bool doApplyForSingleParagraph(bool forceCreateList, const HTMLQualifiedName&, Range& currentSelection, EditingState*);
void unlistifyParagraph(const VisiblePosition& originalStart, HTMLElement* listNode, Node* listChildNode);
void listifyParagraph(const VisiblePosition& originalStart, const HTMLQualifiedName& listTag, EditingState*);
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
index a2297835..36b5938 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -148,7 +148,7 @@
return parent.release();
}
-void InsertParagraphSeparatorCommand::doApply(EditingState*)
+void InsertParagraphSeparatorCommand::doApply(EditingState* editingState)
{
if (!endingSelection().isNonOrphanedCaretOrRange())
return;
@@ -193,7 +193,7 @@
//---------------------------------------------------------------------
// Handle special case of typing return on an empty list item
- if (breakOutOfEmptyListItem())
+ if (breakOutOfEmptyListItem(editingState) || editingState->isAborted())
return;
//---------------------------------------------------------------------
@@ -410,7 +410,9 @@
}
}
- moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert);
+ moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert, editingState);
+ if (editingState->isAborted())
+ return;
}
// Handle whitespace that occurs after the split
diff --git a/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
index c1d2518..4a3af35 100644
--- a/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/MoveSelectionCommand.cpp
@@ -36,7 +36,7 @@
ASSERT(m_fragment);
}
-void MoveSelectionCommand::doApply(EditingState*)
+void MoveSelectionCommand::doApply(EditingState* editingState)
{
ASSERT(endingSelection().isNonOrphanedRange());
@@ -55,7 +55,9 @@
pos = Position(pos.computeContainerNode(), pos.offsetInContainerNode() + selectionStart.offsetInContainerNode());
}
- deleteSelection(ASSERT_NO_EDITING_ABORT, m_smartDelete);
+ deleteSelection(editingState, m_smartDelete);
+ if (editingState->isAborted())
+ return;
// If the node for the destination has been removed as a result of the deletion,
// set the destination to the ending point after the deletion.
@@ -64,7 +66,9 @@
if (!pos.inDocument())
pos = endingSelection().start();
- cleanupAfterDeletion(createVisiblePosition(pos));
+ cleanupAfterDeletion(editingState, createVisiblePosition(pos));
+ if (editingState->isAborted())
+ return;
setEndingSelection(VisibleSelection(pos, endingSelection().affinity(), endingSelection().isDirectional()));
if (!pos.inDocument()) {
@@ -74,7 +78,7 @@
ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
if (m_smartInsert)
options |= ReplaceSelectionCommand::SmartReplace;
- applyCommandToComposite(ReplaceSelectionCommand::create(document(), m_fragment, options));
+ applyCommandToComposite(ReplaceSelectionCommand::create(document(), m_fragment, options), editingState);
}
EditAction MoveSelectionCommand::editingAction() const
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index eb5383d..45824f2 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -633,7 +633,7 @@
return elements.contains(name);
}
-void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes& insertedNodes)
+void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes& insertedNodes, EditingState* editingState)
{
RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf();
RefPtrWillBeRawPtr<Node> next = nullptr;
@@ -649,18 +649,24 @@
HTMLElement& element = toHTMLElement(*node);
if (isProhibitedParagraphChild(element.localName())) {
- if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(element), pTag)))
- moveElementOutOfAncestor(&element, paragraphElement);
+ if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWithTag(positionInParentBeforeNode(element), pTag))) {
+ moveElementOutOfAncestor(&element, paragraphElement, editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
if (isHTMLHeaderElement(&element)) {
- if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(element), isHTMLHeaderElement)))
- moveElementOutOfAncestor(&element, headerElement);
+ if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeOfType(positionInParentBeforeNode(element), isHTMLHeaderElement))) {
+ moveElementOutOfAncestor(&element, headerElement, editingState);
+ if (editingState->isAborted())
+ return;
+ }
}
}
}
-void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor)
+void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor, EditingState* editingState)
{
RefPtrWillBeRawPtr<Element> element = prpElement;
RefPtrWillBeRawPtr<Element> ancestor = prpAncestor;
@@ -671,18 +677,26 @@
VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOrAfterNode(element.get()));
VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPositionInNode(ancestor.get()));
if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEquivalent()) {
- removeNode(element);
+ removeNode(element, editingState);
+ if (editingState->isAborted())
+ return;
if (ancestor->nextSibling())
- insertNodeBefore(element, ancestor->nextSibling());
+ insertNodeBefore(element, ancestor->nextSibling(), editingState);
else
- appendNode(element, ancestor->parentNode());
+ appendNode(element, ancestor->parentNode(), editingState);
+ if (editingState->isAborted())
+ return;
} else {
RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(), ancestor.get(), true);
- removeNode(element);
- insertNodeBefore(element, nodeToSplitTo);
+ removeNode(element, editingState);
+ if (editingState->isAborted())
+ return;
+ insertNodeBefore(element, nodeToSplitTo, editingState);
+ if (editingState->isAborted())
+ return;
}
if (!ancestor->hasChildren())
- removeNode(ancestor.release());
+ removeNode(ancestor.release(), editingState);
}
static inline bool nodeHasVisibleLayoutText(Text& text)
@@ -699,7 +713,8 @@
&& !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted), selectTag)
&& !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted), scriptTag)) {
insertedNodes.willRemoveNode(*lastLeafInserted);
- removeNode(lastLeafInserted);
+ // Removing a Text node won't dispatch synchronous events.
+ removeNode(lastLeafInserted, ASSERT_NO_EDITING_ABORT);
}
// We don't have to make sure that firstNodeInserted isn't inside a select or script element, because
@@ -707,7 +722,8 @@
Node* firstNodeInserted = insertedNodes.firstNodeInserted();
if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleLayoutText(toText(*firstNodeInserted))) {
insertedNodes.willRemoveNode(*firstNodeInserted);
- removeNode(firstNodeInserted);
+ // Removing a Text node won't dispatch synchronous events.
+ removeNode(firstNodeInserted, ASSERT_NO_EDITING_ABORT);
}
}
@@ -932,7 +948,10 @@
return;
ReplacementFragment fragment(&document(), m_documentFragment.get(), selection);
- if (performTrivialReplace(fragment))
+ bool trivialReplaceResult = performTrivialReplace(fragment, editingState);
+ if (editingState->isAborted())
+ return;
+ if (trivialReplaceResult)
return;
// We can skip matching the style if the selection is plain text.
@@ -1015,7 +1034,9 @@
ASSERT(isHTMLBRElement(br));
// Insert content between the two blockquotes, but remove the br (since it was just a placeholder).
insertionPos = positionInParentBeforeNode(*br);
- removeNode(br);
+ removeNode(br, editingState);
+ if (editingState->isAborted())
+ return;
}
// Inserting content could cause whitespace to collapse, e.g. inserting <div>foo</div> into hello^ world.
@@ -1170,14 +1191,20 @@
if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)))) {
RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode();
insertedNodes.willRemoveNode(*endBR);
- removeNode(endBR);
+ removeNode(endBR, editingState);
+ if (editingState->isAborted())
+ return;
if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) {
insertedNodes.willRemoveNode(*nodeToRemove);
- removeNode(nodeToRemove);
+ removeNode(nodeToRemove, editingState);
+ if (editingState->isAborted())
+ return;
}
}
- makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes);
+ makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes, editingState);
+ if (editingState->isAborted())
+ return;
removeRedundantStylesAndKeepStyleSpanInline(insertedNodes);
@@ -1268,7 +1295,7 @@
if (plainTextFragment)
m_matchStyle = false;
- completeHTMLReplacement(lastPositionToSelect);
+ completeHTMLReplacement(lastPositionToSelect, editingState);
}
bool ReplaceSelectionCommand::shouldRemoveEndBR(HTMLBRElement* endBR, const VisiblePosition& originalVisPosBeforeEndBR)
@@ -1362,7 +1389,7 @@
}
}
-void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositionToSelect)
+void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositionToSelect, EditingState* editingState)
{
Position start = positionAtStartOfInsertedContent().deepEquivalent();
Position end = positionAtEndOfInsertedContent().deepEquivalent();
@@ -1381,7 +1408,9 @@
if (lastPositionToSelect.isNotNull())
end = lastPositionToSelect;
- mergeTextNodesAroundPosition(start, end);
+ mergeTextNodesAroundPosition(start, end, editingState);
+ if (editingState->isAborted())
+ return;
} else if (lastPositionToSelect.isNotNull()) {
start = end = lastPositionToSelect;
} else {
@@ -1397,7 +1426,7 @@
setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelection().isDirectional()));
}
-void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, Position& positionOnlyToBeUpdated)
+void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, Position& positionOnlyToBeUpdated, EditingState* editingState)
{
bool positionIsOffsetInAnchor = position.isOffsetInAnchor();
bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOffsetInAnchor();
@@ -1435,7 +1464,9 @@
updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous);
}
- removeNode(previous);
+ removeNode(previous, editingState);
+ if (editingState->isAborted())
+ return;
}
if (text->nextSibling() && text->nextSibling()->isTextNode()) {
RefPtrWillBeRawPtr<Text> next = toText(text->nextSibling());
@@ -1450,7 +1481,9 @@
else
updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next);
- removeNode(next);
+ removeNode(next, editingState);
+ if (editingState->isAborted())
+ return;
}
}
@@ -1517,7 +1550,7 @@
// directly into the text node that holds the selection. This is much faster than the generalized code in
// ReplaceSelectionCommand, and works around <https://bugs.webkit.org/show_bug.cgi?id=6148> since we don't
// split text nodes.
-bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& fragment)
+bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& fragment, EditingState* editingState)
{
if (!fragment.firstChild() || fragment.firstChild() != fragment.lastChild() || !fragment.firstChild()->isTextNode())
return false;
@@ -1540,8 +1573,11 @@
return false;
if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBRElement(*nodeAfterInsertionPos)
- && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), createVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get()))))
- removeNodeAndPruneAncestors(nodeAfterInsertionPos.get());
+ && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), createVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) {
+ removeNodeAndPruneAncestors(nodeAfterInsertionPos.get(), editingState);
+ if (editingState->isAborted())
+ return false;
+ }
m_startOfInsertedRange = start;
m_endOfInsertedRange = end;
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
index 4a36cb3..09d151d 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.h
@@ -94,8 +94,8 @@
void removeUnrenderedTextNodesAtEnds(InsertedNodes&);
void removeRedundantStylesAndKeepStyleSpanInline(InsertedNodes&);
- void makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes&);
- void moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element> ancestor);
+ void makeInsertedContentRoundTrippableWithHTMLTreeBuilder(const InsertedNodes&, EditingState*);
+ void moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<Element>, PassRefPtrWillBeRawPtr<Element> ancestor, EditingState*);
void handleStyleSpans(InsertedNodes&);
VisiblePosition positionAtStartOfInsertedContent() const;
@@ -103,10 +103,10 @@
bool shouldPerformSmartReplace() const;
void addSpacesForSmartReplace();
- void completeHTMLReplacement(const Position& lastPositionToSelect);
- void mergeTextNodesAroundPosition(Position&, Position& positionOnlyToBeUpdated);
+ void completeHTMLReplacement(const Position& lastPositionToSelect, EditingState*);
+ void mergeTextNodesAroundPosition(Position&, Position& positionOnlyToBeUpdated, EditingState*);
- bool performTrivialReplace(const ReplacementFragment&);
+ bool performTrivialReplace(const ReplacementFragment&, EditingState*);
Position m_startOfInsertedContent;
Position m_endOfInsertedContent;
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
index d2dcf2565..725c1b1b 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -386,7 +386,7 @@
typingAddedToOpenCommand(InsertParagraphSeparatorInQuotedContent);
}
-bool TypingCommand::makeEditableRootEmpty()
+bool TypingCommand::makeEditableRootEmpty(EditingState* editingState)
{
Element* root = endingSelection().rootEditableElement();
if (!root || !root->hasChildren())
@@ -400,8 +400,11 @@
}
}
- while (Node* child = root->firstChild())
- removeNode(child);
+ while (Node* child = root->firstChild()) {
+ removeNode(child, editingState);
+ if (editingState->isAborted())
+ return false;
+ }
addBlockPlaceholderIfNeeded(root);
setEndingSelection(VisibleSelection(firstPositionInNode(root), TextAffinity::Downstream, endingSelection().isDirectional()));
@@ -428,7 +431,10 @@
case CaretSelection: {
// After breaking out of an empty mail blockquote, we still want continue with the deletion
// so actual content will get deleted, and not just the quote style.
- if (breakOutOfEmptyMailBlockquotedParagraph())
+ bool breakOutResult = breakOutOfEmptyMailBlockquotedParagraph(editingState);
+ if (editingState->isAborted())
+ return;
+ if (breakOutResult)
typingAddedToOpenCommand(DeleteKey);
m_smartDelete = false;
@@ -442,15 +448,20 @@
VisiblePosition visibleStart(endingSelection().visibleStart());
if (previousPositionOf(visibleStart, CannotCrossEditingBoundary).isNull()) {
// When the caret is at the start of the editable area in an empty list item, break out of the list item.
- if (breakOutOfEmptyListItem()) {
+ bool breakOutOfEmptyListItemResult = breakOutOfEmptyListItem(editingState);
+ if (editingState->isAborted())
+ return;
+ if (breakOutOfEmptyListItemResult) {
typingAddedToOpenCommand(DeleteKey);
return;
}
// When there are no visible positions in the editing root, delete its entire contents.
- if (nextPositionOf(visibleStart, CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty()) {
+ if (nextPositionOf(visibleStart, CannotCrossEditingBoundary).isNull() && makeEditableRootEmpty(editingState)) {
typingAddedToOpenCommand(DeleteKey);
return;
}
+ if (editingState->isAborted())
+ return;
}
// If we have a caret selection at the beginning of a cell, we have nothing to do.
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
index d015e60..3e9c7104 100644
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
@@ -109,7 +109,7 @@
void updatePreservesTypingStyle(ETypingCommand);
void markMisspellingsAfterTyping(ETypingCommand);
void typingAddedToOpenCommand(ETypingCommand);
- bool makeEditableRootEmpty();
+ bool makeEditableRootEmpty(EditingState*);
void updateCommandTypeOfOpenCommand(ETypingCommand typingCommand) { m_commandType = typingCommand; }
ETypingCommand commandTypeOfOpenCommand() const { return m_commandType; }