diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index 7bd0ee6bad06..e95b67424ca2 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -6225,9 +6225,16 @@ nsresult HTMLEditor::SplitParentInlineElementsAtRangeEdges( RangeItem& aRangeItem) { MOZ_ASSERT(IsEditActionDataAvailable()); - if (!aRangeItem.IsCollapsed()) { + RefPtr editingHost = GetActiveEditingHost(); + if (NS_WARN_IF(!editingHost)) { + return NS_OK; + } + + if (!aRangeItem.IsCollapsed() && aRangeItem.mEndContainer && + aRangeItem.mEndContainer->IsContent()) { nsCOMPtr mostAncestorInlineContentAtEnd = - GetMostAncestorInlineElement(*aRangeItem.mEndContainer); + HTMLEditUtils::GetMostDistantAncestorInlineElement( + *aRangeItem.mEndContainer->AsContent(), editingHost); if (mostAncestorInlineContentAtEnd) { SplitNodeResult splitEndInlineResult = SplitNodeDeepWithTransaction( @@ -6242,6 +6249,12 @@ nsresult HTMLEditor::SplitParentInlineElementsAtRangeEdges( "eDoNotCreateEmptyContainer) failed"); return splitEndInlineResult.Rv(); } + if (editingHost != GetActiveEditingHost()) { + NS_WARNING( + "HTMLEditor::SplitNodeDeepWithTransaction(SplitAtEdges::" + "eDoNotCreateEmptyContainer) caused changing editing host"); + return NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE; + } EditorRawDOMPoint splitPointAtEnd(splitEndInlineResult.SplitPoint()); if (!splitPointAtEnd.IsSet()) { NS_WARNING( @@ -6254,8 +6267,13 @@ nsresult HTMLEditor::SplitParentInlineElementsAtRangeEdges( } } + if (!aRangeItem.mStartContainer || !aRangeItem.mStartContainer->IsContent()) { + return NS_OK; + } + nsCOMPtr mostAncestorInlineContentAtStart = - GetMostAncestorInlineElement(*aRangeItem.mStartContainer); + HTMLEditUtils::GetMostDistantAncestorInlineElement( + *aRangeItem.mStartContainer->AsContent(), editingHost); if (mostAncestorInlineContentAtStart) { SplitNodeResult splitStartInlineResult = SplitNodeDeepWithTransaction( @@ -6350,47 +6368,6 @@ nsresult HTMLEditor::SplitElementsAtEveryBRElement( return NS_OK; } -nsIContent* HTMLEditor::GetMostAncestorInlineElement(nsINode& aNode) const { - MOZ_ASSERT(IsEditActionDataAvailable()); - - if (!aNode.IsContent() || HTMLEditUtils::IsBlockElement(*aNode.AsContent())) { - return nullptr; - } - - Element* host = GetActiveEditingHost(); - if (NS_WARN_IF(!host)) { - return nullptr; - } - - // If aNode is the editing host itself, there is no modifiable inline - // parent. - if (&aNode == host) { - return nullptr; - } - - // If aNode is outside of the element, we don't support to edit - // such elements for now. - // XXX This should be MOZ_ASSERT after fixing bug 1413131 for avoiding - // calling this expensive method. - if (NS_WARN_IF(!EditorUtils::IsDescendantOf(aNode, *host))) { - return nullptr; - } - - if (!aNode.GetParent()) { - return aNode.AsContent(); - } - - // Looks for the highest inline parent in the editing host. - nsIContent* topMostInlineContent = aNode.AsContent(); - for (nsIContent* content : aNode.AncestorsOfType()) { - if (content == host || !HTMLEditUtils::IsInlineElement(*content)) { - break; - } - topMostInlineContent = content; - } - return topMostInlineContent; -} - // static void HTMLEditor::MakeTransitionList( const nsTArray>& aArrayOfContents, diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp index aa9939718df5..1ac0350c8acf 100644 --- a/editor/libeditor/HTMLEditUtils.cpp +++ b/editor/libeditor/HTMLEditUtils.cpp @@ -395,7 +395,7 @@ bool HTMLEditUtils::IsVisibleTextNode( } WSScanResult nextWSScanResult = WSRunScanner::ScanNextVisibleNodeOrBlockBoundary( - const_cast(aEditingHost), EditorRawDOMPoint(&aText, 0)); + aEditingHost, EditorRawDOMPoint(&aText, 0)); return nextWSScanResult.InNormalWhiteSpacesOrText() && nextWSScanResult.TextPtr() == &aText; } diff --git a/editor/libeditor/HTMLEditUtils.h b/editor/libeditor/HTMLEditUtils.h index 6a602bd326d3..5ebf5dcbc219 100644 --- a/editor/libeditor/HTMLEditUtils.h +++ b/editor/libeditor/HTMLEditUtils.h @@ -1094,6 +1094,47 @@ class HTMLEditUtils final { static Element* GetClosestAncestorAnyListElement(const nsIContent& aContent); + /** + * GetMostDistantAncestorInlineElement() returns the most distant ancestor + * inline element between aContent and the aEditingHost. Even if aEditingHost + * is an inline element, this method never returns aEditingHost as the result. + */ + static nsIContent* GetMostDistantAncestorInlineElement( + const nsIContent& aContent, const Element* aEditingHost = nullptr) { + if (HTMLEditUtils::IsBlockElement(aContent)) { + return nullptr; + } + + // If aNode is the editing host itself, there is no modifiable inline + // parent. + if (&aContent == aEditingHost) { + return nullptr; + } + + // If aNode is outside of the element, we don't support to edit + // such elements for now. + // XXX This should be MOZ_ASSERT after fixing bug 1413131 for avoiding + // calling this expensive method. + if (aEditingHost && !aContent.IsInclusiveDescendantOf(aEditingHost)) { + return nullptr; + } + + if (!aContent.GetParent()) { + return const_cast(&aContent); + } + + // Looks for the highest inline parent in the editing host. + nsIContent* topMostInlineContent = const_cast(&aContent); + for (nsIContent* content : aContent.AncestorsOfType()) { + if (content == aEditingHost || + !HTMLEditUtils::IsInlineElement(*content)) { + break; + } + topMostInlineContent = content; + } + return topMostInlineContent; + } + /** * GetMostDistantAnscestorEditableEmptyInlineElement() returns most distant * ancestor which only has aEmptyContent or its ancestor, editable and diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index 21292dbfea73..087114191ab2 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -1096,13 +1096,6 @@ class HTMLEditor final : public TextEditor, [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult InsertBRElement(const EditorDOMPoint& aInsertToBreak); - /** - * GetMostAncestorInlineElement() returns the most ancestor inline element - * between aNode and the editing host. Even if the editing host is an inline - * element, this method never returns the editing host as the result. - */ - nsIContent* GetMostAncestorInlineElement(nsINode& aNode) const; - /** * SplitParentInlineElementsAtRangeEdges() splits parent inline nodes at both * start and end of aRangeItem. If this splits at every point, this modifies