Bug 1414713 - EditorUtils::IsDescendantOf() should take EditorDOMPoint and EditorRawDOMPoint as out param r=catalinb,m_kato

EditorUtils::IsDescendantOf() current takes a pointer to offset or a pointer to
child content if the caller needs to know the child of the most ancestor node.

However, some callers should get a child as EditorDOMPoint or EditorRawDOMPoint.
Then, they can be used for some editor methods which need to take child node
for performance optimization.

This patch makes EditorUtils::IsDescendantOf() as only two overloads.  One takes
pointer to EditorRawDOMPoint as optional out argument.  The other takes pointer
to EditorDOMPoint as an out param.

Additionally, this creates new constructor of AutoTrackDOMPoint for making it
can treat EditorDOMPoint directly.

MozReview-Commit-ID: IsAGTUvKI19

--HG--
extra : rebase_source : 97469a21b974c6a1dd515ab472bbc4a88c1899c8
This commit is contained in:
Masayuki Nakano 2017-11-06 17:01:33 +09:00
parent ed4206c563
commit 365f79c262
9 changed files with 179 additions and 102 deletions

View File

@ -203,6 +203,11 @@ public:
return mOffset.value();
}
/**
* Set() sets a point to aOffset or aChild.
* If it's set with offset, mRef is invalidated. If it's set with aChild,
* mOffset may be invalidated unless the offset can be computed simply.
*/
void
Set(nsINode* aContainer, int32_t aOffset)
{
@ -210,6 +215,29 @@ public:
mRef = nullptr;
mOffset = mozilla::Some(aOffset);
}
void
Set(const nsIContent* aChild)
{
MOZ_ASSERT(aChild);
mParent = aChild->GetParentNode();
mRef = aChild->GetPreviousSibling();
if (!mRef) {
mOffset = mozilla::Some(0);
} else {
mOffset.reset();
}
}
/**
* Clear() makes the instance not point anywhere.
*/
void
Clear()
{
mParent = nullptr;
mRef = nullptr;
mOffset.reset();
}
/**
* AdvanceOffset() tries to reference next sibling of mRef if its container

View File

@ -3969,7 +3969,7 @@ EditorBase::SplitNodeDeep(nsIContent& aNode,
nsCOMPtr<nsIContent>* ioChildAtSplitPointOffset)
{
MOZ_ASSERT(&aSplitPointParent == &aNode ||
EditorUtils::IsDescendantOf(&aSplitPointParent, &aNode));
EditorUtils::IsDescendantOf(aSplitPointParent, aNode));
int32_t offset = aSplitPointOffset;
nsCOMPtr<nsIContent> leftNode, rightNode;

View File

@ -5,6 +5,7 @@
#include "mozilla/EditorUtils.h"
#include "mozilla/EditorDOMPoint.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/Selection.h"
#include "nsComponentManagerUtils.h"
@ -135,19 +136,23 @@ DOMSubtreeIterator::~DOMSubtreeIterator()
*****************************************************************************/
bool
EditorUtils::IsDescendantOf(nsINode* aNode,
nsINode* aParent,
int32_t* aOffset)
EditorUtils::IsDescendantOf(const nsINode& aNode,
const nsINode& aParent,
EditorRawDOMPoint* aOutPoint /* = nullptr */)
{
MOZ_ASSERT(aNode && aParent);
if (aNode == aParent) {
if (aOutPoint) {
aOutPoint->Clear();
}
if (&aNode == &aParent) {
return false;
}
for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
if (node->GetParentNode() == aParent) {
if (aOffset) {
*aOffset = aParent->IndexOf(node);
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
if (node->GetParentNode() == &aParent) {
if (aOutPoint) {
MOZ_ASSERT(node->IsContent());
aOutPoint->Set(node->AsContent());
}
return true;
}
@ -157,19 +162,20 @@ EditorUtils::IsDescendantOf(nsINode* aNode,
}
bool
EditorUtils::IsDescendantOf(nsINode* aNode,
nsINode* aParent,
nsIContent** aChild)
EditorUtils::IsDescendantOf(const nsINode& aNode,
const nsINode& aParent,
EditorDOMPoint* aOutPoint)
{
MOZ_ASSERT(aNode && aParent && aChild);
*aChild = nullptr;
if (aNode == aParent) {
MOZ_ASSERT(aOutPoint);
aOutPoint->Clear();
if (&aNode == &aParent) {
return false;
}
for (nsCOMPtr<nsINode> node = aNode; node; node = node->GetParentNode()) {
if (node->GetParentNode() == aParent) {
*aChild = node->AsContent();
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
if (node->GetParentNode() == &aParent) {
MOZ_ASSERT(node->IsContent());
aOutPoint->Set(node->AsContent());
return true;
}
}
@ -177,17 +183,6 @@ EditorUtils::IsDescendantOf(nsINode* aNode,
return false;
}
bool
EditorUtils::IsDescendantOf(nsIDOMNode* aNode,
nsIDOMNode* aParent,
int32_t* aOffset)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsCOMPtr<nsINode> parent = do_QueryInterface(aParent);
NS_ENSURE_TRUE(node && parent, false);
return IsDescendantOf(node, parent, aOffset);
}
bool
EditorUtils::IsLeafNode(nsIDOMNode* aNode)
{

View File

@ -9,6 +9,7 @@
#include "mozilla/dom/Selection.h"
#include "mozilla/EditorBase.h"
#include "mozilla/EditorDOMPoint.h"
#include "mozilla/GuardObjects.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
@ -378,13 +379,19 @@ public:
class EditorUtils final
{
public:
// Note that aChild isn't a normal XPCOM outparam and won't get AddRef'ed.
static bool IsDescendantOf(nsINode* aNode, nsINode* aParent,
nsIContent** aChild);
static bool IsDescendantOf(nsINode* aNode, nsINode* aParent,
int32_t* aOffset = nullptr);
static bool IsDescendantOf(nsIDOMNode* aNode, nsIDOMNode* aParent,
int32_t* aOffset = nullptr);
/**
* IsDescendantOf() checks if aNode is a child or a descendant of aParent.
* aOutPoint is set to the child of aParent.
*
* @return true if aNode is a child or a descendant of aParent.
*/
static bool IsDescendantOf(const nsINode& aNode,
const nsINode& aParent,
EditorRawDOMPoint* aOutPoint = nullptr);
static bool IsDescendantOf(const nsINode& aNode,
const nsINode& aParent,
EditorDOMPoint* aOutPoint);
static bool IsLeafNode(nsIDOMNode* aNode);
};

View File

@ -2858,19 +2858,20 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
// different lists, join the lists instead.
bool mergeLists = false;
nsAtom* existingList = nsGkAtoms::_empty;
nsIContent* childInBlock = nullptr;
EditorDOMPoint childInBlock;
nsCOMPtr<Element> leftList, rightList;
if (HTMLEditUtils::IsListItem(leftBlock) &&
HTMLEditUtils::IsListItem(rightBlock)) {
leftList = leftBlock->GetParentElement();
rightList = rightBlock->GetParentElement();
if (leftList && rightList && leftList != rightList &&
!EditorUtils::IsDescendantOf(leftList, rightBlock, &childInBlock) &&
!EditorUtils::IsDescendantOf(rightList, leftBlock, &childInBlock)) {
!EditorUtils::IsDescendantOf(*leftList, *rightBlock, &childInBlock) &&
!EditorUtils::IsDescendantOf(*rightList, *leftBlock, &childInBlock)) {
// There are some special complications if the lists are descendants of
// the other lists' items. Note that it is okay for them to be
// descendants of the other lists themselves, which is the usual case for
// sublists in our implementation.
MOZ_DIAGNOSTIC_ASSERT(!childInBlock.IsSet());
leftBlock = leftList;
rightBlock = rightList;
mergeLists = true;
@ -2880,15 +2881,13 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
int32_t rightOffset = 0;
int32_t leftOffset = -1;
// offset below is where you find yourself in rightBlock when you traverse
// upwards from leftBlock
if (EditorUtils::IsDescendantOf(leftBlock, rightBlock, &rightOffset)) {
EditorDOMPoint rightBlockChild;
if (EditorUtils::IsDescendantOf(*leftBlock, *rightBlock, &rightBlockChild)) {
// Tricky case. Left block is inside right block. Do ws adjustment. This
// just destroys non-visible ws at boundaries we will be joining.
rightOffset++;
rightBlockChild.AdvanceOffset();
nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
WSRunObject::kBlockEnd,
leftBlock);
@ -2898,23 +2897,25 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
{
// We can't just track rightBlock because it's an Element.
nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
address_of(trackingRightBlock), &rightOffset);
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &rightBlockChild);
rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
WSRunObject::kAfterBlock,
rightBlock, rightOffset);
rightBlock,
rightBlockChild.Offset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return EditActionIgnored(rv);
}
if (trackingRightBlock->IsElement()) {
rightBlock = trackingRightBlock->AsElement();
// XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
// Do we really need to do update rightBlock here??
MOZ_ASSERT(rightBlock == rightBlockChild.Container());
if (rightBlockChild.Container()->IsElement()) {
rightBlock = rightBlockChild.Container()->AsElement();
} else {
if (NS_WARN_IF(!trackingRightBlock->GetParentElement())) {
if (NS_WARN_IF(!rightBlockChild.Container()->GetParentElement())) {
return EditActionIgnored(NS_ERROR_UNEXPECTED);
}
rightBlock = trackingRightBlock->GetParentElement();
rightBlock = rightBlockChild.Container()->GetParentElement();
}
}
// Do br adjustment.
@ -2924,8 +2925,12 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
if (mergeLists) {
// The idea here is to take all children in rightList that are past
// offset, and pull them into leftlist.
for (nsCOMPtr<nsIContent> child = childInBlock;
child; child = rightList->GetChildAt(rightOffset)) {
// XXX Looks like that when mergeLists is true, childInBlock has never
// been set. So, this block must be dead code.
MOZ_DIAGNOSTIC_ASSERT(childInBlock.IsSet());
uint32_t offset = rightBlockChild.Offset();
for (nsCOMPtr<nsIContent> child = childInBlock.GetChildAtOffset();
child; child = rightList->GetChildAt(offset)) {
rv = htmlEditor->MoveNode(child, leftList, -1);
if (NS_WARN_IF(NS_FAILED(rv))) {
return EditActionIgnored(rv);
@ -2933,13 +2938,21 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
}
// XXX Should this set to true only when above for loop moves the node?
ret.MarkAsHandled();
// childInBlock and rightBlockChild were moved to leftList. So, they
// are now invalid.
rightBlockChild.Clear();
childInBlock.Clear();
} else {
// XXX Why do we ignore the result of MoveBlock()?
EditActionResult retMoveBlock =
MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
MoveBlock(*leftBlock, *rightBlock,
-1, rightBlockChild.Offset());
if (retMoveBlock.Handled()) {
ret.MarkAsHandled();
}
// Now, all children of rightBlock were moved to leftBlock. So,
// rightBlockChild is now invalid.
rightBlockChild.Clear();
}
if (brNode && NS_SUCCEEDED(htmlEditor->DeleteNode(brNode))) {
ret.MarkAsHandled();
@ -2947,9 +2960,12 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
return ret;
}
MOZ_DIAGNOSTIC_ASSERT(!rightBlockChild.IsSet());
// Offset below is where you find yourself in leftBlock when you traverse
// upwards from rightBlock
if (EditorUtils::IsDescendantOf(rightBlock, leftBlock, &leftOffset)) {
EditorDOMPoint leftBlockChild;
if (EditorUtils::IsDescendantOf(*rightBlock, *leftBlock, &leftBlockChild)) {
// Tricky case. Right block is inside left block. Do ws adjustment. This
// just destroys non-visible ws at boundaries we will be joining.
nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
@ -2962,50 +2978,51 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
{
// We can't just track leftBlock because it's an Element, so track
// something else.
nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater,
address_of(trackingLeftBlock), &leftOffset);
AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &leftBlockChild);
rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
WSRunObject::kBeforeBlock,
leftBlock, leftOffset);
leftBlock, leftBlockChild.Offset());
if (NS_WARN_IF(NS_FAILED(rv))) {
return EditActionIgnored(rv);
}
if (trackingLeftBlock->IsElement()) {
leftBlock = trackingLeftBlock->AsElement();
// XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
// Do we really need to do update rightBlock here??
MOZ_DIAGNOSTIC_ASSERT(leftBlock == leftBlockChild.Container());
if (leftBlockChild.Container()->IsElement()) {
leftBlock = leftBlockChild.Container()->AsElement();
} else {
if (NS_WARN_IF(!trackingLeftBlock->GetParentElement())) {
if (NS_WARN_IF(!leftBlockChild.Container()->GetParentElement())) {
return EditActionIgnored(NS_ERROR_UNEXPECTED);
}
leftBlock = trackingLeftBlock->GetParentElement();
leftBlock = leftBlockChild.Container()->GetParentElement();
}
}
// Do br adjustment.
nsCOMPtr<Element> brNode =
CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock, leftOffset);
CheckForInvisibleBR(*leftBlock, BRLocation::beforeBlock,
leftBlockChild.Offset());
EditActionResult ret(NS_OK);
if (mergeLists) {
// XXX Why do we ignore the result of MoveContents()?
int32_t offset = leftBlockChild.Offset();
EditActionResult retMoveContents =
MoveContents(*rightList, *leftList, &leftOffset);
MoveContents(*rightList, *leftList, &offset);
if (retMoveContents.Handled()) {
ret.MarkAsHandled();
}
// leftBlockChild was moved to rightList. So, it's invalid now.
leftBlockChild.Clear();
} else {
// Left block is a parent of right block, and the parent of the previous
// visible content. Right block is a child and contains the contents we
// want to move.
int32_t previousContentOffset;
nsCOMPtr<nsINode> previousContentParent;
EditorDOMPoint previousContent;
if (&aLeftNode == leftBlock) {
// We are working with valid HTML, aLeftNode is a block node, and is
// therefore allowed to contain rightBlock. This is the simple case,
// we will simply move the content in rightBlock out of its block.
previousContentParent = leftBlock;
previousContentOffset = leftOffset;
previousContent = leftBlockChild;
} else {
// We try to work as well as possible with HTML that's already invalid.
// Although "right block" is a block, and a block must not be contained
@ -3016,13 +3033,10 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
// However, in some situations this strategy moves the content to an
// unexpected position. (see bug 200416) The new idea is to make the
// moving content a sibling, next to the previous visible content.
previousContentParent = aLeftNode.GetParentNode();
previousContentOffset = previousContentParent ?
previousContentParent->IndexOf(&aLeftNode) : -1;
previousContent.Set(&aLeftNode);
// We want to move our content just after the previous visible node.
previousContentOffset++;
previousContent.AdvanceOffset();
}
// Because we don't want the moving content to receive the style of the
@ -3031,6 +3045,8 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
nsCOMPtr<Element> editorRoot = htmlEditor->GetEditorRoot();
if (!editorRoot || &aLeftNode != editorRoot) {
nsCOMPtr<nsIContent> splittedPreviousContent;
nsCOMPtr<nsINode> previousContentParent = previousContent.Container();
int32_t previousContentOffset = previousContent.Offset();
rv = htmlEditor->SplitStyleAbovePoint(
address_of(previousContentParent),
&previousContentOffset,
@ -3041,18 +3057,18 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
}
if (splittedPreviousContent) {
previousContentParent = splittedPreviousContent->GetParentNode();
previousContentOffset = previousContentParent ?
previousContentParent->IndexOf(splittedPreviousContent) : -1;
previousContent.Set(splittedPreviousContent);
} else {
previousContent.Set(previousContentParent, previousContentOffset);
}
}
if (NS_WARN_IF(!previousContentParent)) {
if (NS_WARN_IF(!previousContent.IsSet())) {
return EditActionIgnored(NS_ERROR_NULL_POINTER);
}
ret |= MoveBlock(*previousContentParent->AsElement(), *rightBlock,
previousContentOffset, rightOffset);
ret |= MoveBlock(*previousContent.Container()->AsElement(), *rightBlock,
previousContent.Offset(), 0);
if (NS_WARN_IF(ret.Failed())) {
return ret;
}
@ -3063,6 +3079,9 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
return ret;
}
MOZ_DIAGNOSTIC_ASSERT(!rightBlockChild.IsSet());
MOZ_DIAGNOSTIC_ASSERT(!leftBlockChild.IsSet());
// Normal case. Blocks are siblings, or at least close enough. An example
// of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>. The
// first li and the p are not true siblings, but we still want to join them
@ -3089,7 +3108,7 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode,
ret.MarkAsHandled();
} else {
// Nodes are dissimilar types.
ret |= MoveBlock(*leftBlock, *rightBlock, leftOffset, rightOffset);
ret |= MoveBlock(*leftBlock, *rightBlock, -1, 0);
if (NS_WARN_IF(ret.Failed())) {
return ret;
}
@ -3438,7 +3457,7 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
if (HTMLEditUtils::IsList(curNode)) {
// do we have a curList already?
if (curList && !EditorUtils::IsDescendantOf(curNode, curList)) {
if (curList && !EditorUtils::IsDescendantOf(*curNode, *curList)) {
// move all of our children into curList. cheezy way to do it: move
// whole list and then RemoveContainer() on the list. ConvertListType
// first: that routine handles converting the list item types, if
@ -3469,7 +3488,7 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
if (!curParent->IsHTMLElement(listType)) {
// list item is in wrong type of list. if we don't have a curList,
// split the old list and make a new list of correct type.
if (!curList || EditorUtils::IsDescendantOf(curNode, curList)) {
if (!curList || EditorUtils::IsDescendantOf(*curNode, *curList)) {
NS_ENSURE_STATE(mHTMLEditor);
NS_ENSURE_STATE(curParent->IsContent());
ErrorResult rv;
@ -4405,7 +4424,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
// Do we have a blockquote that we are already committed to removing?
if (curBlockQuote) {
// If so, is this node a descendant?
if (EditorUtils::IsDescendantOf(curNode, curBlockQuote)) {
if (EditorUtils::IsDescendantOf(*curNode, *curBlockQuote)) {
lastBQChild = curNode;
// Then we don't need to do anything different for this node
continue;
@ -4532,7 +4551,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
int32_t startOffset = aSelection.GetRangeAt(0)->StartOffset();
if (rememberedLeftBQ &&
(startNode == rememberedLeftBQ ||
EditorUtils::IsDescendantOf(startNode, rememberedLeftBQ))) {
EditorUtils::IsDescendantOf(*startNode, *rememberedLeftBQ))) {
// Selection is inside rememberedLeftBQ - push it past it.
startNode = rememberedLeftBQ->GetParentNode();
startOffset = startNode ? 1 + startNode->IndexOf(rememberedLeftBQ) : 0;
@ -4543,7 +4562,7 @@ HTMLEditRules::WillOutdent(Selection& aSelection,
startOffset = aSelection.GetRangeAt(0)->StartOffset();
if (rememberedRightBQ &&
(startNode == rememberedRightBQ ||
EditorUtils::IsDescendantOf(startNode, rememberedRightBQ))) {
EditorUtils::IsDescendantOf(*startNode, *rememberedRightBQ))) {
// Selection is inside rememberedRightBQ - push it before it.
startNode = rememberedRightBQ->GetParentNode();
startOffset = startNode ? startNode->IndexOf(rememberedRightBQ) : -1;
@ -4584,8 +4603,8 @@ HTMLEditRules::SplitBlock(Element& aBlock,
nsIContent** aOutMiddleNode)
{
// aStartChild and aEndChild must be exclusive descendants of aBlock
MOZ_ASSERT(EditorUtils::IsDescendantOf(&aStartChild, &aBlock) &&
EditorUtils::IsDescendantOf(&aEndChild, &aBlock));
MOZ_ASSERT(EditorUtils::IsDescendantOf(aStartChild, aBlock) &&
EditorUtils::IsDescendantOf(aEndChild, aBlock));
NS_ENSURE_TRUE_VOID(mHTMLEditor);
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
@ -6396,7 +6415,7 @@ HTMLEditRules::GetHighestInlineParent(nsINode& aNode)
// 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))) {
if (NS_WARN_IF(!EditorUtils::IsDescendantOf(aNode, *host))) {
return nullptr;
}
@ -7088,7 +7107,7 @@ HTMLEditRules::RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
} else if (IsInlineNode(curNode)) {
if (curBlock) {
// If so, is this node a descendant?
if (EditorUtils::IsDescendantOf(curNode, curBlock)) {
if (EditorUtils::IsDescendantOf(*curNode, *curBlock)) {
// Then we don't need to do anything different for this node
lastNode = curNode->AsContent();
continue;
@ -8160,7 +8179,7 @@ HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
*aResult = true;
return NS_OK;
}
if (EditorUtils::IsDescendantOf(startContainer, aNode)) {
if (EditorUtils::IsDescendantOf(*startContainer, *aNode)) {
*aResult = true;
return NS_OK;
}
@ -8174,7 +8193,7 @@ HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
*aResult = true;
return NS_OK;
}
if (EditorUtils::IsDescendantOf(endContainer, aNode)) {
if (EditorUtils::IsDescendantOf(*endContainer, *aNode)) {
*aResult = true;
return NS_OK;
}

View File

@ -758,7 +758,7 @@ HTMLEditor::GetBlockNodeParent(nsINode* aNode,
MOZ_ASSERT(aNode);
MOZ_ASSERT(!aAncestorLimiter ||
aNode == aAncestorLimiter ||
EditorUtils::IsDescendantOf(aNode, aAncestorLimiter),
EditorUtils::IsDescendantOf(*aNode, *aAncestorLimiter),
"aNode isn't in aAncestorLimiter");
// The caller has already reached the limiter.
@ -791,7 +791,7 @@ HTMLEditor::GetBlock(nsINode& aNode,
{
MOZ_ASSERT(!aAncestorLimiter ||
&aNode == aAncestorLimiter ||
EditorUtils::IsDescendantOf(&aNode, aAncestorLimiter),
EditorUtils::IsDescendantOf(aNode, *aAncestorLimiter),
"aNode isn't in aAncestorLimiter");
if (NodeIsBlockStatic(&aNode)) {

View File

@ -442,7 +442,11 @@ HTMLEditor::DoInsertHTMLWithContext(const nsAString& aInputString,
if (insertedContextParent) {
// if we had to insert something higher up in the paste hierarchy, we want to
// skip any further paste nodes that descend from that. Else we will paste twice.
if (EditorUtils::IsDescendantOf(curNode, insertedContextParent)) {
nsCOMPtr<nsINode> insertedContextParentNode =
do_QueryInterface(insertedContextParent);
if (NS_WARN_IF(!insertedContextParentNode) ||
EditorUtils::IsDescendantOf(*nodeList[j],
*insertedContextParentNode)) {
continue;
}
}
@ -2380,7 +2384,7 @@ HTMLEditor::ReplaceOrphanedStructure(
(i - removedCount) : (originalLength - i - 1);
OwningNonNull<nsINode> endpoint = aNodeArray[idx];
if (endpoint == replaceNode ||
EditorUtils::IsDescendantOf(endpoint, replaceNode)) {
EditorUtils::IsDescendantOf(*endpoint, *replaceNode)) {
aNodeArray.RemoveElementAt(idx);
removedCount++;
}

View File

@ -287,7 +287,7 @@ RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
// check for range endpoints that are in descendants of aNode
nsCOMPtr<nsINode> oldStart;
if (EditorUtils::IsDescendantOf(item->mStartContainer, aNode)) {
if (EditorUtils::IsDescendantOf(*item->mStartContainer, *aNode)) {
oldStart = item->mStartContainer; // save for efficiency hack below.
item->mStartContainer = parent;
item->mStartOffset = offset;
@ -295,7 +295,7 @@ RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
// avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
if (item->mEndContainer == oldStart ||
EditorUtils::IsDescendantOf(item->mEndContainer, aNode)) {
EditorUtils::IsDescendantOf(*item->mEndContainer, *aNode)) {
item->mEndContainer = parent;
item->mEndOffset = offset;
}

View File

@ -6,6 +6,7 @@
#ifndef mozilla_SelectionState_h
#define mozilla_SelectionState_h
#include "mozilla/EditorDOMPoint.h"
#include "nsCOMPtr.h"
#include "nsIDOMNode.h"
#include "nsINode.h"
@ -180,6 +181,7 @@ private:
nsCOMPtr<nsINode>* mNode;
nsCOMPtr<nsIDOMNode>* mDOMNode;
int32_t* mOffset;
EditorDOMPoint* mPoint;
RefPtr<RangeItem> mRangeItem;
public:
@ -189,6 +191,7 @@ public:
, mNode(aNode)
, mDOMNode(nullptr)
, mOffset(aOffset)
, mPoint(nullptr)
{
mRangeItem = new RangeItem();
mRangeItem->mStartContainer = *mNode;
@ -204,6 +207,7 @@ public:
, mNode(nullptr)
, mDOMNode(aNode)
, mOffset(aOffset)
, mPoint(nullptr)
{
mRangeItem = new RangeItem();
mRangeItem->mStartContainer = do_QueryInterface(*mDOMNode);
@ -213,9 +217,29 @@ public:
mRangeUpdater.RegisterRangeItem(mRangeItem);
}
AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
EditorDOMPoint* aPoint)
: mRangeUpdater(aRangeUpdater)
, mNode(nullptr)
, mDOMNode(nullptr)
, mOffset(nullptr)
, mPoint(aPoint)
{
mRangeItem = new RangeItem();
mRangeItem->mStartContainer = mPoint->Container();
mRangeItem->mEndContainer = mPoint->Container();
mRangeItem->mStartOffset = mPoint->Offset();
mRangeItem->mEndOffset = mPoint->Offset();
mRangeUpdater.RegisterRangeItem(mRangeItem);
}
~AutoTrackDOMPoint()
{
mRangeUpdater.DropRangeItem(mRangeItem);
if (mPoint) {
mPoint->Set(mRangeItem->mStartContainer, mRangeItem->mStartOffset);
return;
}
if (mNode) {
*mNode = mRangeItem->mStartContainer;
} else {