| Index: third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
|
| index 37203396c42ee4fa818532c23845fc635c22a097..46f8df6cc36ca40aab759bc219fd55403ade226d 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 @@ void ApplyStyleCommand::applyInlineStyle(EditingStyle* style, EditingState* edit
|
| 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 @@ HTMLElement* ApplyStyleCommand::highestAncestorWithConflictingInlineStyle(Editin
|
| return result;
|
| }
|
|
|
| -void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style)
|
| +void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* style, EditingState* editingState)
|
| {
|
| ASSERT(node);
|
|
|
| @@ -1061,10 +1073,10 @@ void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
|
| // 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 @@ void ApplyStyleCommand::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
|
|
|
| // 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::pushDownInlineStyleAroundNode(EditingStyle* style, Node*
|
| }
|
| }
|
|
|
| -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 @@ void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &s
|
| 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 @@ void ApplyStyleCommand::removeInlineStyle(EditingStyle* style, const Position &s
|
| }
|
|
|
| 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 @@ bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position)
|
| 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 @@ bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start,
|
| 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 @@ bool ApplyStyleCommand::mergeStartWithPreviousIfIdentical(const Position& start,
|
| 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 @@ bool ApplyStyleCommand::mergeEndWithNextIfIdentical(const Position& start, const
|
| 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 @@ void ApplyStyleCommand::surroundNodeRangeWithElement(PassRefPtrWillBeRawPtr<Node
|
| 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 @@ void ApplyStyleCommand::addBlockStyle(const StyleChange& styleChange, HTMLElemen
|
| 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 @@ void ApplyStyleCommand::addInlineStyleIfNeeded(EditingStyle* style, PassRefPtrWi
|
| 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 @@ void ApplyStyleCommand::joinChildTextNodes(ContainerNode* node, const Position&
|
| 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.
|
| }
|
|
|
|
|