Part 7 of fix for bug 560273 (Stop using DOM tearoffs from quickstubs) - add nsINode::IsEqualNode/CompareDocumentPosition/IsSameNode. r=jst.

--HG--
extra : rebase_source : d4722a28e8c913dcb6f9a1e7bf13261a12b60525
This commit is contained in:
Peter Van der Beken 2010-04-19 17:40:17 +02:00
Родитель 0ede6ae84d
Коммит 804eb196c3
9 изменённых файлов: 134 добавлений и 148 удалений

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

@ -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;

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

@ -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

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

@ -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)
{

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

@ -523,22 +523,20 @@ NS_IMETHODIMP
nsDOMAttribute::CompareDocumentPosition(nsIDOMNode* aOther,
PRUint16* aReturn)
{
NS_ENSURE_ARG_POINTER(aOther);
nsCOMPtr<nsINode> 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<nsINode> other = do_QueryInterface(aOther);
NS_ENSURE_TRUE(other, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
*aReturn = SameCOMIdentity(static_cast<nsIDOMNode*>(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<nsINode> other = do_QueryInterface(aOther);
if (!aOther)
return NS_OK;
*aReturn = other && IsEqualNode(other);
// Node type check by QI. We also reuse this later.
nsCOMPtr<nsIAttribute> 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<nsDOMAttribute*>(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

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

@ -116,6 +116,7 @@ public:
}
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual already_AddRefed<nsIURI> GetBaseURI() const;
virtual PRBool IsEqualNode(nsINode *aOtherNode);
static void Initialize();
static void Shutdown();

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

@ -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<nsINode> 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<nsINode> 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<nsIDocument> 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<nsINode> other = do_QueryInterface(aOther);
*aReturn = other && IsEqualNode(other);
return NS_OK;
}

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

@ -738,6 +738,7 @@ public:
{
return NS_ERROR_NOT_IMPLEMENTED;
}
virtual PRBool IsEqualNode(nsINode* aOther);
// nsIRadioGroupContainer
NS_IMETHOD WalkRadioGroup(const nsAString& aName,

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

@ -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<nsINode, 32> 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<nsIAttribute*>(aNode1);
if (node1->IsNodeOfType(nsINode::eATTRIBUTE)) {
attr1 = static_cast<nsIAttribute*>(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<nsINode*>(attr1));
}
}
if (aNode2->IsNodeOfType(nsINode::eATTRIBUTE)) {
nsIAttribute* attr2 = static_cast<nsIAttribute*>(aNode2);
if (node2->IsNodeOfType(nsINode::eATTRIBUTE)) {
nsIAttribute* attr2 = static_cast<nsIAttribute*>(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<nsINode*>(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<nsINode> 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<nsIContent> other(do_QueryInterface(aOther));
*aReturn = mContent == other;
nsCOMPtr<nsINode> 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<nsIDOMDocumentType> docType1 = do_QueryInterface(aContent1);
nsCOMPtr<nsIDOMDocumentType> docType2 = do_QueryInterface(aContent2);
if (Tag() == nsGkAtoms::documentTypeNodeName) {
nsCOMPtr<nsIDOMDocumentType> docType1 = do_QueryInterface(this);
nsCOMPtr<nsIDOMDocumentType> 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<nsIDOMNode> domNode1 = do_QueryInterface(aContent1);
nsCOMPtr<nsIDOMNode> domNode2 = do_QueryInterface(aContent2);
// Node value check.
nsCOMPtr<nsIDOMNode> domNode1 = do_QueryInterface(this);
nsCOMPtr<nsIDOMNode> 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<nsIContent*>(aOther));
}
NS_IMETHODIMP
nsNode3Tearoff::IsEqualNode(nsIDOMNode* aOther, PRBool* aReturn)
{
*aReturn = PR_FALSE;
// Since we implement nsINode, aOther must as well.
nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
if (!aOther)
return NS_OK;
*aReturn = other && mContent->IsEqualNode(other);
// Since we implement nsIContent, aOther must as well.
nsCOMPtr<nsIContent> aOtherContent = do_QueryInterface(aOther);
// Documents and attributes don't implement nsIContent.
if (!aOtherContent) {
return NS_OK;
}
*aReturn = nsNode3Tearoff::AreNodesEqual(mContent, aOtherContent);
return NS_OK;
}

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

@ -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() {}