diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index 7649bee2e81..a3b1e213267 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -43,6 +43,7 @@ #include "nsIDOMScriptObjectFactory.h" #include "nsIJSContextStack.h" #include "nsIScriptContext.h" +#include "nsCOMArray.h" class nsIScriptGlobalObject; class nsIXPConnect; @@ -133,13 +134,39 @@ public: * 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|. - * - * These elements were |nsIDOMNode*|s before casting to void* and must - * be cast back to |nsIDOMNode*| on usage, or bad things will happen. */ static nsresult GetFirstDifferentAncestors(nsIDOMNode *aNode, nsIDOMNode *aOther, - nsVoidArray* aDifferentNodes); + nsCOMArray& aDifferentNodes); + + /** + * 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! + * + * @param aNode The node to which you are comparing. + * @param aOther The reference node to which aNode is compared. + * + * @return The document position flags of the nodes. + * + * @see nsIDOMNode + * @see nsIDOM3Node + */ + static PRUint16 ComparePositionWithAncestors(nsIDOMNode *aNode, + nsIDOMNode *aOther); + + /** + * Reverses the document position flags passed in. + * + * @param aDocumentPosition The document position flags to be reversed. + * + * @return The reversed document position flags. + * + * @see nsIDOMNode + * @see nsIDOM3Node + */ + static PRUint16 ReverseDocumentPosition(PRUint16 aDocumentPosition); // These are copied from nsJSUtils.h diff --git a/mozilla/content/base/src/nsContentList.cpp b/mozilla/content/base/src/nsContentList.cpp index 0d2dcf94d3b..604848b6d97 100644 --- a/mozilla/content/base/src/nsContentList.cpp +++ b/mozilla/content/base/src/nsContentList.cpp @@ -676,10 +676,10 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer, nsCOMPtr newNode(do_QueryInterface(firstAppendedContent)); NS_ASSERTION(newNode, "Content being inserted is not a node.... why?"); PRUint16 comparisonFlags; - nsresult rv = ourLastDOM3Node->CompareTreePosition(newNode, - &comparisonFlags); + nsresult rv = + ourLastDOM3Node->CompareDocumentPosition(newNode, &comparisonFlags); if (NS_SUCCEEDED(rv) && - (comparisonFlags & nsIDOMNode::TREE_POSITION_FOLLOWING)) { + (comparisonFlags & nsIDOMNode::DOCUMENT_POSITION_FOLLOWING)) { appendToList = PR_TRUE; } } diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index 1d9660e958a..0379a1046bc 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -50,6 +50,7 @@ #include "nsINodeInfo.h" #include "nsReadableUtils.h" #include "nsIDOMDocument.h" +#include "nsIDOMNodeList.h" #include "nsIURI.h" #include "nsIScriptSecurityManager.h" #include "nsDOMError.h" @@ -1023,12 +1024,11 @@ nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode, { *aCommonAncestor = nsnull; - nsAutoVoidArray nodeArray; - nsresult rv = GetFirstDifferentAncestors(aNode, aOther, &nodeArray); + nsCOMArray nodeArray; + nsresult rv = GetFirstDifferentAncestors(aNode, aOther, nodeArray); NS_ENSURE_SUCCESS(rv, rv); - nsIDOMNode *common = - NS_STATIC_CAST(nsIDOMNode*, nodeArray.ElementAt(0)); + nsIDOMNode *common = nodeArray[0]; NS_ASSERTION(common, "The common ancestor is null! Very bad!"); @@ -1042,33 +1042,33 @@ nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode, nsresult nsContentUtils::GetFirstDifferentAncestors(nsIDOMNode *aNode, nsIDOMNode *aOther, - nsVoidArray* aDifferentNodes) + nsCOMArray& aDifferentNodes) { NS_ENSURE_ARG_POINTER(aNode); NS_ENSURE_ARG_POINTER(aOther); - if (aDifferentNodes->Count() != 0) { + if (aDifferentNodes.Count() != 0) { NS_WARNING("The aDifferentNodes array passed in is not empty!"); - aDifferentNodes->Clear(); + aDifferentNodes.Clear(); } // Test if both are the same node. if (aNode == aOther) { - aDifferentNodes->AppendElement(NS_STATIC_CAST(void*, aNode)); + aDifferentNodes.AppendObject(aNode); return NS_OK; } - nsAutoVoidArray nodeAncestors; - nsAutoVoidArray otherAncestors; + nsCOMArray nodeAncestors; + nsCOMArray otherAncestors; // Insert all the ancestors of |aNode| nsCOMPtr node(aNode); nsCOMPtr ancestor(node); do { - nodeAncestors.AppendElement(node.get()); + nodeAncestors.AppendObject(node); node->GetParentNode(getter_AddRefs(ancestor)); if (ancestor == aOther) { - aDifferentNodes->AppendElement(NS_STATIC_CAST(void*, aOther)); + aDifferentNodes.AppendObject(aOther); return NS_OK; } node = ancestor; @@ -1078,10 +1078,10 @@ nsContentUtils::GetFirstDifferentAncestors(nsIDOMNode *aNode, nsCOMPtr other(aOther); ancestor = other; do { - otherAncestors.AppendElement(other.get()); + otherAncestors.AppendObject(other); other->GetParentNode(getter_AddRefs(ancestor)); if (ancestor == aNode) { - aDifferentNodes->AppendElement(NS_STATIC_CAST(void*, aNode)); + aDifferentNodes.AppendObject(aNode); return NS_OK; } other = ancestor; @@ -1090,7 +1090,7 @@ nsContentUtils::GetFirstDifferentAncestors(nsIDOMNode *aNode, PRInt32 nodeIdx = nodeAncestors.Count() - 1; PRInt32 otherIdx = otherAncestors.Count() - 1; - if (nodeAncestors.ElementAt(nodeIdx) != otherAncestors.ElementAt(otherIdx)) { + if (nodeAncestors[nodeIdx] != otherAncestors[otherIdx]) { NS_ERROR("This function was called on two disconnected nodes!"); return NS_ERROR_FAILURE; } @@ -1100,18 +1100,139 @@ nsContentUtils::GetFirstDifferentAncestors(nsIDOMNode *aNode, do { --nodeIdx; --otherIdx; - } while (nodeAncestors.ElementAt(nodeIdx) == otherAncestors.ElementAt(otherIdx)); + } while (nodeAncestors[nodeIdx] == otherAncestors[otherIdx]); NS_ASSERTION(nodeIdx >= 0 && otherIdx >= 0, "Something's wrong: our indices should not be negative here!"); - aDifferentNodes->AppendElement(nodeAncestors.ElementAt(nodeIdx + 1)); - aDifferentNodes->AppendElement(nodeAncestors.ElementAt(nodeIdx)); - aDifferentNodes->AppendElement(otherAncestors.ElementAt(otherIdx)); + aDifferentNodes.AppendObject(nodeAncestors[nodeIdx + 1]); + aDifferentNodes.AppendObject(nodeAncestors[nodeIdx]); + aDifferentNodes.AppendObject(otherAncestors[otherIdx]); return NS_OK; } +PRUint16 +nsContentUtils::ComparePositionWithAncestors(nsIDOMNode *aNode, + nsIDOMNode *aOther) +{ +#ifdef DEBUG + PRInt16 nodeType = 0; + PRInt16 otherType = 0; + aNode->GetNodeType(&nodeType); + aOther->GetNodeType(&otherType); + + 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 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 = (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); + + return mask; + } + + nsIDOMNode* commonAncestor = nodeAncestors[0]; + + if (commonAncestor == aNode) { + mask = (nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED | + nsIDOMNode::DOCUMENT_POSITION_FOLLOWING); + + return mask; + } + + if (commonAncestor == aOther) { + mask |= (nsIDOMNode::DOCUMENT_POSITION_CONTAINS | + nsIDOMNode::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 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 childNode; + children->Item(i, getter_AddRefs(childNode)); + if (childNode == nodeAncestor) { + mask |= nsIDOMNode::DOCUMENT_POSITION_FOLLOWING; + break; + } + + if (childNode == otherAncestor) { + mask |= nsIDOMNode::DOCUMENT_POSITION_PRECEDING; + break; + } + } + } + + return mask; +} + +PRUint16 +nsContentUtils::ReverseDocumentPosition(PRUint16 aDocumentPosition) +{ + // Disconnected and implementation-specific flags cannot be reversed. + // Keep them. + PRUint16 reversedPosition = + aDocumentPosition & (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); + + // Following/preceding + if (aDocumentPosition & nsIDOMNode::DOCUMENT_POSITION_FOLLOWING) { + reversedPosition |= nsIDOMNode::DOCUMENT_POSITION_PRECEDING; + } + else if (aDocumentPosition & nsIDOMNode::DOCUMENT_POSITION_PRECEDING) { + reversedPosition |= nsIDOMNode::DOCUMENT_POSITION_FOLLOWING; + } + + // Is contained/contains. + if (aDocumentPosition & nsIDOMNode::DOCUMENT_POSITION_CONTAINS) { + reversedPosition |= nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED; + } + else if (aDocumentPosition & nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED) { + reversedPosition |= nsIDOMNode::DOCUMENT_POSITION_CONTAINS; + } + + return reversedPosition; +} + inline PRBool IsCharInSet(const char* aSet, const PRUnichar aChar) diff --git a/mozilla/content/base/src/nsDOMAttribute.cpp b/mozilla/content/base/src/nsDOMAttribute.cpp index f75b8930bd7..a548b97144f 100644 --- a/mozilla/content/base/src/nsDOMAttribute.cpp +++ b/mozilla/content/base/src/nsDOMAttribute.cpp @@ -495,48 +495,120 @@ nsDOMAttribute::GetBaseURI(nsAString &aURI) } NS_IMETHODIMP -nsDOMAttribute::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsDOMAttribute::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_ENSURE_ARG_POINTER(aOther); - PRUint16 mask = nsIDOMNode::TREE_POSITION_DISCONNECTED; + NS_PRECONDITION(aReturn, "Must have an out parameter"); + + PRUint16 mask = 0; nsCOMPtr el; GetOwnerElement(getter_AddRefs(el)); - if (el) { - // Check to see if the other node is also an attribute - PRUint16 nodeType = 0; - aOther->GetNodeType(&nodeType); - if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) { - nsCOMPtr otherAttr(do_QueryInterface(aOther)); - nsCOMPtr otherEl; - otherAttr->GetOwnerElement(getter_AddRefs(otherEl)); - if (el == otherEl) { - // same parent node, the two attributes have equivalent position - mask |= nsIDOMNode::TREE_POSITION_EQUIVALENT; - PRBool sameNode = PR_FALSE; - IsSameNode(aOther, &sameNode); - if (sameNode) { - mask |= nsIDOMNode::TREE_POSITION_SAME_NODE; - } - } - } - else { - // The other node isn't an attribute. - // Compare position relative to this attribute's owner element. - nsCOMPtr parent(do_QueryInterface(el)); - PRUint16 parentMask; - parent->CompareTreePosition(aOther, &parentMask); - if (parentMask & nsIDOMNode::TREE_POSITION_SAME_NODE) { - mask |= nsIDOMNode::TREE_POSITION_PRECEDING; - } - else { - mask |= parentMask & (nsIDOMNode::TREE_POSITION_FOLLOWING | - nsIDOMNode::TREE_POSITION_PRECEDING); - } - } + 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 |= (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::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 otherAttr(do_QueryInterface(aOther)); + nsCOMPtr otherEl; + otherAttr->GetOwnerElement(getter_AddRefs(otherEl)); + if (el == otherEl) { + PRBool sameNode = PR_FALSE; + IsSameNode(aOther, &sameNode); + if (!sameNode) { + // 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 |= nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + } + + // If the two nodes being compared are the same node, + // then no flags are set on the return. + } + + *aReturn = mask; + + return NS_OK; + } + + PRBool sameNode = PR_FALSE; + + 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 ourOnlyChild; + GetFirstChild(getter_AddRefs(ourOnlyChild)); + + nsCOMPtr 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 |= (nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED | + nsIDOMNode::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 parent(do_QueryInterface(el)); + parent->IsSameNode(aOther, &sameNode); + if (sameNode) { + // If the other node contains us, then it precedes us. + mask |= (nsIDOMNode::DOCUMENT_POSITION_CONTAINS | + nsIDOMNode::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 & ~nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED; + *aReturn = mask; return NS_OK; } @@ -558,12 +630,9 @@ nsDOMAttribute::IsSameNode(nsIDOMNode* aOther, nsCOMPtr other(do_QueryInterface(aOther)); nsCOMPtr otherOwner; other->GetOwnerElement(getter_AddRefs(otherOwner)); - nsCOMPtr owner(do_QueryInterface(nodeOwner)); - PRBool sameOwners = PR_FALSE; - owner->IsSameNode(otherOwner, &sameOwners); // Do these attributes belong to the same element? - if (sameOwners) { + if (nodeOwner == otherOwner) { PRBool ci = PR_FALSE; nsCOMPtr content(do_QueryInterface(nodeOwner)); // Check to see if we're in HTML. diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 8c2bc8e2347..dcb6c177eb2 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -3349,27 +3349,71 @@ nsDocument::GetBaseURI(nsAString &aURI) } NS_IMETHODIMP -nsDocument::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsDocument::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_ENSURE_ARG_POINTER(aOther); - PRUint16 mask = nsIDOMNode::TREE_POSITION_DISCONNECTED; + NS_PRECONDITION(aReturn, "Must have an out parameter"); - PRBool sameNode = PR_FALSE; - IsSameNode(aOther, &sameNode); - if (sameNode) { - mask |= (nsIDOMNode::TREE_POSITION_SAME_NODE | - nsIDOMNode::TREE_POSITION_EQUIVALENT); + 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; + } + + PRUint16 mask = 0; + + nsCOMPtr 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 otherAttr(do_QueryInterface(aOther)); + NS_ASSERTION(otherAttr, "Attributes really should be supporting " + "nsIDOMAttr you know..."); + + nsCOMPtr 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 |= (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); + + *aReturn = mask; + return NS_OK; + } + + nsCOMPtr otherDoc; + otherContent->GetDocument(*getter_AddRefs(otherDoc)); + if (this == otherDoc) { + // If the node being compared is contained by our node, + // then it follows it. + mask |= (nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED | + nsIDOMNode::DOCUMENT_POSITION_FOLLOWING); } else { - nsCOMPtr otherDoc; - aOther->GetOwnerDocument(getter_AddRefs(otherDoc)); - nsCOMPtr other(do_QueryInterface(otherDoc)); - IsSameNode(other, &sameNode); - if (sameNode) { - mask |= (nsIDOMNode::TREE_POSITION_DESCENDANT | - nsIDOMNode::TREE_POSITION_FOLLOWING); - } + // 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 |= (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); } *aReturn = mask; diff --git a/mozilla/content/base/src/nsDocumentFragment.cpp b/mozilla/content/base/src/nsDocumentFragment.cpp index ba7c80d5ab4..1c08d42dacc 100644 --- a/mozilla/content/base/src/nsDocumentFragment.cpp +++ b/mozilla/content/base/src/nsDocumentFragment.cpp @@ -125,7 +125,8 @@ public: // nsIDOM3Node NS_IMETHOD GetBaseURI(nsAString& aURI) { aURI.Truncate(); return NS_OK; } - NS_IMETHOD CompareTreePosition(nsIDOMNode *aOther, PRUint16* aReturn); + NS_IMETHOD CompareDocumentPosition(nsIDOMNode *aOther, + PRUint16* aReturn); NS_IMETHOD IsSameNode(nsIDOMNode *aOther, PRBool* aReturn); NS_IMETHOD LookupNamespacePrefix(const nsAString& aNamespaceURI, nsAString& aPrefix) { @@ -395,44 +396,55 @@ nsDocumentFragment::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) } NS_IMETHODIMP -nsDocumentFragment::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsDocumentFragment::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_ENSURE_ARG_POINTER(aOther); - PRUint32 mask = nsIDOMNode::TREE_POSITION_DISCONNECTED; + NS_PRECONDITION(aReturn, "Must have an out parameter"); - PRBool sameNode = PR_FALSE; - IsSameNode(aOther, &sameNode); - if (sameNode) { - mask |= nsIDOMNode::TREE_POSITION_SAME_NODE; + 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; } - else { - nsCOMPtr other(aOther); - while (other) { - IsSameNode(other, &sameNode); - if (sameNode) { - mask |= nsIDOMNode::TREE_POSITION_DESCENDANT; + + PRUint16 mask = 0; + + nsCOMPtr other(aOther); + do { + nsCOMPtr 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 |= (nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED | + nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC); + break; } - nsCOMPtr 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 we are, let's get the owner element and continue up the tree - nsCOMPtr attr(do_QueryInterface(tmp)); - nsCOMPtr owner; - attr->GetOwnerElement(getter_AddRefs(owner)); - other = do_QueryInterface(owner); - continue; - } - break; - } + // If we are, let's get the owner element and continue up the tree + nsCOMPtr attr(do_QueryInterface(tmp)); + nsCOMPtr 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 |= (nsIDOMNode::DOCUMENT_POSITION_IS_CONTAINED | + nsIDOMNode::DOCUMENT_POSITION_FOLLOWING); + break; + } + } while (other); *aReturn = mask; return NS_OK; @@ -444,7 +456,7 @@ nsDocumentFragment::IsSameNode(nsIDOMNode* aOther, { PRBool sameNode = PR_FALSE; - if (this == aOther) { + if (NS_STATIC_CAST(nsIDOMNode*, this) == aOther) { sameNode = PR_TRUE; } diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index d8080ea1fe0..7fdb63421c0 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -246,27 +246,22 @@ nsNode3Tearoff::GetBaseURI(nsAString& aURI) } NS_IMETHODIMP -nsNode3Tearoff::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsNode3Tearoff::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_ENSURE_ARG_POINTER(aOther); - PRUint16 mask = nsIDOMNode::TREE_POSITION_DISCONNECTED; + NS_PRECONDITION(aReturn, "Must have an out parameter"); nsCOMPtr node(do_QueryInterface(mContent)); if (node == aOther) { - mask |= nsIDOMNode::TREE_POSITION_SAME_NODE; - nsCOMPtr doc; - mContent->GetDocument(*getter_AddRefs(doc)); - // Loose nodes without an owner document are not equivalent - // in tree position since they are not in any tree. - // Add the 'equivalent' flag only if we have an owner document. - if (doc) { - mask |= nsIDOMNode::TREE_POSITION_EQUIVALENT; - } - *aReturn = mask; + // If the two nodes being compared are the same node, + // then no flags are set on the return. + *aReturn = 0; return NS_OK; } + 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. @@ -275,22 +270,11 @@ nsNode3Tearoff::CompareTreePosition(nsIDOMNode* aOther, if (otherType == nsIDOMNode::ATTRIBUTE_NODE || otherType == nsIDOMNode::DOCUMENT_NODE || otherType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) { - PRUint16 otherMask = nsIDOMNode::TREE_POSITION_DISCONNECTED; + PRUint16 otherMask = 0; nsCOMPtr other(do_QueryInterface(aOther)); - other->CompareTreePosition(node, &otherMask); - if (otherMask & nsIDOMNode::TREE_POSITION_FOLLOWING) { - mask |= nsIDOMNode::TREE_POSITION_PRECEDING; - } else if (otherMask & nsIDOMNode::TREE_POSITION_PRECEDING) { - mask |= nsIDOMNode::TREE_POSITION_FOLLOWING; - } + other->CompareDocumentPosition(node, &otherMask); - if (otherMask & nsIDOMNode::TREE_POSITION_ANCESTOR) { - mask |= nsIDOMNode::TREE_POSITION_DESCENDANT; - } else if (otherMask & nsIDOMNode::TREE_POSITION_DESCENDANT) { - mask |= nsIDOMNode::TREE_POSITION_ANCESTOR; - } - - *aReturn = mask; + *aReturn = nsContentUtils::ReverseDocumentPosition(otherMask); return NS_OK; } @@ -298,86 +282,24 @@ nsNode3Tearoff::CompareTreePosition(nsIDOMNode* aOther, { PRUint16 nodeType = 0; node->GetNodeType(&nodeType); - 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), - "Invalid node type!"); + + 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), + "Invalid node type!"); + } } #endif - nsAutoVoidArray nodeAncestors; - - nsresult rv = - nsContentUtils::GetFirstDifferentAncestors(node, aOther, &nodeAncestors); - - if (NS_FAILED(rv)) { - // The nodes have no common ancestor. We're done. - *aReturn = mask; - return NS_OK; - } - - nsIDOMNode* commonAncestor = - NS_STATIC_CAST(nsIDOMNode*, nodeAncestors.ElementAt(0)); - - nsCOMPtr doc; - mContent->GetDocument(*getter_AddRefs(doc)); - - if (commonAncestor == node) { - mask |= nsIDOMNode::TREE_POSITION_DESCENDANT; - // Should nodes in a document fragment get following/preceding? - // Currently we assume they can't. - // XXXcaa - See bug 154166. - if (doc) { - mask |= nsIDOMNode::TREE_POSITION_FOLLOWING; - } - *aReturn = mask; - return NS_OK; - } - - if (commonAncestor == aOther) { - mask |= nsIDOMNode::TREE_POSITION_ANCESTOR; - // Should nodes in a document fragment get following/preceding? - // Currently we assume they can't. - // XXXcaa - See bug 154166. - if (doc) { - mask |= nsIDOMNode::TREE_POSITION_PRECEDING; - } - *aReturn = mask; - return NS_OK; - } - - if (commonAncestor && doc && nodeAncestors.Count() == 3) { - nsIDOMNode* nodeAncestor = - NS_STATIC_CAST(nsIDOMNode*, nodeAncestors.ElementAt(1)); - nsIDOMNode* otherAncestor = - NS_STATIC_CAST(nsIDOMNode*, nodeAncestors.ElementAt(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 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 childNode; - children->Item(i, getter_AddRefs(childNode)); - if (childNode == nodeAncestor) { - mask |= nsIDOMNode::TREE_POSITION_FOLLOWING; - break; - } - - if (childNode == otherAncestor) { - mask |= nsIDOMNode::TREE_POSITION_PRECEDING; - break; - } - } - } - } + mask |= nsContentUtils::ComparePositionWithAncestors(node, aOther); *aReturn = mask; return NS_OK; diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index b49c01fd039..769b5ed811f 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -1929,10 +1929,10 @@ nsHTMLDocument::GetBaseURI(nsAString &aURI) } NS_IMETHODIMP -nsHTMLDocument::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsHTMLDocument::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { - return nsDocument::CompareTreePosition(aOther, aReturn); + return nsDocument::CompareDocumentPosition(aOther, aReturn); } NS_IMETHODIMP diff --git a/mozilla/content/html/style/src/nsCSSLoader.cpp b/mozilla/content/html/style/src/nsCSSLoader.cpp index 8debfdbe078..410a8d2df26 100644 --- a/mozilla/content/html/style/src/nsCSSLoader.cpp +++ b/mozilla/content/html/style/src/nsCSSLoader.cpp @@ -1360,7 +1360,7 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet, * which the inserting requests come in, since all of these are * inserted during header data processing in the content sink * 3) Sheets with linking elements are ordered based on document order - * as determined by CompareTreePosition. + * as determined by CompareDocumentPosition. */ nsresult CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, @@ -1413,15 +1413,20 @@ CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, } // Have to compare - PRUint16 comparisonFlags = nsIDOMNode::TREE_POSITION_DISCONNECTED; - rv = linkingNode->CompareTreePosition(sheetOwner, &comparisonFlags); + PRUint16 comparisonFlags = 0; + rv = linkingNode->CompareDocumentPosition(sheetOwner, &comparisonFlags); // If we can't get the order right, just bail... NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(!(comparisonFlags & nsIDOMNode::TREE_POSITION_DISCONNECTED), + NS_ASSERTION(!(comparisonFlags & nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED), "Why are these elements in different documents?"); - NS_ASSERTION(!(comparisonFlags & nsIDOMNode::TREE_POSITION_SAME_NODE), - "Why do we still have our old sheet?"); - if (comparisonFlags & nsIDOMNode::TREE_POSITION_PRECEDING) { +#ifdef DEBUG + { + PRBool sameNode = PR_FALSE; + linkingNode->IsSameNode(sheetOwner, &sameNode); + NS_ASSERTION(!sameNode, "Why do we still have our old sheet?"); + } +#endif // DEBUG + if (comparisonFlags & nsIDOMNode::DOCUMENT_POSITION_PRECEDING) { // The current sheet comes before us, and it better be the first // such, because now we break break; diff --git a/mozilla/content/xul/content/src/nsXULAttributes.cpp b/mozilla/content/xul/content/src/nsXULAttributes.cpp index 70e095c707f..1941f27f351 100644 --- a/mozilla/content/xul/content/src/nsXULAttributes.cpp +++ b/mozilla/content/xul/content/src/nsXULAttributes.cpp @@ -400,8 +400,8 @@ nsXULAttribute::GetBaseURI(nsAString &aURI) } NS_IMETHODIMP -nsXULAttribute::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsXULAttribute::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_NOTYETIMPLEMENTED("write me"); return NS_ERROR_NOT_IMPLEMENTED; diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index 899d208c459..746b81405fe 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -4365,8 +4365,8 @@ nsXULDocument::GetBaseURI(nsAString &aURI) } NS_IMETHODIMP -nsXULDocument::CompareTreePosition(nsIDOMNode* aOther, - PRUint16* aReturn) +nsXULDocument::CompareDocumentPosition(nsIDOMNode* aOther, + PRUint16* aReturn) { NS_NOTYETIMPLEMENTED("write me"); return NS_ERROR_NOT_IMPLEMENTED; diff --git a/mozilla/dom/public/idl/core/nsIDOM3Node.idl b/mozilla/dom/public/idl/core/nsIDOM3Node.idl index cb6f804f3c9..889efd7fbb6 100644 --- a/mozilla/dom/public/idl/core/nsIDOM3Node.idl +++ b/mozilla/dom/public/idl/core/nsIDOM3Node.idl @@ -46,14 +46,7 @@ interface nsIDOM3Node : nsISupports // Introduced in DOM Level 3: readonly attribute DOMString baseURI; // Introduced in DOM Level 3: - // XXXcaa compareTreePosition existed in an old DOM3 Core WD: - // - // It has been renamed in the newest WD to compareDocumentPosition: - // - // Disable compareTreePosition from script only for now since we - // rely on it in C++. When we implement this as per the latest - // spec, re-enable it for scripts. - [noscript] unsigned short compareTreePosition(in nsIDOMNode other); + unsigned short compareDocumentPosition(in nsIDOMNode other); // Introduced in DOM Level 3: boolean isSameNode(in nsIDOMNode other); // Introduced in DOM Level 3: diff --git a/mozilla/dom/public/idl/core/nsIDOMNode.idl b/mozilla/dom/public/idl/core/nsIDOMNode.idl index 605e7e24dc3..dba18d7a7f9 100644 --- a/mozilla/dom/public/idl/core/nsIDOMNode.idl +++ b/mozilla/dom/public/idl/core/nsIDOMNode.idl @@ -110,24 +110,13 @@ interface nsIDOMNode : nsISupports // Introduced in DOM Level 2: boolean hasAttributes(); -%{C++ // Introduced in DOM Level 3: - // XXXcaa the constants existed in an old DOM3 Core WD: - // - // They have been renamed in the newest WD: - // - // Disable these from script only for now since we rely on them - // in C++. When we implement them as per the latest spec, - // rename and re-enable them. - enum { - TREE_POSITION_PRECEDING = 0x01, - TREE_POSITION_FOLLOWING = 0x02, - TREE_POSITION_ANCESTOR = 0x04, - TREE_POSITION_DESCENDANT = 0x08, - TREE_POSITION_EQUIVALENT = 0x10, - TREE_POSITION_SAME_NODE = 0x20, - TREE_POSITION_DISCONNECTED = 0x00 - }; -%} - + // DocumentPosition + // XXX actual constant values await w3c feedback + const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x20; + const unsigned short DOCUMENT_POSITION_PRECEDING = 0x01; + const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x02; + const unsigned short DOCUMENT_POSITION_CONTAINS = 0x04; + const unsigned short DOCUMENT_POSITION_IS_CONTAINED = 0x08; + const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x10; }; diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index bcc6ce37b99..77cc793fc0a 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -1357,11 +1357,13 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(CDATASection, nsIDOMCDATASection) DOM_CLASSINFO_MAP_ENTRY(nsIDOMCDATASection) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) + DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(ProcessingInstruction, nsIDOMProcessingInstruction) DOM_CLASSINFO_MAP_ENTRY(nsIDOMProcessingInstruction) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) + DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(Entity, nsIDOMEntity) @@ -1904,6 +1906,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMProcessingInstruction) DOM_CLASSINFO_MAP_ENTRY(nsIDOMLinkStyle) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) + DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node) DOM_CLASSINFO_MAP_END #ifdef MOZ_SVG diff --git a/mozilla/layout/style/nsCSSLoader.cpp b/mozilla/layout/style/nsCSSLoader.cpp index 8debfdbe078..410a8d2df26 100644 --- a/mozilla/layout/style/nsCSSLoader.cpp +++ b/mozilla/layout/style/nsCSSLoader.cpp @@ -1360,7 +1360,7 @@ CSSLoaderImpl::PrepareSheet(nsICSSStyleSheet* aSheet, * which the inserting requests come in, since all of these are * inserted during header data processing in the content sink * 3) Sheets with linking elements are ordered based on document order - * as determined by CompareTreePosition. + * as determined by CompareDocumentPosition. */ nsresult CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, @@ -1413,15 +1413,20 @@ CSSLoaderImpl::InsertSheetInDoc(nsICSSStyleSheet* aSheet, } // Have to compare - PRUint16 comparisonFlags = nsIDOMNode::TREE_POSITION_DISCONNECTED; - rv = linkingNode->CompareTreePosition(sheetOwner, &comparisonFlags); + PRUint16 comparisonFlags = 0; + rv = linkingNode->CompareDocumentPosition(sheetOwner, &comparisonFlags); // If we can't get the order right, just bail... NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(!(comparisonFlags & nsIDOMNode::TREE_POSITION_DISCONNECTED), + NS_ASSERTION(!(comparisonFlags & nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED), "Why are these elements in different documents?"); - NS_ASSERTION(!(comparisonFlags & nsIDOMNode::TREE_POSITION_SAME_NODE), - "Why do we still have our old sheet?"); - if (comparisonFlags & nsIDOMNode::TREE_POSITION_PRECEDING) { +#ifdef DEBUG + { + PRBool sameNode = PR_FALSE; + linkingNode->IsSameNode(sheetOwner, &sameNode); + NS_ASSERTION(!sameNode, "Why do we still have our old sheet?"); + } +#endif // DEBUG + if (comparisonFlags & nsIDOMNode::DOCUMENT_POSITION_PRECEDING) { // The current sheet comes before us, and it better be the first // such, because now we break break;