diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index e7efe3151d91..efc9305aa0e3 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -68,6 +68,7 @@ #include "nsReadableUtils.h" #include "nsIPrefBranch2.h" #include "mozilla/AutoRestore.h" +#include "nsINode.h" #include "jsapi.h" @@ -75,7 +76,6 @@ struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will f class nsIDOMScriptObjectFactory; class nsIXPConnect; -class nsINode; class nsIContent; class nsIDOMNode; class nsIDOMKeyEvent; @@ -269,23 +269,6 @@ public: static nsINode* GetCommonAncestor(nsINode* aNode1, nsINode* aNode2); - /** - * Compares the document position of nodes. - * - * @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. 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 ComparePosition(nsINode* aNode1, - nsINode* aNode2); - /** * Returns true if aNode1 is before aNode2 in the same connected * tree. @@ -293,7 +276,7 @@ public: static PRBool PositionIsBefore(nsINode* aNode1, nsINode* aNode2) { - return (ComparePosition(aNode1, aNode2) & + return (aNode2->CompareDocumentPosition(aNode1) & (nsIDOM3Node::DOCUMENT_POSITION_PRECEDING | nsIDOM3Node::DOCUMENT_POSITION_DISCONNECTED)) == nsIDOM3Node::DOCUMENT_POSITION_PRECEDING; diff --git a/content/base/public/nsIContent.h b/content/base/public/nsIContent.h index ea9d88424b57..b75ebd1fb6e4 100644 --- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -911,6 +911,10 @@ public: nsIAtom* LookupPrefix(const nsAString& aNamespaceURI); + PRBool IsEqual(nsIContent *aOther); + + virtual PRBool IsEqualNode(nsINode* aOther); + private: /** * Hook for implementing GetClasses. This is guaranteed to only be diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 3ff5dad7a42d..156b59befe36 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -1009,6 +1009,35 @@ public: const nsAString& aVersion, nsISupports** aReturn); + /** + * Compares the document position of a node to this node. + * + * @param aOtherNode The node whose position is being compared to this node + * + * @return The document position flags of the nodes. aOtherNode is compared + * to this node, i.e. if aOtherNode is before this node then + * DOCUMENT_POSITION_PRECEDING will be set. + * + * @see nsIDOMNode + * @see nsIDOM3Node + */ + PRUint16 CompareDocumentPosition(nsINode* aOtherNode); + nsresult CompareDocumentPosition(nsINode* aOtherNode, PRUint16* aResult) + { + NS_ENSURE_ARG(aOtherNode); + + *aResult = CompareDocumentPosition(aOtherNode); + + return NS_OK; + } + + PRBool IsSameNode(nsINode *aOtherNode) + { + return aOtherNode == this; + } + + virtual PRBool IsEqualNode(nsINode *aOtherNode) = 0; + void LookupPrefix(const nsAString& aNamespaceURI, nsAString& aPrefix); PRBool IsDefaultNamespace(const nsAString& aNamespaceURI) { diff --git a/content/base/src/nsDOMAttribute.cpp b/content/base/src/nsDOMAttribute.cpp index d554431f9249..7fdf8098750c 100644 --- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -523,22 +523,20 @@ NS_IMETHODIMP nsDOMAttribute::CompareDocumentPosition(nsIDOMNode* aOther, PRUint16* aReturn) { - NS_ENSURE_ARG_POINTER(aOther); - nsCOMPtr other = do_QueryInterface(aOther); NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR); - *aReturn = nsContentUtils::ComparePosition(other, this); - return NS_OK; + return nsINode::CompareDocumentPosition(other, aReturn); } NS_IMETHODIMP nsDOMAttribute::IsSameNode(nsIDOMNode* aOther, PRBool* aReturn) { - NS_ASSERTION(aReturn, "IsSameNode() called with aReturn == nsnull!"); + nsCOMPtr other = do_QueryInterface(aOther); + NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR); - *aReturn = SameCOMIdentity(static_cast(this), aOther); + *aReturn = nsINode::IsSameNode(other); return NS_OK; } @@ -547,35 +545,33 @@ NS_IMETHODIMP nsDOMAttribute::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn) { - *aReturn = PR_FALSE; + nsCOMPtr other = do_QueryInterface(aOther); - if (!aOther) - return NS_OK; + *aReturn = other && IsEqualNode(other); - // Node type check by QI. We also reuse this later. - nsCOMPtr aOtherAttr = do_QueryInterface(aOther); - if (!aOtherAttr) { - return NS_OK; - } + return NS_OK; +} + +PRBool +nsDOMAttribute::IsEqualNode(nsINode* aOther) +{ + if (!aOther || !aOther->IsNodeOfType(eATTRIBUTE)) + return PR_FALSE; + + nsDOMAttribute *other = static_cast(aOther); // Prefix, namespace URI, local name, node name check. - if (!mNodeInfo->Equals(aOtherAttr->NodeInfo())) { - return NS_OK; + if (!mNodeInfo->Equals(other->NodeInfo())) { + return PR_FALSE; } // Value check - nsAutoString ourValue, otherValue; - nsresult rv = GetValue(ourValue); - NS_ENSURE_SUCCESS(rv, rv); - rv = aOther->GetNodeValue(otherValue); - NS_ENSURE_SUCCESS(rv, rv); - if (!ourValue.Equals(otherValue)) - return NS_OK; - // Checks not needed: Child nodes, attributes. + nsAutoString ourValue, otherValue; + GetValue(ourValue); + other->GetValue(otherValue); - *aReturn = PR_TRUE; - return NS_OK; + return ourValue.Equals(otherValue); } NS_IMETHODIMP diff --git a/content/base/src/nsDOMAttribute.h b/content/base/src/nsDOMAttribute.h index 87f090e0aa1e..ad6c8658ee63 100644 --- a/content/base/src/nsDOMAttribute.h +++ b/content/base/src/nsDOMAttribute.h @@ -116,6 +116,7 @@ public: } virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; virtual already_AddRefed GetBaseURI() const; + virtual PRBool IsEqualNode(nsINode *aOtherNode); static void Initialize(); static void Shutdown(); diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index f4e770d7aedb..916288443db1 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -5657,59 +5657,38 @@ nsDocument::SetTextContent(const nsAString& aTextContent) NS_IMETHODIMP nsDocument::CompareDocumentPosition(nsIDOMNode* aOther, PRUint16* aReturn) { - NS_ENSURE_ARG_POINTER(aOther); - - // 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. - nsCOMPtr other = do_QueryInterface(aOther); NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR); - *aReturn = nsContentUtils::ComparePosition(other, this); - return NS_OK; + return nsINode::CompareDocumentPosition(other, aReturn); } NS_IMETHODIMP nsDocument::IsSameNode(nsIDOMNode* aOther, PRBool* aReturn) { - PRBool sameNode = PR_FALSE; + nsCOMPtr other = do_QueryInterface(aOther); + NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR); - if (this == aOther) { - sameNode = PR_TRUE; - } - - *aReturn = sameNode; + *aReturn = nsINode::IsSameNode(other); return NS_OK; } -NS_IMETHODIMP -nsDocument::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn) +PRBool +nsDocument::IsEqualNode(nsINode* aOther) { - *aReturn = PR_FALSE; - - if (!aOther) - return NS_OK; - - // Node type check by QI. We also reuse this later. - nsCOMPtr aOtherDoc = do_QueryInterface(aOther); - if (!aOtherDoc) { - return NS_OK; - } + if (!aOther || !aOther->IsNodeOfType(eDOCUMENT)) + return PR_FALSE; // Child nodes check. PRUint32 childCount = GetChildCount(); - if (childCount != aOtherDoc->GetChildCount()) { - return NS_OK; + if (childCount != aOther->GetChildCount()) { + return PR_FALSE; } for (PRUint32 i = 0; i < childCount; i++) { - nsIContent* aChild1 = GetChildAt(i); - nsIContent* aChild2 = aOtherDoc->GetChildAt(i); - if (!nsNode3Tearoff::AreNodesEqual(aChild1, aChild2)) { - return NS_OK; + if (!GetChildAt(i)->IsEqual(aOther->GetChildAt(i))) { + return PR_FALSE; } } @@ -5717,7 +5696,16 @@ nsDocument::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn) node value, attributes. */ - *aReturn = PR_TRUE; + return PR_TRUE; +} + +NS_IMETHODIMP +nsDocument::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn) +{ + nsCOMPtr other = do_QueryInterface(aOther); + + *aReturn = other && IsEqualNode(other); + return NS_OK; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index a2d17835f1a9..a94d7695de7f 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -738,6 +738,7 @@ public: { return NS_ERROR_NOT_IMPLEMENTED; } + virtual PRBool IsEqualNode(nsINode* aOther); // nsIRadioGroupContainer NS_IMETHOD WalkRadioGroup(const nsAString& aName, diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index eb84e4d9e1cc..27e98c931aa3 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -675,33 +675,34 @@ nsINode::SetUserData(const nsAString &aKey, nsIVariant *aData, } PRUint16 -nsContentUtils::ComparePosition(nsINode* aNode1, - nsINode* aNode2) +nsINode::CompareDocumentPosition(nsINode* aOtherNode) { - NS_PRECONDITION(aNode1 && aNode2, "don't pass null"); + NS_PRECONDITION(aOtherNode, "don't pass null"); - if (aNode1 == aNode2) { + if (this == aOtherNode) { return 0; } nsAutoTPtrArray parents1, parents2; + nsINode *node1 = aOtherNode, *node2 = this; + // Check if either node is an attribute nsIAttribute* attr1 = nsnull; - if (aNode1->IsNodeOfType(nsINode::eATTRIBUTE)) { - attr1 = static_cast(aNode1); + if (node1->IsNodeOfType(nsINode::eATTRIBUTE)) { + attr1 = static_cast(node1); 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; + node1 = elem; parents1.AppendElement(static_cast(attr1)); } } - if (aNode2->IsNodeOfType(nsINode::eATTRIBUTE)) { - nsIAttribute* attr2 = static_cast(aNode2); + if (node2->IsNodeOfType(nsINode::eATTRIBUTE)) { + nsIAttribute* attr2 = static_cast(node2); nsIContent* elem = attr2->GetContent(); - if (elem == aNode1 && attr1) { + if (elem == node1 && attr1) { // Both nodes are attributes on the same element. // Compare position between the attributes. @@ -724,7 +725,7 @@ nsContentUtils::ComparePosition(nsINode* aNode1, } if (elem) { - aNode2 = elem; + node2 = elem; parents2.AppendElement(static_cast(attr2)); } } @@ -736,13 +737,13 @@ nsContentUtils::ComparePosition(nsINode* aNode1, // Build the chain of parents do { - parents1.AppendElement(aNode1); - aNode1 = aNode1->GetNodeParent(); - } while (aNode1); + parents1.AppendElement(node1); + node1 = node1->GetNodeParent(); + } while (node1); do { - parents2.AppendElement(aNode2); - aNode2 = aNode2->GetNodeParent(); - } while (aNode2); + parents2.AppendElement(node2); + node2 = node2->GetNodeParent(); + } while (node2); // Check if the nodes are disconnected. PRUint32 pos1 = parents1.Length(); @@ -1054,12 +1055,11 @@ NS_IMETHODIMP nsNode3Tearoff::CompareDocumentPosition(nsIDOMNode* aOther, PRUint16* aReturn) { - NS_ENSURE_ARG_POINTER(aOther); - nsCOMPtr other = do_QueryInterface(aOther); - NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR); + NS_ENSURE_ARG(other); + + *aReturn = mContent->CompareDocumentPosition(other); - *aReturn = nsContentUtils::ComparePosition(other, mContent); return NS_OK; } @@ -1067,30 +1067,29 @@ NS_IMETHODIMP nsNode3Tearoff::IsSameNode(nsIDOMNode* aOther, PRBool* aReturn) { - nsCOMPtr other(do_QueryInterface(aOther)); - *aReturn = mContent == other; + nsCOMPtr other = do_QueryInterface(aOther); + *aReturn = mContent->IsSameNode(other); return NS_OK; } PRBool -nsNode3Tearoff::AreNodesEqual(nsIContent* aContent1, - nsIContent* aContent2) +nsIContent::IsEqual(nsIContent* aOther) { // We use nsIContent instead of nsINode for the attributes of elements. - NS_PRECONDITION(aContent1 && aContent2, "Who called AreNodesEqual?"); + NS_PRECONDITION(aOther, "Who called IsEqual?"); nsAutoString string1, string2; // Prefix, namespace URI, local name, node name check. - if (!aContent1->NodeInfo()->Equals(aContent2->NodeInfo())) { + if (!NodeInfo()->Equals(aOther->NodeInfo())) { return PR_FALSE; } - if (aContent1->Tag() == nsGkAtoms::documentTypeNodeName) { - nsCOMPtr docType1 = do_QueryInterface(aContent1); - nsCOMPtr docType2 = do_QueryInterface(aContent2); + if (Tag() == nsGkAtoms::documentTypeNodeName) { + nsCOMPtr docType1 = do_QueryInterface(this); + nsCOMPtr docType2 = do_QueryInterface(aOther); NS_ASSERTION(docType1 && docType2, "Why don't we have a document type node?"); @@ -1119,25 +1118,22 @@ nsNode3Tearoff::AreNodesEqual(nsIContent* aContent1, } } - if (aContent1->IsElement()) { - // aContent1 is an element. So is aContent2, since the nodeinfos - // were equal. Do the check on attributes. - Element* element1 = aContent1->AsElement(); - Element* element2 = aContent2->AsElement(); - PRUint32 attrCount = element1->GetAttrCount(); + if (IsElement()) { + // Both are elements (we checked that their nodeinfos are equal). Do the + // check on attributes. + Element* element2 = aOther->AsElement(); + PRUint32 attrCount = GetAttrCount(); if (attrCount != element2->GetAttrCount()) { return PR_FALSE; } // Iterate over attributes. for (PRUint32 i = 0; i < attrCount; ++i) { - const nsAttrName* attrName1 = element1->GetAttrNameAt(i); + const nsAttrName* attrName1 = GetAttrNameAt(i); #ifdef DEBUG PRBool hasAttr = #endif - element1->GetAttr(attrName1->NamespaceID(), - attrName1->LocalName(), - string1); + GetAttr(attrName1->NamespaceID(), attrName1->LocalName(), string1); NS_ASSERTION(hasAttr, "Why don't we have an attr?"); if (!element2->AttrValueIs(attrName1->NamespaceID(), @@ -1149,23 +1145,21 @@ nsNode3Tearoff::AreNodesEqual(nsIContent* aContent1, } // Child nodes count. - PRUint32 childCount = element1->GetChildCount(); + PRUint32 childCount = GetChildCount(); if (childCount != element2->GetChildCount()) { return PR_FALSE; } // Iterate over child nodes. for (PRUint32 i = 0; i < childCount; ++i) { - nsIContent* child1 = element1->GetChildAt(i); - nsIContent* child2 = element2->GetChildAt(i); - if (!AreNodesEqual(child1, child2)) { + if (!GetChildAt(i)->IsEqual(element2->GetChildAt(i))) { return PR_FALSE; } } } else { - // aContent1 is not an element. Node value check. - nsCOMPtr domNode1 = do_QueryInterface(aContent1); - nsCOMPtr domNode2 = do_QueryInterface(aContent2); + // Node value check. + nsCOMPtr domNode1 = do_QueryInterface(this); + nsCOMPtr domNode2 = do_QueryInterface(aOther); NS_ASSERTION(domNode1 && domNode2, "How'd we get nsIContent without nsIDOMNode?"); domNode1->GetNodeValue(string1); domNode2->GetNodeValue(string2); @@ -1177,22 +1171,23 @@ nsNode3Tearoff::AreNodesEqual(nsIContent* aContent1, return PR_TRUE; } +PRBool +nsIContent::IsEqualNode(nsINode* aOther) +{ + if (!aOther || !aOther->IsNodeOfType(eCONTENT)) + return PR_FALSE; + + return IsEqual(static_cast(aOther)); +} + NS_IMETHODIMP nsNode3Tearoff::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn) { - *aReturn = PR_FALSE; + // Since we implement nsINode, aOther must as well. + nsCOMPtr other = do_QueryInterface(aOther); - if (!aOther) - return NS_OK; + *aReturn = other && mContent->IsEqualNode(other); - // Since we implement nsIContent, aOther must as well. - nsCOMPtr aOtherContent = do_QueryInterface(aOther); - // Documents and attributes don't implement nsIContent. - if (!aOtherContent) { - return NS_OK; - } - - *aReturn = nsNode3Tearoff::AreNodesEqual(mContent, aOtherContent); return NS_OK; } diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index c5e4431d0d48..aaabbc1dc5e4 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -159,17 +159,6 @@ public: { } - /** - * Determines whether two nodes are equal. - * - * @param aContent1 The first node to compare. - * @param aContent2 The second node to compare. - * - * @return PR_TRUE if the nodes are equal. - */ - static PRBool AreNodesEqual(nsIContent* aContent1, - nsIContent* aContent2); - protected: virtual ~nsNode3Tearoff() {}