Bug 1792387 - part 4: Make `JoinNodesTransaction` and `SplitNodeTransaction` support both join/split node directions r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 30 Sep 2022 22:20:21 +0000
changeset 636757 9f24abab5fb2e13f09239241615b23e1d6908ab2
parent 636756 953647a15a7dedd3558415f3a24cf782888e80c4
child 636758 8cc61e8fe7bc593b13e91e469f1b9028b1866d7b
push id170484
push usermasayuki@d-toybox.com
push dateFri, 30 Sep 2022 22:23:25 +0000
treeherderautoland@f4c48015c119 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1792387
milestone107.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1792387 - part 4: Make `JoinNodesTransaction` and `SplitNodeTransaction` support both join/split node directions r=m_kato The reason why the changes of `SplitNodeTransaction` is smaller than `JoinNodesTransaction` is, `HTMLEditor::DoSplitNode` does almost all things instead. Differential Revision: https://phabricator.services.mozilla.com/D158102
editor/libeditor/JoinNodesTransaction.cpp
editor/libeditor/SplitNodeTransaction.cpp
--- a/editor/libeditor/JoinNodesTransaction.cpp
+++ b/editor/libeditor/JoinNodesTransaction.cpp
@@ -35,18 +35,24 @@ already_AddRefed<JoinNodesTransaction> J
   }
   return transaction.forget();
 }
 
 JoinNodesTransaction::JoinNodesTransaction(HTMLEditor& aHTMLEditor,
                                            nsIContent& aLeftContent,
                                            nsIContent& aRightContent)
     : mHTMLEditor(&aHTMLEditor),
-      mRemovedContent(&aLeftContent),
-      mKeepingContent(&aRightContent) {
+      mRemovedContent(aHTMLEditor.GetJoinNodesDirection() ==
+                              JoinNodesDirection::LeftNodeIntoRightNode
+                          ? &aLeftContent
+                          : &aRightContent),
+      mKeepingContent(aHTMLEditor.GetJoinNodesDirection() ==
+                              JoinNodesDirection::LeftNodeIntoRightNode
+                          ? &aRightContent
+                          : &aLeftContent) {
   // printf("JoinNodesTransaction size: %zu\n", sizeof(JoinNodesTransaction));
   static_assert(sizeof(JoinNodesTransaction) <= 64,
                 "Transaction classes may be created a lot and may be alive "
                 "long so that keep the foot print smaller as far as possible");
 }
 
 std::ostream& operator<<(std::ostream& aStream,
                          const JoinNodesTransaction& aTransaction) {
@@ -126,26 +132,33 @@ nsresult JoinNodesTransaction::DoTransac
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // Set this instance's mParentNode.  Other methods will see a non-null
   // mParentNode and know all is well
   mParentNode = removingContentParentNode;
   // For now, setting mJoinedOffset to removed content length so that
   // CreateJoinedPoint returns a point in mKeepingContent whose offset is
-  // the result if all content in mRemovedContent are moved to start of
-  // mKeepingContent.  The offset will be adjusted below.
-  mJoinedOffset = mRemovedContent->Length();
+  // the result if all content in mRemovedContent are moved to start or end of
+  // mKeepingContent without any intervation.  The offset will be adjusted
+  // below.
+  mJoinedOffset =
+      GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode
+          ? mRemovedContent->Length()
+          : mKeepingContent->Length();
 
   const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
   const OwningNonNull<nsIContent> removingContent = *mRemovedContent;
   const OwningNonNull<nsIContent> keepingContent = *mKeepingContent;
   nsresult rv;
   // Let's try to get actual joined point with the tacker.
-  EditorDOMPoint joinNodesPoint(mKeepingContent, 0u);
+  EditorDOMPoint joinNodesPoint =
+      GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode
+          ? EditorDOMPoint(keepingContent, 0u)
+          : EditorDOMPoint::AtEndOf(keepingContent);
   {
     AutoTrackDOMPoint trackJoinNodePoint(htmlEditor->RangeUpdaterRef(),
                                          &joinNodesPoint);
     rv = htmlEditor->DoJoinNodes(keepingContent, removingContent,
                                  GetJoinNodesDirection());
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HTMLEditor::DoJoinNodes() failed");
   }
   // Adjust join node offset to the actual offset where the original first
@@ -169,20 +182,19 @@ NS_IMETHODIMP JoinNodesTransaction::Undo
   if (NS_WARN_IF(!mParentNode) || NS_WARN_IF(!mKeepingContent) ||
       NS_WARN_IF(!mRemovedContent) || NS_WARN_IF(!mHTMLEditor)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
   const OwningNonNull<nsIContent> removedContent = *mRemovedContent;
 
-  const SplitNodeResult splitNodeResult = htmlEditor->DoSplitNode(
-      EditorDOMPoint(mKeepingContent,
-                     std::min(mJoinedOffset, mKeepingContent->Length())),
-      removedContent, GetSplitNodeDirection());
+  const SplitNodeResult splitNodeResult =
+      htmlEditor->DoSplitNode(CreateJoinedPoint<EditorDOMPoint>(),
+                              removedContent, GetSplitNodeDirection());
   NS_WARNING_ASSERTION(splitNodeResult.isOk(),
                        "HTMLEditor::DoSplitNode() failed");
   // When adding caret suggestion to SplitNodeResult, here didn't change
   // selection so that just ignore it.
   splitNodeResult.IgnoreCaretPointSuggestion();
   return splitNodeResult.unwrapErr();
 }
 
--- a/editor/libeditor/SplitNodeTransaction.cpp
+++ b/editor/libeditor/SplitNodeTransaction.cpp
@@ -7,16 +7,17 @@
 
 #include "EditorDOMPoint.h"   // for EditorRawDOMPoint
 #include "HTMLEditHelpers.h"  // for SplitNodeResult, SplitNodeDirection, etc
 #include "HTMLEditor.h"       // for HTMLEditor
 #include "HTMLEditUtils.h"
 #include "SelectionState.h"  // for AutoTrackDOMPoint and RangeUpdater
 
 #include "mozilla/Logging.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/ToString.h"
 #include "nsAString.h"
 #include "nsDebug.h"     // for NS_ASSERTION, etc.
 #include "nsError.h"     // for NS_ERROR_NOT_INITIALIZED, etc.
 #include "nsIContent.h"  // for nsIContent
 
 namespace mozilla {
 
@@ -174,26 +175,35 @@ NS_IMETHODIMP SplitNodeTransaction::Undo
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // This assumes Do inserted the new node in front of the prior existing node
   const OwningNonNull<HTMLEditor> htmlEditor = *mHTMLEditor;
   const OwningNonNull<nsIContent> keepingContent = *mSplitContent;
   const OwningNonNull<nsIContent> removingContent = *mNewContent;
   nsresult rv;
-  EditorDOMPoint joinedPoint(keepingContent, 0u);
+  EditorDOMPoint joinedPoint;
   {
-    AutoTrackDOMPoint trackJoinedPoint(htmlEditor->RangeUpdaterRef(),
-                                       &joinedPoint);
+    // Unfortunately, we cannot track joining point if moving right node content
+    // into left node since it cannot track changes from web apps and HTMLEditor
+    // never removes the content of the left node.  So it should be true that
+    // we don't need to track the point in the direction.
+    Maybe<AutoTrackDOMPoint> trackJoinedPoint;
+    if (GetJoinNodesDirection() == JoinNodesDirection::LeftNodeIntoRightNode) {
+      joinedPoint.Set(keepingContent, 0u);
+      trackJoinedPoint.emplace(htmlEditor->RangeUpdaterRef(), &joinedPoint);
+    }
     rv = htmlEditor->DoJoinNodes(keepingContent, removingContent,
                                  GetJoinNodesDirection());
   }
   if (NS_SUCCEEDED(rv)) {
     // Adjust split offset for redo here
-    mSplitOffset = joinedPoint.Offset();
+    if (joinedPoint.IsSet()) {
+      mSplitOffset = joinedPoint.Offset();
+    }
   } else {
     NS_WARNING("HTMLEditor::DoJoinNodes() failed");
   }
   return rv;
 }
 
 /* Redo cannot simply resplit the right node, because subsequent transactions
  * on the redo stack may depend on the left node existing in its previous