Bug 335913: Reimplement CompareDocumentPosition using nsINode interfaces. r/sr=bz

This commit is contained in:
cvshook%sicking.cc 2006-05-16 14:51:52 +00:00
Родитель 0fa46c65df
Коммит 2241eae8cb
18 изменённых файлов: 195 добавлений и 517 удалений

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

@ -51,6 +51,7 @@
#include "nsContentList.h"
#include "nsDOMClassInfoID.h"
#include "nsIClassInfo.h"
#include "nsIDOM3Node.h"
class nsIDOMScriptObjectFactory;
class nsIXPConnect;
@ -175,41 +176,49 @@ public:
/*
* The out parameter, |aCommonAncestor| will be the closest node, if any,
* to both |aNode| and |aOther| which is also an ancestor of each.
* Returns an error if the two nodes are disconnected and don't have
* a common ancestor.
*/
static nsresult GetCommonAncestor(nsIDOMNode *aNode,
nsIDOMNode *aOther,
nsIDOMNode** aCommonAncestor);
/*
* |aDifferentNodes| will contain up to 3 elements.
* The first, if present, is the common ancestor of |aNode| and |aOther|.
* The second, if present, is the ancestor node of |aNode| which is
* closest to the common ancestor, but not an ancestor of |aOther|.
* The third, if present, is the ancestor node of |aOther| which is
* closest to the common ancestor, but not an ancestor of |aNode|.
*
* @throws NS_ERROR_FAILURE if aNode and aOther are disconnected.
/**
* Returns the common ancestor, if any, for two nodes. Returns null if the
* nodes are disconnected.
*/
static nsresult GetFirstDifferentAncestors(nsIDOMNode *aNode,
nsIDOMNode *aOther,
nsCOMArray<nsIDOMNode>& aDifferentNodes);
static nsINode* GetCommonAncestor(nsINode* aNode1,
nsINode* aNode2);
/**
* Compares the document position of nodes which may have parents.
* DO NOT pass in nodes that cannot have a parentNode. In other words:
* DO NOT pass in Attr, Document, DocumentFragment, Entity, or Notation!
* The results will be completely wrong!
* Compares the document position of nodes.
*
* @param aNode The node to which you are comparing.
* @param aOther The reference node to which aNode is compared.
* @param aNode1 The node whose position is being compared to the reference
* node
* @param aNode2 The reference node
*
* @return The document position flags of the nodes.
* @return The document position flags of the nodes. aNode1 is compared to
* aNode2, i.e. if aNode1 is before aNode2 then
* DOCUMENT_POSITION_PRECEDING will be set.
*
* @see nsIDOMNode
* @see nsIDOM3Node
*/
static PRUint16 ComparePositionWithAncestors(nsIDOMNode *aNode,
nsIDOMNode *aOther);
static PRUint16 ComparePosition(nsINode* aNode1,
nsINode* aNode2);
/**
* Returns true if aNode1 is before aNode2 in the same connected
* tree.
*/
static PRBool PositionIsBefore(nsINode* aNode1,
nsINode* aNode2)
{
return ComparePosition(aNode1, aNode2) &
(nsIDOM3Node::DOCUMENT_POSITION_PRECEDING |
nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED) ==
nsIDOM3Node::DOCUMENT_POSITION_PRECEDING;
}
/**
* Brute-force search of the element subtree rooted at aContent for

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

@ -175,7 +175,7 @@ public:
* If the return value is not -1, then calling GetChildAt() with that value
* will return aPossibleChild.
*/
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const = 0;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const = 0;
/**
* Do we need a GetCurrentDoc of some sort? I don't think we do...

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

@ -220,7 +220,7 @@ nsAttrAndChildArray::RemoveChildAt(PRUint32 aPos)
}
PRInt32
nsAttrAndChildArray::IndexOfChild(nsIContent* aPossibleChild) const
nsAttrAndChildArray::IndexOfChild(nsINode* aPossibleChild) const
{
if (!mImpl) {
return -1;

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

@ -48,6 +48,7 @@
#include "nsAttrName.h"
#include "nsAttrValue.h"
class nsINode;
class nsIContent;
class nsMappedAttributes;
class nsHTMLStyleSheet;
@ -93,7 +94,7 @@ public:
}
nsresult InsertChildAt(nsIContent* aChild, PRUint32 aPos);
void RemoveChildAt(PRUint32 aPos);
PRInt32 IndexOfChild(nsIContent* aPossibleChild) const;
PRInt32 IndexOfChild(nsINode* aPossibleChild) const;
PRUint32 AttrCount() const;
const nsAttrValue* GetAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;

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

@ -148,6 +148,11 @@ public:
return !IsAtom() && NodeInfo()->Equals(aLocalName, aNamespaceID);
}
PRBool Equals(nsINodeInfo* aNodeInfo) const
{
return Equals(aNodeInfo->NameAtom(), aNodeInfo->NamespaceID());
}
PRInt32 NamespaceID() const
{
return IsAtom() ? kNameSpaceID_None : NodeInfo()->NamespaceID();

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

@ -597,19 +597,9 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
* We want to append instead of invalidating if the first thing
* that got appended comes after ourLastContent.
*/
nsCOMPtr<nsIDOM3Node> ourLastDOM3Node(do_QueryInterface(ourLastContent));
if (ourLastDOM3Node) {
nsCOMPtr<nsIDOMNode> newNode =
do_QueryInterface(aContainer->GetChildAt(aNewIndexInContainer));
NS_ASSERTION(newNode, "Content being inserted is not a node.... why?");
PRUint16 comparisonFlags;
nsresult rv =
ourLastDOM3Node->CompareDocumentPosition(newNode, &comparisonFlags);
if (NS_SUCCEEDED(rv) &&
(comparisonFlags & nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING)) {
appendToList = PR_TRUE;
}
if (nsContentUtils::PositionIsBefore(ourLastContent,
aContainer->GetChildAt(aNewIndexInContainer))) {
appendToList = PR_TRUE;
}
}

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

@ -129,6 +129,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsICharsetConverterManager.h"
#include "nsXULAtoms.h"
#include "nsIEventListenerManager.h"
#include "nsAttrName.h"
// for ReportToConsole
#include "nsIStringBundle.h"
@ -1179,213 +1180,164 @@ nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
{
*aCommonAncestor = nsnull;
nsCOMArray<nsIDOMNode> nodeArray;
nsresult rv = GetFirstDifferentAncestors(aNode, aOther, nodeArray);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode);
nsCOMPtr<nsINode> node2 = do_QueryInterface(aOther);
nsIDOMNode *common = nodeArray[0];
NS_ENSURE_TRUE(node1 && node2, NS_ERROR_UNEXPECTED);
NS_ASSERTION(common, "The common ancestor is null! Very bad!");
nsINode* common = GetCommonAncestor(node1, node2);
NS_ENSURE_TRUE(common, NS_ERROR_NOT_AVAILABLE);
*aCommonAncestor = common;
NS_IF_ADDREF(*aCommonAncestor);
return NS_OK;
return CallQueryInterface(common, aCommonAncestor);
}
// static
nsresult
nsContentUtils::GetFirstDifferentAncestors(nsIDOMNode *aNode,
nsIDOMNode *aOther,
nsCOMArray<nsIDOMNode>& aDifferentNodes)
nsINode*
nsContentUtils::GetCommonAncestor(nsINode* aNode1,
nsINode* aNode2)
{
NS_ENSURE_ARG_POINTER(aNode);
NS_ENSURE_ARG_POINTER(aOther);
if (aDifferentNodes.Count() != 0) {
NS_WARNING("The aDifferentNodes array passed in is not empty!");
aDifferentNodes.Clear();
if (aNode1 == aNode2) {
return aNode1;
}
// Test if both are the same node.
if (aNode == aOther) {
aDifferentNodes.AppendObject(aNode);
return NS_OK;
}
nsCOMArray<nsIDOMNode> nodeAncestors;
nsCOMArray<nsIDOMNode> otherAncestors;
// Insert all the ancestors of |aNode|
nsCOMPtr<nsIDOMNode> node(aNode);
nsCOMPtr<nsIDOMNode> ancestor(node);
// Build the chain of parents
nsAutoVoidArray parents1, parents2;
do {
nodeAncestors.AppendObject(node);
node->GetParentNode(getter_AddRefs(ancestor));
if (ancestor == aOther) {
aDifferentNodes.AppendObject(aOther);
return NS_OK;
parents1.AppendElement(aNode1);
aNode1 = aNode1->GetNodeParent();
} while (aNode1);
do {
parents2.AppendElement(aNode2);
aNode2 = aNode2->GetNodeParent();
} while (aNode2);
// Find where the parent chain differs
PRUint32 pos1 = parents1.Count();
PRUint32 pos2 = parents2.Count();
nsINode* parent = nsnull;
PRUint32 len;
for (len = PR_MIN(pos1, pos2); len > 0; --len) {
nsINode* child1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* child2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
if (child1 != child2) {
break;
}
node.swap(ancestor);
} while (node);
// Insert all the ancestors of |aOther|
nsCOMPtr<nsIDOMNode> other(aOther);
ancestor = other;
do {
otherAncestors.AppendObject(other);
other->GetParentNode(getter_AddRefs(ancestor));
if (ancestor == aNode) {
aDifferentNodes.AppendObject(aNode);
return NS_OK;
}
other.swap(ancestor);
} while (other);
PRInt32 nodeIdx = nodeAncestors.Count() - 1;
PRInt32 otherIdx = otherAncestors.Count() - 1;
if (nodeAncestors[nodeIdx] != otherAncestors[otherIdx]) {
// These two nodes are disconnected. We can't get a common ancestor.
return NS_ERROR_FAILURE;
parent = child1;
}
// Go back through the ancestors, starting from the root,
// until the first different ancestor found.
do {
--nodeIdx;
--otherIdx;
} while (nodeAncestors[nodeIdx] == otherAncestors[otherIdx]);
NS_ASSERTION(nodeIdx >= 0 && otherIdx >= 0,
"Something's wrong: our indices should not be negative here!");
aDifferentNodes.AppendObject(nodeAncestors[nodeIdx + 1]);
aDifferentNodes.AppendObject(nodeAncestors[nodeIdx]);
aDifferentNodes.AppendObject(otherAncestors[otherIdx]);
return NS_OK;
return parent;
}
PRUint16
nsContentUtils::ComparePositionWithAncestors(nsIDOMNode *aNode,
nsIDOMNode *aOther)
nsContentUtils::ComparePosition(nsINode* aNode1,
nsINode* aNode2)
{
#ifdef DEBUG
PRUint16 nodeType = 0;
PRUint16 otherType = 0;
aNode->GetNodeType(&nodeType);
aOther->GetNodeType(&otherType);
NS_PRECONDITION(aNode1 && aNode2, "don't pass null");
NS_PRECONDITION(nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
nodeType != nsIDOMNode::DOCUMENT_NODE &&
nodeType != nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
nodeType != nsIDOMNode::ENTITY_NODE &&
nodeType != nsIDOMNode::NOTATION_NODE &&
otherType != nsIDOMNode::ATTRIBUTE_NODE &&
otherType != nsIDOMNode::DOCUMENT_NODE &&
otherType != nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
otherType != nsIDOMNode::ENTITY_NODE &&
otherType != nsIDOMNode::NOTATION_NODE,
"Bad. Go read the documentation in the header!");
#endif // DEBUG
PRUint16 mask = 0;
nsCOMArray<nsIDOMNode> nodeAncestors;
nsresult rv =
nsContentUtils::GetFirstDifferentAncestors(aNode, aOther, nodeAncestors);
if (NS_FAILED(rv)) {
// If there is no common container node, then the order is based upon
// order between the root container of each node that is in no container.
// In this case, the result is disconnected and implementation-dependent.
mask = (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
return mask;
if (aNode1 == aNode2) {
return 0;
}
nsIDOMNode* commonAncestor = nodeAncestors[0];
nsAutoVoidArray parents1, parents2;
if (commonAncestor == aNode) {
mask = (nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY |
nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
return mask;
// Check if either node is an attribute
nsIAttribute* attr1 = nsnull;
if (aNode1->IsNodeOfType(nsINode::eATTRIBUTE)) {
attr1 = NS_STATIC_CAST(nsIAttribute*, aNode1);
nsIContent* elem = attr1->GetContent();
// If there is an owner element add the attribute
// to the chain and walk up to the element
if (elem) {
aNode1 = elem;
parents1.AppendElement(attr1);
}
}
if (aNode2->IsNodeOfType(nsINode::eATTRIBUTE)) {
nsIAttribute* attr2 = NS_STATIC_CAST(nsIAttribute*, aNode2);
nsIContent* elem = attr2->GetContent();
if (elem == aNode1 && attr1) {
// Both nodes are attributes on the same element.
// Compare position between the attributes.
if (commonAncestor == aOther) {
mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINS |
nsIDOM3Node::DOCUMENT_POSITION_PRECEDING);
return mask;
}
// GetFirstDifferentAncestors should only succeed if one of the
// two nodes is the common ancestor, or if we have a common ancestor
// and the two first different ancestors. We checked the case above
// where one of the two nodes were the common ancestor, so we must
// have three items in our array now.
NS_ASSERTION(commonAncestor && nodeAncestors.Count() == 3,
"Something's wrong");
nsIDOMNode* nodeAncestor = nodeAncestors[1];
nsIDOMNode* otherAncestor = nodeAncestors[2];
if (nodeAncestor && otherAncestor) {
// Find out which of the two nodes comes first in the document order.
// First get the children of the common ancestor.
nsCOMPtr<nsIDOMNodeList> children;
commonAncestor->GetChildNodes(getter_AddRefs(children));
PRUint32 numKids;
children->GetLength(&numKids);
for (PRUint32 i = 0; i < numKids; ++i) {
// Then go through the children one at a time to see which we hit first.
nsCOMPtr<nsIDOMNode> childNode;
children->Item(i, getter_AddRefs(childNode));
if (childNode == nodeAncestor) {
mask |= nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING;
break;
PRUint32 i;
const nsAttrName* attrName;
for (i = 0; (attrName = elem->GetAttrNameAt(i)); ++i) {
if (attrName->Equals(attr1->NodeInfo())) {
NS_ASSERTION(!attrName->Equals(attr2->NodeInfo()),
"Different attrs at same position");
return nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
nsIDOM3Node::DOCUMENT_POSITION_PRECEDING;
}
if (attrName->Equals(attr2->NodeInfo())) {
return nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING;
}
}
NS_NOTREACHED("neither attribute in the element");
return nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED;
}
if (childNode == otherAncestor) {
mask |= nsIDOM3Node::DOCUMENT_POSITION_PRECEDING;
break;
}
if (elem) {
aNode2 = elem;
parents2.AppendElement(attr2);
}
}
return mask;
}
// We now know that both nodes are either nsIContents or nsIDocuments.
// If either node started out as an attribute, that attribute will have
// the same relative position as its ownerElement, except if the
// ownerElement ends up being the container for the other node
PRUint16
nsContentUtils::ReverseDocumentPosition(PRUint16 aDocumentPosition)
{
// Disconnected and implementation-specific flags cannot be reversed.
// Keep them.
PRUint16 reversedPosition =
aDocumentPosition & (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
// Build the chain of parents
do {
parents1.AppendElement(aNode1);
aNode1 = aNode1->GetNodeParent();
} while (aNode1);
do {
parents2.AppendElement(aNode2);
aNode2 = aNode2->GetNodeParent();
} while (aNode2);
// Following/preceding
if (aDocumentPosition & nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING) {
reversedPosition |= nsIDOM3Node::DOCUMENT_POSITION_PRECEDING;
}
else if (aDocumentPosition & nsIDOM3Node::DOCUMENT_POSITION_PRECEDING) {
reversedPosition |= nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING;
// Check if the nodes are disconnected.
PRUint32 pos1 = parents1.Count();
PRUint32 pos2 = parents2.Count();
nsINode* top1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* top2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
if (top1 != top2) {
return top1 < top2 ?
(nsIDOM3Node::DOCUMENT_POSITION_PRECEDING |
nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) :
(nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING |
nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
}
// Is contained/contains.
if (aDocumentPosition & nsIDOM3Node::DOCUMENT_POSITION_CONTAINS) {
reversedPosition |= nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY;
}
else if (aDocumentPosition & nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY) {
reversedPosition |= nsIDOM3Node::DOCUMENT_POSITION_CONTAINS;
// Find where the parent chain differs and check indices in the parent.
nsINode* parent = top1;
PRUint32 len;
for (len = PR_MIN(pos1, pos2); len > 0; --len) {
nsINode* child1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* child2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
if (child1 != child2) {
// child1 or child2 can be an attribute here. This will work fine since
// IndexOf will return -1 for the attribute making the attribute be
// considered before any child.
return parent->IndexOf(child1) < parent->IndexOf(child2) ?
NS_STATIC_CAST(PRUint16, nsIDOM3Node::DOCUMENT_POSITION_PRECEDING) :
NS_STATIC_CAST(PRUint16, nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
}
parent = child1;
}
return reversedPosition;
// We hit the end of one of the parent chains without finding a difference
// between the chains. That must mean that one node is an ancestor of the
// other. The one with the shortest chain must be the ancestor.
return pos1 < pos2 ?
(nsIDOM3Node::DOCUMENT_POSITION_PRECEDING |
nsIDOM3Node::DOCUMENT_POSITION_CONTAINS) :
(nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING |
nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY);
}
inline PRBool
@ -1753,14 +1705,7 @@ nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
// we check whether the content comes after the form. If it does,
// return true. If it does not, then it couldn't have been inside
// the form in the HTML.
nsCOMPtr<nsIDOM3Node> contentAsDOM3(do_QueryInterface(aContent));
PRUint16 comparisonFlags = 0;
nsresult rv = NS_OK;
if (contentAsDOM3) {
rv = contentAsDOM3->CompareDocumentPosition(aForm, &comparisonFlags);
}
if (NS_FAILED(rv) ||
comparisonFlags & nsIDOM3Node::DOCUMENT_POSITION_PRECEDING) {
if (PositionIsBefore(form, aContent)) {
// We could be in this form!
// In the future, we may want to get document.forms, look at the
// form after aForm, and if aContent is after that form after

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

@ -504,135 +504,11 @@ nsDOMAttribute::CompareDocumentPosition(nsIDOMNode* aOther,
PRUint16* aReturn)
{
NS_ENSURE_ARG_POINTER(aOther);
NS_PRECONDITION(aReturn, "Must have an out parameter");
PRUint16 mask = 0;
nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
PRBool sameNode = PR_FALSE;
IsSameNode(aOther, &sameNode);
if (sameNode) {
// If the two nodes being compared are the same node,
// then no flags are set on the return.
*aReturn = 0;
return NS_OK;
}
nsCOMPtr<nsIDOMElement> el;
GetOwnerElement(getter_AddRefs(el));
if (!el) {
// If we have no owner element then there is no common container node,
// (of course there isn't if we have no container!) and the order is
// then based upon order between the root container of each node that
// is in no container. In this case, the result is disconnected
// and implementation-dependent.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
*aReturn = mask;
return NS_OK;
}
// Check to see if the other node is also an attribute
PRUint16 nodeType = 0;
aOther->GetNodeType(&nodeType);
if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
nsCOMPtr<nsIDOMAttr> otherAttr(do_QueryInterface(aOther));
nsCOMPtr<nsIDOMElement> otherEl;
otherAttr->GetOwnerElement(getter_AddRefs(otherEl));
if (!otherEl) {
// This is as if they were comparing to us, and our element was null.
// See "if (!el)" above.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
}
else if (el == otherEl) {
// If neither of the two determining nodes is a child node and
// nodeType is the same for both determining nodes, then an
// implementation-dependent order between the determining nodes
// is returned.
mask |= nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
}
else
{
// For attrs owned by elements A and B, if A != B, the right value is
// comparing the tree position of A and B.
nsCOMPtr<nsIDOM3Node> elNode3(do_QueryInterface(el));
PRUint16 parentMask;
elNode3->CompareDocumentPosition(otherEl, &parentMask);
// Though elements can contain each other, attributes can't.
parentMask &= ~(nsIDOM3Node::DOCUMENT_POSITION_CONTAINS |
nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY);
mask |= parentMask;
}
*aReturn = mask;
return NS_OK;
}
if (nodeType == nsIDOMNode::TEXT_NODE ||
nodeType == nsIDOMNode::CDATA_SECTION_NODE ||
nodeType == nsIDOMNode::ENTITY_REFERENCE_NODE) {
// XXXcaa we really should check the other node's parentNode
// against ourselves. But since we can't, we should walk our
// child node list to see if it's a descendant. But wait!
// We suck so bad that we cannot even do that, since we store
// only one text node per attribute, even if there are multiple.
// So technically, we could walk the child nodes list, but it
// would not make sense really to walk it for only one thing.
// How lame. So.... it seems the only option that we DO have
// is to get our one and only child and compare it against the
// other node. As such, that is exactly what we'll do.
// *Sigh* These silly hacks are quite disgusting, really....
nsCOMPtr<nsIDOMNode> ourOnlyChild;
GetFirstChild(getter_AddRefs(ourOnlyChild));
nsCOMPtr<nsIDOM3Node> longLostRelative(do_QueryInterface(aOther));
NS_ASSERTION(longLostRelative, "All our data nodes support DOM3Node");
longLostRelative->IsSameNode(ourOnlyChild, &sameNode);
if (sameNode) {
// Woohoo! We found our long lost relative and it's our child!
// Throw a party! Celebrate by returning that it is contained
// and following this node.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY |
nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
*aReturn = mask;
return NS_OK;
}
// Sigh. The other node isn't our child, but it still may be
// related to us. Fall through so we can keep looking.
}
// The other node isn't an attribute, or a child.
// Compare position relative to this attribute's owner element.
nsCOMPtr<nsIDOM3Node> parent(do_QueryInterface(el));
parent->IsSameNode(aOther, &sameNode);
if (sameNode) {
// If the other node contains us, then it precedes us.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINS |
nsIDOM3Node::DOCUMENT_POSITION_PRECEDING);
*aReturn = mask;
return NS_OK;
}
PRUint16 parentMask = 0;
parent->CompareDocumentPosition(aOther, &parentMask);
// We already established earlier that the node is not contained
// by this attribute. So if it is contained by our owner element,
// unset the flag.
mask |= parentMask & ~nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY;
*aReturn = mask;
*aReturn = nsContentUtils::ComparePosition(other, this);
return NS_OK;
}
@ -789,7 +665,7 @@ nsDOMAttribute::GetChildAt(PRUint32 aIndex) const
}
PRInt32
nsDOMAttribute::IndexOf(nsIContent* aPossibleChild) const
nsDOMAttribute::IndexOf(nsINode* aPossibleChild) const
{
// No need to call EnsureChildState here. If we don't already have a child
// then aPossibleChild can't possibly be our child.

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

@ -112,7 +112,7 @@ public:
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);

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

@ -1707,7 +1707,7 @@ nsDocument::GetChildAt(PRUint32 aIndex) const
}
PRInt32
nsDocument::IndexOf(nsIContent* aPossibleChild) const
nsDocument::IndexOf(nsINode* aPossibleChild) const
{
return mChildren.IndexOfChild(aPossibleChild);
}
@ -3614,69 +3614,16 @@ NS_IMETHODIMP
nsDocument::CompareDocumentPosition(nsIDOMNode* aOther, PRUint16* aReturn)
{
NS_ENSURE_ARG_POINTER(aOther);
NS_PRECONDITION(aReturn, "Must have an out parameter");
if (this == aOther) {
// If the two nodes being compared are the same node,
// then no flags are set on the return.
*aReturn = 0;
// We could optimize this by getting the other nodes current document
// and comparing with ourself. But then we'd have to deal with the
// current document being null and such so it's easier this way.
// It's hardly a case to optimize anyway.
return NS_OK;
}
PRUint16 mask = 0;
nsCOMPtr<nsIContent> otherContent(do_QueryInterface(aOther));
if (!otherContent) {
PRUint16 otherNodeType = 0;
aOther->GetNodeType(&otherNodeType);
NS_ASSERTION(otherNodeType == nsIDOMNode::DOCUMENT_NODE ||
otherNodeType == nsIDOMNode::ATTRIBUTE_NODE,
"Hmm, this really _should_ support nsIContent...");
if (otherNodeType == nsIDOMNode::ATTRIBUTE_NODE) {
nsCOMPtr<nsIDOMAttr> otherAttr(do_QueryInterface(aOther));
NS_ASSERTION(otherAttr, "Attributes really should be supporting "
"nsIDOMAttr you know...");
nsCOMPtr<nsIDOMElement> otherOwnerEl;
otherAttr->GetOwnerElement(getter_AddRefs(otherOwnerEl));
if (otherOwnerEl) {
// Documents have no direct relationship to attribute
// nodes. So we'll look at our relationship in relation
// to its owner element, since that is also our relation
// to the attribute.
return CompareDocumentPosition(otherOwnerEl, aReturn);
}
}
// If there is no common container node, then the order
// is based upon order between the root container of each
// node that is in no container. In this case, the result
// is disconnected and implementation-dependent.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
*aReturn = mask;
return NS_OK;
}
if (this == otherContent->GetDocument()) {
// If the node being compared is contained by our node,
// then it follows it.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY |
nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
}
else {
// If there is no common container node, then the order
// is based upon order between the root container of each
// node that is in no container. In this case, the result
// is disconnected and implementation-dependent.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
}
*aReturn = mask;
nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
*aReturn = nsContentUtils::ComparePosition(other, this);
return NS_OK;
}

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

@ -531,7 +531,7 @@ public:
// nsINode
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual PRUint32 GetChildCount() const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);

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

@ -267,53 +267,11 @@ nsDocumentFragment::CompareDocumentPosition(nsIDOMNode* aOther,
PRUint16* aReturn)
{
NS_ENSURE_ARG_POINTER(aOther);
NS_PRECONDITION(aReturn, "Must have an out parameter");
if (this == aOther) {
// If the two nodes being compared are the same node,
// then no flags are set on the return.
*aReturn = 0;
return NS_OK;
}
nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
PRUint16 mask = 0;
nsCOMPtr<nsIDOMNode> other(aOther);
do {
nsCOMPtr<nsIDOMNode> tmp(other);
tmp->GetParentNode(getter_AddRefs(other));
if (!other) {
// No parent. Check to see if we're at an attribute node.
PRUint16 nodeType = 0;
tmp->GetNodeType(&nodeType);
if (nodeType != nsIDOMNode::ATTRIBUTE_NODE) {
// If there is no common container node, then the order
// is based upon order between the root container of each
// node that is in no container. In this case, the result
// is disconnected and implementation-dependent.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED |
nsIDOM3Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
break;
}
// If we are, let's get the owner element and continue up the tree
nsCOMPtr<nsIDOMAttr> attr(do_QueryInterface(tmp));
nsCOMPtr<nsIDOMElement> owner;
attr->GetOwnerElement(getter_AddRefs(owner));
other = do_QueryInterface(owner);
}
if (NS_STATIC_CAST(nsIDOMNode*, this) == other) {
// If the node being compared is contained by our node,
// then it follows it.
mask |= (nsIDOM3Node::DOCUMENT_POSITION_CONTAINED_BY |
nsIDOM3Node::DOCUMENT_POSITION_FOLLOWING);
break;
}
} while (other);
*aReturn = mask;
*aReturn = nsContentUtils::ComparePosition(other, this);
return NS_OK;
}

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

@ -831,7 +831,7 @@ nsGenericDOMDataNode::GetChildAt(PRUint32 aIndex) const
}
PRInt32
nsGenericDOMDataNode::IndexOf(nsIContent* aPossibleChild) const
nsGenericDOMDataNode::IndexOf(nsINode* aPossibleChild) const
{
return -1;
}

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

@ -187,7 +187,7 @@ public:
// nsINode methods
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);

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

@ -479,59 +479,11 @@ nsNode3Tearoff::CompareDocumentPosition(nsIDOMNode* aOther,
PRUint16* aReturn)
{
NS_ENSURE_ARG_POINTER(aOther);
NS_PRECONDITION(aReturn, "Must have an out parameter");
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
if (node == aOther) {
// If the two nodes being compared are the same node,
// then no flags are set on the return.
*aReturn = 0;
return NS_OK;
}
nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
PRUint16 mask = 0;
// If the other node is an attribute, document, or document fragment,
// we can find the position easier by comparing this node relative to
// the other node, and then reversing positions.
PRUint16 otherType = 0;
aOther->GetNodeType(&otherType);
if (otherType == nsIDOMNode::ATTRIBUTE_NODE ||
otherType == nsIDOMNode::DOCUMENT_NODE ||
otherType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
PRUint16 otherMask = 0;
nsCOMPtr<nsIDOM3Node> other(do_QueryInterface(aOther));
other->CompareDocumentPosition(node, &otherMask);
*aReturn = nsContentUtils::ReverseDocumentPosition(otherMask);
return NS_OK;
}
#ifdef DEBUG
{
PRUint16 nodeType = 0;
node->GetNodeType(&nodeType);
if (nodeType == nsIDOMNode::ENTITY_NODE ||
nodeType == nsIDOMNode::NOTATION_NODE) {
NS_NOTYETIMPLEMENTED("Entities and Notations are not fully supported yet");
}
else {
NS_ASSERTION((nodeType == nsIDOMNode::ELEMENT_NODE ||
nodeType == nsIDOMNode::TEXT_NODE ||
nodeType == nsIDOMNode::CDATA_SECTION_NODE ||
nodeType == nsIDOMNode::ENTITY_REFERENCE_NODE ||
nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
nodeType == nsIDOMNode::COMMENT_NODE ||
nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE),
"Invalid node type!");
}
}
#endif
mask |= nsContentUtils::ComparePositionWithAncestors(node, aOther);
*aReturn = mask;
*aReturn = nsContentUtils::ComparePosition(other, mContent);
return NS_OK;
}
@ -539,14 +491,9 @@ NS_IMETHODIMP
nsNode3Tearoff::IsSameNode(nsIDOMNode* aOther,
PRBool* aReturn)
{
PRBool sameNode = PR_FALSE;
nsCOMPtr<nsIContent> other(do_QueryInterface(aOther));
if (mContent == other) {
sameNode = PR_TRUE;
}
*aReturn = mContent == other;
*aReturn = sameNode;
return NS_OK;
}
@ -3807,7 +3754,7 @@ nsGenericElement::GetChildAt(PRUint32 aIndex) const
}
PRInt32
nsGenericElement::IndexOf(nsIContent* aPossibleChild) const
nsGenericElement::IndexOf(nsINode* aPossibleChild) const
{
return mAttrsAndChildren.IndexOfChild(aPossibleChild);
}

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

@ -307,7 +307,7 @@ public:
// nsINode interface methods
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);

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

@ -1014,7 +1014,7 @@ nsXULElement::GetChildAt(PRUint32 aIndex) const
}
PRInt32
nsXULElement::IndexOf(nsIContent* aPossibleChild) const
nsXULElement::IndexOf(nsINode* aPossibleChild) const
{
if (NS_FAILED(EnsureContentsGenerated())) {
return -1;

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

@ -464,7 +464,7 @@ public:
// nsINode
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);