Bug 1419745 - part 3: CreateElementTransaction and SplitNodeTransaction should store DOM point with EditorDOMPoint rather than RangeBoundary r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 28 Nov 2017 17:13:15 +0900
changeset 704244 534765e957fb3c7f32c9ec3d597c41fe4358d7f2
parent 704243 470a59bdd3a3ecd3be67394676d568b3f071b70a
child 742049 93234afa06605fe83458a2c121154721b1beb72b
push id91129
push usermasayuki@d-toybox.com
push dateTue, 28 Nov 2017 13:40:01 +0000
reviewersm_kato
bugs1419745
milestone59.0a1
Bug 1419745 - part 3: CreateElementTransaction and SplitNodeTransaction should store DOM point with EditorDOMPoint rather than RangeBoundary r?m_kato CreateElementTransaction and SplitNodeTransaction store DOM point with RangeBoundary now. However, it refers next child of referring point. Therefore, if it's moved to different container or removed from the DOM tree, they cannot do undo/redo. We can say for the child node, however, it doesn't make sense depending on a node which is not directly referring. MozReview-Commit-ID: Baohbub3RNZ
editor/libeditor/CreateElementTransaction.h
editor/libeditor/EditorDOMPoint.h
editor/libeditor/SplitNodeTransaction.h
--- a/editor/libeditor/CreateElementTransaction.h
+++ b/editor/libeditor/CreateElementTransaction.h
@@ -62,17 +62,17 @@ protected:
 
   // The document into which the new node will be inserted.
   RefPtr<EditorBase> mEditorBase;
 
   // The tag (mapping to object type) for the new element.
   RefPtr<nsAtom> mTag;
 
   // The DOM point we will insert mNewNode.
-  RangeBoundary mPointToInsert;
+  EditorDOMPoint mPointToInsert;
 
   // The new node to insert.
   nsCOMPtr<dom::Element> mNewNode;
 };
 
 } // namespace mozilla
 
 #endif // #ifndef CreateElementTransaction_h
--- a/editor/libeditor/EditorDOMPoint.h
+++ b/editor/libeditor/EditorDOMPoint.h
@@ -62,17 +62,17 @@ class EditorDOMPointBase;
  * AutoEditorDOMPointOffsetInvalidator and AutoEditorDOMPointChildInvalidator.
  */
 
 typedef EditorDOMPointBase<nsCOMPtr<nsINode>,
                            nsCOMPtr<nsIContent>> EditorDOMPoint;
 typedef EditorDOMPointBase<nsINode*, nsIContent*> EditorRawDOMPoint;
 
 template<typename ParentType, typename ChildType>
-class MOZ_STACK_CLASS EditorDOMPointBase final
+class EditorDOMPointBase final
 {
   typedef EditorDOMPointBase<ParentType, ChildType> SelfType;
 
 public:
   EditorDOMPointBase()
     : mParent(nullptr)
     , mChild(nullptr)
     , mIsChildInitialized(false)
@@ -551,49 +551,52 @@ public:
   }
 
   template<typename A, typename B>
   bool operator!=(const EditorDOMPointBase<A, B>& aOther) const
   {
     return !(*this == aOther);
   }
 
-  template<typename A, typename B>
-  operator const RangeBoundaryBase<A, B>() const
+  /**
+   * This operator should be used if API of other modules take RawRangeBoundary,
+   * e.g., methods of Selection and nsRange.
+   */
+  operator const RawRangeBoundary() const
   {
     if (!IsSet() ||
         NS_WARN_IF(!mIsChildInitialized && !mOffset.isSome())) {
-      return RangeBoundaryBase<A, B>();
+      return RawRangeBoundary();
     }
     if (!mParent->IsContainerNode()) {
       // If the container is a data node like a text node, we need to create
       // RangeBoundaryBase instance only with mOffset because mChild is always
       // nullptr.
-      return RangeBoundaryBase<A, B>(mParent, mOffset.value());
+      return RawRangeBoundary(mParent, mOffset.value());
     }
     if (mIsChildInitialized && mOffset.isSome()) {
       // If we've already set both child and offset, we should use both of them
       // to create RangeBoundaryBase instance because the constructor will
       // validate the relation in debug build.
       if (mChild) {
-        return RangeBoundaryBase<A, B>(mParent, mChild->GetPreviousSibling(),
-                                       mOffset.value());
+        return RawRangeBoundary(mParent, mChild->GetPreviousSibling(),
+                                mOffset.value());
       }
-      return RangeBoundaryBase<A, B>(mParent, mParent->GetLastChild(),
-                                     mOffset.value());
+      return RawRangeBoundary(mParent, mParent->GetLastChild(),
+                              mOffset.value());
     }
     // Otherwise, we should create RangeBoundaryBase only with available
     // information.
     if (mOffset.isSome()) {
-      return RangeBoundaryBase<A, B>(mParent, mOffset.value());
+      return RawRangeBoundary(mParent, mOffset.value());
     }
     if (mChild) {
-      return RangeBoundaryBase<A, B>(mParent, mChild->GetPreviousSibling());
+      return RawRangeBoundary(mParent, mChild->GetPreviousSibling());
     }
-    return RangeBoundaryBase<A, B>(mParent, mParent->GetLastChild());
+    return RawRangeBoundary(mParent, mParent->GetLastChild());
   }
 
 private:
   void
   EnsureChild()
   {
     if (mIsChildInitialized) {
       return;
@@ -616,18 +619,40 @@ private:
   ChildType mChild;
 
   mozilla::Maybe<uint32_t> mOffset;
 
   bool mIsChildInitialized;
 
   template<typename PT, typename CT>
   friend class EditorDOMPointBase;
+
+  friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
+                                          EditorDOMPoint&, const char*,
+                                          uint32_t);
+  friend void ImplCycleCollectionUnlink(EditorDOMPoint&);
 };
 
+inline void
+ImplCycleCollectionUnlink(EditorDOMPoint& aField)
+{
+  ImplCycleCollectionUnlink(aField.mParent);
+  ImplCycleCollectionUnlink(aField.mChild);
+}
+
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            EditorDOMPoint& aField,
+                            const char* aName,
+                            uint32_t aFlags)
+{
+  ImplCycleCollectionTraverse(aCallback, aField.mParent, "mParent", 0);
+  ImplCycleCollectionTraverse(aCallback, aField.mChild, "mChild", 0);
+}
+
 /**
  * AutoEditorDOMPointOffsetInvalidator is useful if DOM tree will be changed
  * when EditorDOMPoint instance is available and keeps referring same child
  * node.
  *
  * This class automatically guarantees that given EditorDOMPoint instance
  * stores the child node and invalidates its offset when the instance is
  * destroyed.  Additionally, users of this class can invalidate the offset
--- a/editor/libeditor/SplitNodeTransaction.h
+++ b/editor/libeditor/SplitNodeTransaction.h
@@ -49,17 +49,17 @@ public:
 
 protected:
   virtual ~SplitNodeTransaction();
 
   RefPtr<EditorBase> mEditorBase;
 
   // The container is existing right node (will be split).
   // The point referring this is start of the right node after it's split.
-  RangeBoundary mStartOfRightNode;
+  EditorDOMPoint mStartOfRightNode;
 
   // The node we create when splitting mExistingRightNode.
   nsCOMPtr<nsIContent> mNewLeftNode;
 
   // The parent shared by mExistingRightNode and mNewLeftNode.
   nsCOMPtr<nsINode> mParent;
 };