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
--- 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;
};