Bug 1413181 - part 13: HTMLEditRules::MaybeSplitAncestorsForInsert() should be able to return a DOM point in text node r=m_kato

HTMLEditRules::MaybeSplitAncestorsForInsert() may be called with a point in a
text and it needs to return given split point as is.  Additionally, the given
point may be in a text node.  So, it may not be represented with an
nsCOMPtr<nsIContent>.

Therefore, we need to add new member, EditorDOMPoint, to SplitNodeResult and
when MaybeSplitAncestorsForInsert() needs to return the given point as is,
it should use it.

Note that if the methods which return SplitNodeResult split some nodes actually,
the left node and/or the right node may be removed from the DOM tree.  In this
case, EditorDOMPoint cannot store such orphan node.  Therefore, we cannot
make mNextNode nor mPreviousNode EditorDOMPoint.

MozReview-Commit-ID: LwH8RZzkrmT

--HG--
extra : rebase_source : a5ae2328bef3d887c0bf4e1b9c4a4247b93a4ac0
This commit is contained in:
Masayuki Nakano 2017-11-19 11:05:26 +09:00
parent 7537ae3755
commit c06378ebc9
2 changed files with 49 additions and 5 deletions

View File

@ -175,18 +175,35 @@ public:
*/
nsIContent* GetRightNode() const
{
if (mGivenSplitPoint.IsSet()) {
return mGivenSplitPoint.GetChildAtOffset();
}
return mPreviousNode && !mNextNode ? mPreviousNode : mNextNode;
}
/**
* GetPreviousNode() returns previous node at the split point.
*/
nsIContent* GetPreviousNode() const { return mPreviousNode; }
nsIContent* GetPreviousNode() const
{
if (mGivenSplitPoint.IsSet()) {
return mGivenSplitPoint.IsEndOfContainer() ?
mGivenSplitPoint.GetChildAtOffset() : nullptr;
}
return mPreviousNode;
}
/**
* GetNextNode() returns next node at the split point.
*/
nsIContent* GetNextNode() const { return mNextNode; }
nsIContent* GetNextNode() const
{
if (mGivenSplitPoint.IsSet()) {
return !mGivenSplitPoint.IsEndOfContainer() ?
mGivenSplitPoint.GetChildAtOffset() : nullptr;
}
return mNextNode;
}
/**
* SplitPoint() returns the split point in the container.
@ -202,6 +219,9 @@ public:
if (Failed()) {
return EditorRawDOMPoint();
}
if (mGivenSplitPoint.IsSet()) {
return mGivenSplitPoint.AsRaw();
}
if (!mPreviousNode) {
return EditorRawDOMPoint(mNextNode);
}
@ -230,6 +250,17 @@ public:
MOZ_DIAGNOSTIC_ASSERT(mPreviousNode || mNextNode);
}
/**
* This constructor should be used when the method didn't split any nodes
* but want to return given split point as right point.
*/
explicit SplitNodeResult(const EditorRawDOMPoint& aGivenSplitPoint)
: mGivenSplitPoint(aGivenSplitPoint)
, mRv(NS_OK)
{
MOZ_DIAGNOSTIC_ASSERT(mGivenSplitPoint.IsSet());
}
/**
* This constructor shouldn't be used by anybody except methods which
* use this as error result when it fails.
@ -241,9 +272,22 @@ public:
}
private:
// When methods which return this class split some nodes actually, they
// need to set a set of left node and right node to this class. However,
// one or both of them may be moved or removed by mutation observer.
// In such case, we cannot represent the point with EditorDOMPoint since
// it requires current container node. Therefore, we need to use
// nsCOMPtr<nsIContent> here instead.
nsCOMPtr<nsIContent> mPreviousNode;
nsCOMPtr<nsIContent> mNextNode;
// Methods which return this class may not split any nodes actually. Then,
// they may want to return given split point as is since such behavior makes
// their callers simpler. In this case, the point may be in a text node
// which cannot be represented as a node. Therefore, we need EditorDOMPoint
// for representing the point.
EditorDOMPoint mGivenSplitPoint;
nsresult mRv;
SplitNodeResult() = delete;

View File

@ -7540,10 +7540,10 @@ HTMLEditRules::MaybeSplitAncestorsForInsert(
MOZ_DIAGNOSTIC_ASSERT(pointToInsert.IsSet());
// If the point itself can contain the tag, we don't need to split any
// ancestor nodes.
// ancestor nodes. In this case, we should return the given split point
// as is.
if (pointToInsert.Container() == aStartOfDeepestRightNode.Container()) {
return SplitNodeResult(nullptr,
aStartOfDeepestRightNode.GetChildAtOffset());
return SplitNodeResult(aStartOfDeepestRightNode);
}
SplitNodeResult splitNodeResult =