Bug 1218032 part.1 nsContentIterator should warn if unexpected case occurs r=smaug

This commit is contained in:
Masayuki Nakano 2015-11-10 11:49:04 +09:00
Родитель 4b6e0ca573
Коммит 765a007510
1 изменённых файлов: 95 добавлений и 54 удалений

Просмотреть файл

@ -30,6 +30,7 @@ NodeToParentOffset(nsINode* aNode, int32_t* aOffset)
if (parent) { if (parent) {
*aOffset = parent->IndexOf(aNode); *aOffset = parent->IndexOf(aNode);
NS_WARN_IF(*aOffset < 0);
} }
return parent; return parent;
@ -44,7 +45,7 @@ NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
nsINode* aStartNode, int32_t aStartOffset, nsINode* aStartNode, int32_t aStartOffset,
nsINode* aEndNode, int32_t aEndOffset) nsINode* aEndNode, int32_t aEndOffset)
{ {
if (!aStartNode || !aEndNode || !aNode) { if (NS_WARN_IF(!aStartNode) || NS_WARN_IF(!aEndNode) || NS_WARN_IF(!aNode)) {
return false; return false;
} }
@ -71,6 +72,7 @@ NodeIsInTraversalRange(nsINode* aNode, bool aIsPreMode,
} }
int32_t indx = parent->IndexOf(aNode); int32_t indx = parent->IndexOf(aNode);
NS_WARN_IF(indx == -1);
if (!aIsPreMode) { if (!aIsPreMode) {
++indx; ++indx;
@ -262,7 +264,7 @@ nsContentIterator::~nsContentIterator()
nsresult nsresult
nsContentIterator::Init(nsINode* aRoot) nsContentIterator::Init(nsINode* aRoot)
{ {
if (!aRoot) { if (NS_WARN_IF(!aRoot)) {
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
@ -272,8 +274,10 @@ nsContentIterator::Init(nsINode* aRoot)
if (mPre) { if (mPre) {
mFirst = aRoot; mFirst = aRoot;
mLast = GetDeepLastChild(aRoot); mLast = GetDeepLastChild(aRoot);
NS_WARN_IF(!mLast);
} else { } else {
mFirst = GetDeepFirstChild(aRoot); mFirst = GetDeepFirstChild(aRoot);
NS_WARN_IF(!mFirst);
mLast = aRoot; mLast = aRoot;
} }
@ -286,24 +290,34 @@ nsContentIterator::Init(nsINode* aRoot)
nsresult nsresult
nsContentIterator::Init(nsIDOMRange* aDOMRange) nsContentIterator::Init(nsIDOMRange* aDOMRange)
{ {
NS_ENSURE_ARG_POINTER(aDOMRange); if (NS_WARN_IF(!aDOMRange)) {
return NS_ERROR_INVALID_ARG;
}
nsRange* range = static_cast<nsRange*>(aDOMRange); nsRange* range = static_cast<nsRange*>(aDOMRange);
mIsDone = false; mIsDone = false;
// get common content parent // get common content parent
mCommonParent = range->GetCommonAncestor(); mCommonParent = range->GetCommonAncestor();
NS_ENSURE_TRUE(mCommonParent, NS_ERROR_FAILURE); if (NS_WARN_IF(!mCommonParent)) {
return NS_ERROR_FAILURE;
}
// get the start node and offset // get the start node and offset
int32_t startIndx = range->StartOffset(); int32_t startIndx = range->StartOffset();
NS_WARN_IF(startIndx < 0);
nsINode* startNode = range->GetStartParent(); nsINode* startNode = range->GetStartParent();
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE); if (NS_WARN_IF(!startNode)) {
return NS_ERROR_FAILURE;
}
// get the end node and offset // get the end node and offset
int32_t endIndx = range->EndOffset(); int32_t endIndx = range->EndOffset();
NS_WARN_IF(endIndx < 0);
nsINode* endNode = range->GetEndParent(); nsINode* endNode = range->GetEndParent();
NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE); if (NS_WARN_IF(!endNode)) {
return NS_ERROR_FAILURE;
}
bool startIsData = startNode->IsNodeOfType(nsINode::eDATA_NODE); bool startIsData = startNode->IsNodeOfType(nsINode::eDATA_NODE);
@ -327,7 +341,8 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
mLast = mFirst; mLast = mFirst;
mCurNode = mFirst; mCurNode = mFirst;
RebuildIndexStack(); nsresult rv = RebuildIndexStack();
NS_WARN_IF(NS_FAILED(rv));
return NS_OK; return NS_OK;
} }
} }
@ -338,6 +353,7 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (!startIsData && startNode->HasChildren()) { if (!startIsData && startNode->HasChildren()) {
cChild = startNode->GetChildAt(startIndx); cChild = startNode->GetChildAt(startIndx);
NS_WARN_IF(!cChild);
} }
if (!cChild) { if (!cChild) {
@ -356,11 +372,13 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
// In other words, if the offset is 1, the node should be ignored. // In other words, if the offset is 1, the node should be ignored.
if (!startIsData && startIndx) { if (!startIsData && startIndx) {
mFirst = GetNextSibling(startNode); mFirst = GetNextSibling(startNode);
NS_WARN_IF(!mFirst);
// Does mFirst node really intersect the range? The range could be // Does mFirst node really intersect the range? The range could be
// 'degenerate', i.e., not collapsed but still contain no content. // 'degenerate', i.e., not collapsed but still contain no content.
if (mFirst && !NodeIsInTraversalRange(mFirst, mPre, startNode, if (mFirst &&
startIndx, endNode, endIndx)) { NS_WARN_IF(!NodeIsInTraversalRange(mFirst, mPre, startNode,
startIndx, endNode, endIndx))) {
mFirst = nullptr; mFirst = nullptr;
} }
} else { } else {
@ -368,11 +386,11 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
} }
} else { } else {
// post-order // post-order
if (startNode->IsContent()) { if (NS_WARN_IF(!startNode->IsContent())) {
mFirst = startNode->AsContent();
} else {
// What else can we do? // What else can we do?
mFirst = nullptr; mFirst = nullptr;
} else {
mFirst = startNode->AsContent();
} }
} }
} else { } else {
@ -381,12 +399,14 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
} else { } else {
// post-order // post-order
mFirst = GetDeepFirstChild(cChild); mFirst = GetDeepFirstChild(cChild);
NS_WARN_IF(!mFirst);
// Does mFirst node really intersect the range? The range could be // Does mFirst node really intersect the range? The range could be
// 'degenerate', i.e., not collapsed but still contain no content. // 'degenerate', i.e., not collapsed but still contain no content.
if (mFirst && !NodeIsInTraversalRange(mFirst, mPre, startNode, startIndx, if (mFirst &&
endNode, endIndx)) { NS_WARN_IF(!NodeIsInTraversalRange(mFirst, mPre, startNode, startIndx,
endNode, endIndx))) {
mFirst = nullptr; mFirst = nullptr;
} }
} }
@ -399,22 +419,24 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (endIsData || !endNode->HasChildren() || endIndx == 0) { if (endIsData || !endNode->HasChildren() || endIndx == 0) {
if (mPre) { if (mPre) {
if (endNode->IsContent()) { if (NS_WARN_IF(!endNode->IsContent())) {
// Not much else to do here...
mLast = nullptr;
} else {
// If the end node is an empty element and the end offset is 0, // If the end node is an empty element and the end offset is 0,
// the last element should be the previous node (i.e., shouldn't // the last element should be the previous node (i.e., shouldn't
// include the end node in the range). // include the end node in the range).
if (!endIsData && !endNode->HasChildren() && !endIndx) { if (!endIsData && !endNode->HasChildren() && !endIndx) {
mLast = GetPrevSibling(endNode); mLast = GetPrevSibling(endNode);
if (!NodeIsInTraversalRange(mLast, mPre, startNode, startIndx, NS_WARN_IF(!mLast);
endNode, endIndx)) { if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre,
startNode, startIndx,
endNode, endIndx))) {
mLast = nullptr; mLast = nullptr;
} }
} else { } else {
mLast = endNode->AsContent(); mLast = endNode->AsContent();
} }
} else {
// Not much else to do here...
mLast = nullptr;
} }
} else { } else {
// post-order // post-order
@ -424,9 +446,11 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (!endIsData) { if (!endIsData) {
mLast = GetPrevSibling(endNode); mLast = GetPrevSibling(endNode);
NS_WARN_IF(!mLast);
if (!NodeIsInTraversalRange(mLast, mPre, startNode, startIndx, if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre,
endNode, endIndx)) { startNode, startIndx,
endNode, endIndx))) {
mLast = nullptr; mLast = nullptr;
} }
} else { } else {
@ -438,7 +462,7 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
cChild = endNode->GetChildAt(--indx); cChild = endNode->GetChildAt(--indx);
if (!cChild) { if (NS_WARN_IF(!cChild)) {
// No child at offset! // No child at offset!
NS_NOTREACHED("nsContentIterator::nsContentIterator"); NS_NOTREACHED("nsContentIterator::nsContentIterator");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -446,9 +470,11 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (mPre) { if (mPre) {
mLast = GetDeepLastChild(cChild); mLast = GetDeepLastChild(cChild);
NS_WARN_IF(!mLast);
if (!NodeIsInTraversalRange(mLast, mPre, startNode, startIndx, if (NS_WARN_IF(!NodeIsInTraversalRange(mLast, mPre,
endNode, endIndx)) { startNode, startIndx,
endNode, endIndx))) {
mLast = nullptr; mLast = nullptr;
} }
} else { } else {
@ -459,7 +485,7 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
// If either first or last is null, they both have to be null! // If either first or last is null, they both have to be null!
if (!mFirst || !mLast) { if (NS_WARN_IF(!mFirst) || NS_WARN_IF(!mLast)) {
mFirst = nullptr; mFirst = nullptr;
mLast = nullptr; mLast = nullptr;
} }
@ -470,7 +496,8 @@ nsContentIterator::Init(nsIDOMRange* aDOMRange)
if (!mCurNode) { if (!mCurNode) {
mIndexes.Clear(); mIndexes.Clear();
} else { } else {
RebuildIndexStack(); nsresult rv = RebuildIndexStack();
NS_WARN_IF(NS_FAILED(rv));
} }
return NS_OK; return NS_OK;
@ -499,7 +526,7 @@ nsContentIterator::RebuildIndexStack()
while (current != mCommonParent) { while (current != mCommonParent) {
parent = current->GetParentNode(); parent = current->GetParentNode();
if (!parent) { if (NS_WARN_IF(!parent)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -526,7 +553,7 @@ nsINode*
nsContentIterator::GetDeepFirstChild(nsINode* aRoot, nsContentIterator::GetDeepFirstChild(nsINode* aRoot,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aRoot || !aRoot->HasChildren()) { if (NS_WARN_IF(!aRoot) || !aRoot->HasChildren()) {
return aRoot; return aRoot;
} }
// We can't pass aRoot itself to the full GetDeepFirstChild, because that // We can't pass aRoot itself to the full GetDeepFirstChild, because that
@ -542,7 +569,7 @@ nsIContent*
nsContentIterator::GetDeepFirstChild(nsIContent* aRoot, nsContentIterator::GetDeepFirstChild(nsIContent* aRoot,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aRoot) { if (NS_WARN_IF(!aRoot)) {
return nullptr; return nullptr;
} }
@ -565,7 +592,7 @@ nsINode*
nsContentIterator::GetDeepLastChild(nsINode* aRoot, nsContentIterator::GetDeepLastChild(nsINode* aRoot,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aRoot || !aRoot->HasChildren()) { if (NS_WARN_IF(!aRoot) || !aRoot->HasChildren()) {
return aRoot; return aRoot;
} }
// We can't pass aRoot itself to the full GetDeepLastChild, because that will // We can't pass aRoot itself to the full GetDeepLastChild, because that will
@ -581,7 +608,7 @@ nsIContent*
nsContentIterator::GetDeepLastChild(nsIContent* aRoot, nsContentIterator::GetDeepLastChild(nsIContent* aRoot,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aRoot) { if (NS_WARN_IF(!aRoot)) {
return nullptr; return nullptr;
} }
@ -607,12 +634,12 @@ nsIContent*
nsContentIterator::GetNextSibling(nsINode* aNode, nsContentIterator::GetNextSibling(nsINode* aNode,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aNode) { if (NS_WARN_IF(!aNode)) {
return nullptr; return nullptr;
} }
nsINode* parent = aNode->GetParentNode(); nsINode* parent = aNode->GetParentNode();
if (!parent) { if (NS_WARN_IF(!parent)) {
return nullptr; return nullptr;
} }
@ -626,6 +653,7 @@ nsContentIterator::GetNextSibling(nsINode* aNode,
} else { } else {
indx = mCachedIndex; indx = mCachedIndex;
} }
NS_WARN_IF(indx < 0);
// reverify that the index of the current node hasn't changed. // reverify that the index of the current node hasn't changed.
// not super cheap, but a lot cheaper than IndexOf(), and still O(1). // not super cheap, but a lot cheaper than IndexOf(), and still O(1).
@ -634,6 +662,7 @@ nsContentIterator::GetNextSibling(nsINode* aNode,
if (sib != aNode) { if (sib != aNode) {
// someone changed our index - find the new index the painful way // someone changed our index - find the new index the painful way
indx = parent->IndexOf(aNode); indx = parent->IndexOf(aNode);
NS_WARN_IF(indx < 0);
} }
// indx is now canonically correct // indx is now canonically correct
@ -668,12 +697,12 @@ nsIContent*
nsContentIterator::GetPrevSibling(nsINode* aNode, nsContentIterator::GetPrevSibling(nsINode* aNode,
nsTArray<int32_t>* aIndexes) nsTArray<int32_t>* aIndexes)
{ {
if (!aNode) { if (NS_WARN_IF(!aNode)) {
return nullptr; return nullptr;
} }
nsINode* parent = aNode->GetParentNode(); nsINode* parent = aNode->GetParentNode();
if (!parent) { if (NS_WARN_IF(!parent)) {
return nullptr; return nullptr;
} }
@ -694,6 +723,7 @@ nsContentIterator::GetPrevSibling(nsINode* aNode,
if (sib != aNode) { if (sib != aNode) {
// someone changed our index - find the new index the painful way // someone changed our index - find the new index the painful way
indx = parent->IndexOf(aNode); indx = parent->IndexOf(aNode);
NS_WARN_IF(indx < 0);
} }
// indx is now canonically correct // indx is now canonically correct
@ -725,6 +755,7 @@ nsContentIterator::NextNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
// if it has children then next node is first child // if it has children then next node is first child
if (node->HasChildren()) { if (node->HasChildren()) {
nsIContent* firstChild = node->GetFirstChild(); nsIContent* firstChild = node->GetFirstChild();
MOZ_ASSERT(firstChild);
// update cache // update cache
if (aIndexes) { if (aIndexes) {
@ -743,6 +774,7 @@ nsContentIterator::NextNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
// post-order // post-order
nsINode* parent = node->GetParentNode(); nsINode* parent = node->GetParentNode();
NS_WARN_IF(!parent);
nsIContent* sibling = nullptr; nsIContent* sibling = nullptr;
int32_t indx = 0; int32_t indx = 0;
@ -765,6 +797,7 @@ nsContentIterator::NextNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
if (sibling != node) { if (sibling != node) {
// someone changed our index - find the new index the painful way // someone changed our index - find the new index the painful way
indx = parent->IndexOf(node); indx = parent->IndexOf(node);
NS_WARN_IF(indx < 0);
} }
// indx is now canonically correct // indx is now canonically correct
@ -806,6 +839,7 @@ nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
// if we are a Pre-order iterator, use pre-order // if we are a Pre-order iterator, use pre-order
if (mPre) { if (mPre) {
nsINode* parent = node->GetParentNode(); nsINode* parent = node->GetParentNode();
NS_WARN_IF(!parent);
nsIContent* sibling = nullptr; nsIContent* sibling = nullptr;
int32_t indx = 0; int32_t indx = 0;
@ -824,11 +858,13 @@ nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
// this time - the index may now be out of range. // this time - the index may now be out of range.
if (indx >= 0) { if (indx >= 0) {
sibling = parent->GetChildAt(indx); sibling = parent->GetChildAt(indx);
NS_WARN_IF(!sibling);
} }
if (sibling != node) { if (sibling != node) {
// someone changed our index - find the new index the painful way // someone changed our index - find the new index the painful way
indx = parent->IndexOf(node); indx = parent->IndexOf(node);
NS_WARN_IF(indx < 0);
} }
// indx is now canonically correct // indx is now canonically correct
@ -858,10 +894,12 @@ nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
// post-order // post-order
int32_t numChildren = node->GetChildCount(); int32_t numChildren = node->GetChildCount();
NS_WARN_IF(numChildren < 0);
// if it has children then prev node is last child // if it has children then prev node is last child
if (numChildren) { if (numChildren) {
nsIContent* lastChild = node->GetLastChild(); nsIContent* lastChild = node->GetLastChild();
NS_WARN_IF(!lastChild);
numChildren--; numChildren--;
// update cache // update cache
@ -887,11 +925,7 @@ void
nsContentIterator::First() nsContentIterator::First()
{ {
if (mFirst) { if (mFirst) {
#ifdef DEBUG DebugOnly<nsresult> rv = PositionAt(mFirst);
nsresult rv =
#endif
PositionAt(mFirst);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to position iterator!"); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to position iterator!");
} }
@ -905,11 +939,7 @@ nsContentIterator::Last()
NS_ASSERTION(mLast, "No last node!"); NS_ASSERTION(mLast, "No last node!");
if (mLast) { if (mLast) {
#ifdef DEBUG DebugOnly<nsresult> rv = PositionAt(mLast);
nsresult rv =
#endif
PositionAt(mLast);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to position iterator!"); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to position iterator!");
} }
@ -920,7 +950,7 @@ nsContentIterator::Last()
void void
nsContentIterator::Next() nsContentIterator::Next()
{ {
if (mIsDone || !mCurNode) { if (mIsDone || NS_WARN_IF(!mCurNode)) {
return; return;
} }
@ -936,7 +966,7 @@ nsContentIterator::Next()
void void
nsContentIterator::Prev() nsContentIterator::Prev()
{ {
if (mIsDone || !mCurNode) { if (NS_WARN_IF(mIsDone) || NS_WARN_IF(!mCurNode)) {
return; return;
} }
@ -961,7 +991,7 @@ nsContentIterator::IsDone()
nsresult nsresult
nsContentIterator::PositionAt(nsINode* aCurNode) nsContentIterator::PositionAt(nsINode* aCurNode)
{ {
if (!aCurNode) { if (NS_WARN_IF(!aCurNode)) {
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
} }
@ -984,11 +1014,15 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
if (firstNode && lastNode) { if (firstNode && lastNode) {
if (mPre) { if (mPre) {
firstNode = NodeToParentOffset(mFirst, &firstOffset); firstNode = NodeToParentOffset(mFirst, &firstOffset);
NS_WARN_IF(!firstNode);
NS_WARN_IF(firstOffset < 0);
if (lastNode->GetChildCount()) { if (lastNode->GetChildCount()) {
lastOffset = 0; lastOffset = 0;
} else { } else {
lastNode = NodeToParentOffset(mLast, &lastOffset); lastNode = NodeToParentOffset(mLast, &lastOffset);
NS_WARN_IF(!lastNode);
NS_WARN_IF(lastOffset < 0);
++lastOffset; ++lastOffset;
} }
} else { } else {
@ -996,11 +1030,16 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
if (numChildren) { if (numChildren) {
firstOffset = numChildren; firstOffset = numChildren;
NS_WARN_IF(firstOffset < 0);
} else { } else {
firstNode = NodeToParentOffset(mFirst, &firstOffset); firstNode = NodeToParentOffset(mFirst, &firstOffset);
NS_WARN_IF(!firstNode);
NS_WARN_IF(firstOffset < 0);
} }
lastNode = NodeToParentOffset(mLast, &lastOffset); lastNode = NodeToParentOffset(mLast, &lastOffset);
NS_WARN_IF(!lastNode);
NS_WARN_IF(lastOffset < 0);
++lastOffset; ++lastOffset;
} }
} }
@ -1009,9 +1048,10 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
// need to allow that or 'iter->Init(root)' would assert in Last() or First() // need to allow that or 'iter->Init(root)' would assert in Last() or First()
// for example, bug 327694. // for example, bug 327694.
if (mFirst != mCurNode && mLast != mCurNode && if (mFirst != mCurNode && mLast != mCurNode &&
(!firstNode || !lastNode || (NS_WARN_IF(!firstNode) || NS_WARN_IF(!lastNode) ||
!NodeIsInTraversalRange(mCurNode, mPre, firstNode, firstOffset, NS_WARN_IF(!NodeIsInTraversalRange(mCurNode, mPre,
lastNode, lastOffset))) { firstNode, firstOffset,
lastNode, lastOffset)))) {
mIsDone = true; mIsDone = true;
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1040,7 +1080,7 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
nsINode* parent = tempNode->GetParentNode(); nsINode* parent = tempNode->GetParentNode();
if (!parent) { if (NS_WARN_IF(!parent)) {
// this node has no parent, and thus no index // this node has no parent, and thus no index
break; break;
} }
@ -1060,12 +1100,13 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
while (newCurNode) { while (newCurNode) {
nsINode* parent = newCurNode->GetParentNode(); nsINode* parent = newCurNode->GetParentNode();
if (!parent) { if (NS_WARN_IF(!parent)) {
// this node has no parent, and thus no index // this node has no parent, and thus no index
break; break;
} }
int32_t indx = parent->IndexOf(newCurNode); int32_t indx = parent->IndexOf(newCurNode);
NS_WARN_IF(indx < 0);
// insert at the head! // insert at the head!
newIndexes.InsertElementAt(0, indx); newIndexes.InsertElementAt(0, indx);