From 55b76515388262083b3516347a22fca7de4cb139 Mon Sep 17 00:00:00 2001 From: "Olli.Pettay@helsinki.fi" Date: Sun, 24 Feb 2008 04:46:09 -0800 Subject: [PATCH] Bug 409380, support 'unconnected' ranges , r+sr+a=sicking --- content/base/public/nsContentUtils.h | 8 +- content/base/src/nsContentUtils.cpp | 9 +- content/base/src/nsRange.cpp | 49 ++-- content/base/src/nsRange.h | 1 + content/base/test/Makefile.in | 1 + content/base/test/test_bug409380.html | 379 ++++++++++++++++++++++++++ 6 files changed, 424 insertions(+), 23 deletions(-) create mode 100644 content/base/test/test_bug409380.html diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index ca69a77e16f0..f0ba2f149d0e 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -267,11 +267,13 @@ public: * node/offset pair * Returns -1 if point1 < point2, 1, if point1 > point2, * 0 if error or if point1 == point2. - * NOTE! The two nodes MUST be in the same connected subtree! - * if they are not the result is undefined. + * NOTE! If the two nodes aren't in the same connected subtree, + * the result is undefined, but the optional aDisconnected parameter + * is set to PR_TRUE. */ static PRInt32 ComparePoints(nsINode* aParent1, PRInt32 aOffset1, - nsINode* aParent2, PRInt32 aOffset2); + nsINode* aParent2, PRInt32 aOffset2, + PRBool* aDisconnected = nsnull); /** * Find the first child of aParent with a resolved tag matching diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 1f60b21335c6..ad0564faeb30 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1496,7 +1496,8 @@ nsContentUtils::ComparePosition(nsINode* aNode1, /* static */ PRInt32 nsContentUtils::ComparePoints(nsINode* aParent1, PRInt32 aOffset1, - nsINode* aParent2, PRInt32 aOffset2) + nsINode* aParent2, PRInt32 aOffset2, + PRBool* aDisconnected) { if (aParent1 == aParent2) { return aOffset1 < aOffset2 ? -1 : @@ -1519,8 +1520,12 @@ nsContentUtils::ComparePoints(nsINode* aParent1, PRInt32 aOffset1, PRUint32 pos1 = parents1.Length() - 1; PRUint32 pos2 = parents2.Length() - 1; - NS_ASSERTION(parents1.ElementAt(pos1) == parents2.ElementAt(pos2), + NS_ASSERTION(parents1.ElementAt(pos1) == parents2.ElementAt(pos2) || + aDisconnected, "disconnected nodes"); + if (aDisconnected) { + *aDisconnected = (parents1.ElementAt(pos1) != parents2.ElementAt(pos2)); + } // Find where the parent chains differ nsINode* parent = parents1.ElementAt(pos1); diff --git a/content/base/src/nsRange.cpp b/content/base/src/nsRange.cpp index 744cc0cd8e8e..a45aa8d1882a 100644 --- a/content/base/src/nsRange.cpp +++ b/content/base/src/nsRange.cpp @@ -103,6 +103,7 @@ nsresult nsRange::CompareNodeToRange(nsIContent* aNode, nsIRange* aRange, PRBool *outNodeBefore, PRBool *outNodeAfter) { + NS_ENSURE_STATE(aNode); // create a pair of dom points that expresses location of node: // NODE(start), NODE(end) // Let incoming range be: @@ -142,14 +143,19 @@ nsRange::CompareNodeToRange(nsIContent* aNode, nsIRange* aRange, PRInt32 rangeEndOffset = range->EndOffset(); // is RANGE(start) <= NODE(start) ? + PRBool disconnected = PR_FALSE; *outNodeBefore = nsContentUtils::ComparePoints(rangeStartParent, rangeStartOffset, - parent, nodeStart) > 0; + parent, nodeStart, + &disconnected) > 0; + NS_ENSURE_TRUE(!disconnected, NS_ERROR_DOM_WRONG_DOCUMENT_ERR); + // is RANGE(end) >= NODE(end) ? *outNodeAfter = nsContentUtils::ComparePoints(rangeEndParent, rangeEndOffset, - parent, nodeEnd) < 0; - + parent, nodeEnd, + &disconnected) < 0; + NS_ENSURE_TRUE(!disconnected, NS_ERROR_DOM_WRONG_DOCUMENT_ERR); return NS_OK; } @@ -335,6 +341,18 @@ nsRange::NodeWillBeDestroyed(const nsINode* aNode) DoSetRange(nsnull, 0, nsnull, 0, nsnull); } +void +nsRange::ParentChainChanged(nsIContent *aContent) +{ + NS_ASSERTION(mRoot == aContent, "Wrong ParentChainChanged notification?"); + nsINode* newRoot = mRoot; + nsINode* tmp; + while ((tmp = newRoot->GetNodeParent())) { + newRoot = tmp; + } + DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, newRoot); +} + /******************************************************** * Utilities for comparing points: API from nsIDOMNSRange ********************************************************/ @@ -433,7 +451,9 @@ nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset, (!aRoot->GetNodeParent() && (aRoot->IsNodeOfType(nsINode::eDOCUMENT) || aRoot->IsNodeOfType(nsINode::eATTRIBUTE) || - aRoot->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT))), + aRoot->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) || + /*For backward compatibility*/ + aRoot->IsNodeOfType(nsINode::eCONTENT))), "Bad root"); if (mRoot != aRoot) { @@ -592,22 +612,14 @@ nsINode* nsRange::IsValidBoundary(nsINode* aNode) NS_ASSERTION(!root->IsNodeOfType(nsINode::eDOCUMENT), "GetCurrentDoc should have returned a doc"); - if (root->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) || - root->IsNodeOfType(nsINode::eATTRIBUTE)) { - return root; - } - #ifdef DEBUG_smaug - nsCOMPtr cont = do_QueryInterface(root); - if (cont) { - nsAutoString name; - cont->Tag()->ToString(name); - printf("nsRange::IsValidBoundary: node is not a valid boundary point [%s]\n", - NS_ConvertUTF16toUTF8(name).get()); - } + NS_WARN_IF_FALSE(root->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) || + root->IsNodeOfType(nsINode::eATTRIBUTE), + "Creating a DOM Range using root which isn't in DOM!"); #endif - return nsnull; + // We allow this because of backward compatibility. + return root; } nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset) @@ -1526,7 +1538,7 @@ nsresult nsRange::CloneContents(nsIDOMDocumentFragment** aReturn) tmpNode = clone; res = tmpNode->GetParentNode(getter_AddRefs(clone)); if (NS_FAILED(res)) return res; - if (!node) return NS_ERROR_FAILURE; + if (!clone) return NS_ERROR_FAILURE; } commonCloneAncestor = clone; @@ -1576,6 +1588,7 @@ nsresult nsRange::InsertNode(nsIDOMNode* aN) nsCOMPtr tSCParentNode; res = tStartContainer->GetParentNode(getter_AddRefs(tSCParentNode)); if(NS_FAILED(res)) return res; + NS_ENSURE_STATE(tSCParentNode); PRBool isCollapsed; res = GetCollapsed(&isCollapsed); diff --git a/content/base/src/nsRange.h b/content/base/src/nsRange.h index 96b5a8811bc2..4eca4d2d1b63 100644 --- a/content/base/src/nsRange.h +++ b/content/base/src/nsRange.h @@ -110,6 +110,7 @@ public: nsIContent* aChild, PRInt32 aIndexInContainer); virtual void NodeWillBeDestroyed(const nsINode* aNode); + virtual void ParentChainChanged(nsIContent *aContent); private: // no copy's or assigns diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 8b8491a7fc2c..4a7083b814b4 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -164,6 +164,7 @@ _TEST_FILES = test_bug5141.html \ test_bug403868.xml \ test_bug405182.html \ test_bug403841.html \ + test_bug409380.html \ test_bug410229.html \ test_bug415860.html \ test_bug414190.html \ diff --git a/content/base/test/test_bug409380.html b/content/base/test/test_bug409380.html new file mode 100644 index 000000000000..c06ba7c0cc81 --- /dev/null +++ b/content/base/test/test_bug409380.html @@ -0,0 +1,379 @@ + + + + + Test for Bug 409380 + + + + + +Mozilla Bug 409380 +

+ +
+
+
+
zz
+ + +