diff --git a/content/base/src/nsContentList.cpp b/content/base/src/nsContentList.cpp index c9536caff73b..b82e0e4893ed 100644 --- a/content/base/src/nsContentList.cpp +++ b/content/base/src/nsContentList.cpp @@ -686,6 +686,10 @@ nsContentList::Match(nsIContent *aContent) return (mMatchAll || ni->QualifiedNameEquals(mMatchAtom)); } + if (mMatchNameSpaceId == kNameSpaceID_Wildcard) { + return (mMatchAll || ni->Equals(mMatchAtom)); + } + return ((mMatchAll && ni->NamespaceEquals(mMatchNameSpaceId)) || ni->Equals(mMatchAtom, mMatchNameSpaceId)); } diff --git a/content/base/src/nsContentList.h b/content/base/src/nsContentList.h index 9ad6b79fc6c9..059912794707 100644 --- a/content/base/src/nsContentList.h +++ b/content/base/src/nsContentList.h @@ -53,6 +53,10 @@ #include "nsIAtom.h" #include "nsINameSpaceManager.h" +// Magic namespace id that means "match all namespaces". This is +// negative so it won't collide with actual namespace constants. +#define kNameSpaceID_Wildcard PR_INT32_MIN + // This is a callback function type that can be used to implement an // arbitrary matching algorithm. aContent is the content that may // match the list, while aNamespaceID, aAtom, and aData are whatever @@ -163,11 +167,16 @@ public: /** * @param aRootNode The node under which to limit our search. - * @param aMatchAtom an atom whose meaning depends on aMatchNameSpaceId - * @param aMatchNameSpaceId if kNameSpaceID_Unknown then aMatchAtom is the - * tagName to match. Otherwise we match nodes with - * aMatchNameSpaceId and a localName equal to - * aMatchAtom + * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId. + * The special value "*" always matches whatever aMatchAtom + * is matched against. + * @param aMatchNameSpaceId If kNameSpaceID_Unknown, then aMatchAtom is the + * tagName to match. + * If kNameSpaceID_Wildcard, then aMatchAtom is the + * localName to match. + * Otherwise we match nodes whose namespace is + * aMatchNameSpaceId and localName matches + * aMatchAtom. * @param aDeep If false, then look only at children of the root, nothing * deeper. If true, then look at the whole subtree rooted at * our root. diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index dca024110052..7e2fd07ffc84 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2739,19 +2739,15 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, nsIDOMNodeList** aReturn) { - PRInt32 nameSpaceId = kNameSpaceID_Unknown; + PRInt32 nameSpaceId = kNameSpaceID_Wildcard; nsContentList *list = nsnull; if (!aNamespaceURI.EqualsLiteral("*")) { - nameSpaceId = - nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); - - if (nameSpaceId == kNameSpaceID_Unknown) { - // Unknown namespace means no matches, we create an empty list... - list = NS_GetContentList(this, nsnull, kNameSpaceID_None).get(); - NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - } + nsresult rv = + nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, + nameSpaceId); + NS_ENSURE_SUCCESS(rv, rv); } if (!list) { diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 3688dd2e3130..a1be153d4efd 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1674,21 +1674,15 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, nsIDOMNodeList** aReturn) { - PRInt32 nameSpaceId = kNameSpaceID_Unknown; + PRInt32 nameSpaceId = kNameSpaceID_Wildcard; nsContentList *list = nsnull; - nsIDocument* document = GetCurrentDoc(); if (!aNamespaceURI.EqualsLiteral("*")) { - nameSpaceId = - nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); - - if (nameSpaceId == kNameSpaceID_Unknown) { - // Unknown namespace means no matches, we create an empty list... - list = NS_GetContentList(document, nsnull, - kNameSpaceID_None).get(); - NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - } + nsresult rv = + nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, + nameSpaceId); + NS_ENSURE_SUCCESS(rv, rv); } if (!list) { diff --git a/content/base/src/nsNameSpaceManager.cpp b/content/base/src/nsNameSpaceManager.cpp index e7947f350206..bb47cb4f813b 100644 --- a/content/base/src/nsNameSpaceManager.cpp +++ b/content/base/src/nsNameSpaceManager.cpp @@ -196,12 +196,16 @@ NameSpaceManagerImpl::RegisterNameSpace(const nsAString& aURI, } } + NS_POSTCONDITION(aNameSpaceID >= -1, "Bogus namespace ID"); + return rv; } nsresult NameSpaceManagerImpl::GetNameSpaceURI(PRInt32 aNameSpaceID, nsAString& aURI) { + NS_PRECONDITION(aNameSpaceID >= 0, "Bogus namespace ID"); + PRInt32 index = aNameSpaceID - 1; // id is index + 1 if (index < 0 || index >= mURIArray.Count()) { aURI.Truncate(); @@ -223,8 +227,12 @@ NameSpaceManagerImpl::GetNameSpaceID(const nsAString& aURI) PRInt32 nameSpaceID; - return mURIToIDTable.Get(&aURI, &nameSpaceID) ? nameSpaceID : - kNameSpaceID_Unknown; + if (mURIToIDTable.Get(&aURI, &nameSpaceID)) { + NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID"); + return nameSpaceID; + } + + return kNameSpaceID_Unknown; } nsresult @@ -285,6 +293,11 @@ NameSpaceManagerImpl::HasElementCreator(PRInt32 aNameSpaceID) nsresult NameSpaceManagerImpl::AddNameSpace(const nsAString& aURI, const PRInt32 aNameSpaceID) { + if (aNameSpaceID < 0) { + // We've wrapped... Can't do anything else here; just bail. + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ASSERTION(aNameSpaceID - 1 == mURIArray.Count(), "BAD! AddNameSpace not called in right order!"); diff --git a/content/test/unit/test_nodelist.js b/content/test/unit/test_nodelist.js index 01da0300017d..1a40c494d9b3 100644 --- a/content/test/unit/test_nodelist.js +++ b/content/test/unit/test_nodelist.js @@ -12,6 +12,7 @@ function run_test() test_getElementsByAttribute(); // What else should we test? + // XXXbz we need more tests here to test liveness! } @@ -86,13 +87,9 @@ function test_getElementsByTagNameNS() do_check_eq(doc.getElementById("test2") .getElementsByTagNameNS("", "test").length, 1); - /* XXXbz this test is currently failing because getElementsByTagNameNS("*", - "tagname" is actually broken. See bug 343307. - do_check_eq(doc.getElementById("test2") .getElementsByTagNameNS("*", "test").length, 7); - */ // Check that the first element of getElementsByTagNameNS on the document is // the right thing. @@ -102,20 +99,15 @@ function test_getElementsByTagNameNS() // Check that we get the right things in the right order - /* XXXbz this test is currently failing because getElementsByTagNameNS("*", - "tagname" is actually broken. See bug 343307. - var numTests = doc.getElementsByTagNameNS("*", "test").length; do_check_eq(numTests, 14); for (var i = 1; i <= numTests; ++i) { do_check_true(doc.getElementById("test" + i) instanceof nsIDOMElement); do_check_eq(doc.getElementById("test" + i), - doc.getElementsByTagName("test").item(i-1)); + doc.getElementsByTagNameNS("*", "test").item(i-1)); } - */ - // Check general proper functioning of having a non-wildcard namespace. var test2 = doc.getElementById("test2"); do_check_eq(doc.getElementsByTagNameNS("", "test").length, @@ -141,29 +133,37 @@ function test_getElementsByTagNameNS() do_check_eq(doc.getElementsByTagNameNS(null, "foo:test").length, 0); do_check_eq(doc.getElementsByTagNameNS("foo", "foo:test").length, 0); do_check_eq(doc.getElementsByTagNameNS("bar", "foo:test").length, 0); - /* XXXbz this test is currently failing because getElementsByTagNameNS("*", - "tagname" is actually broken. See bug 343307. do_check_eq(doc.getElementsByTagNameNS("*", "foo:test").length, 0); - */ do_check_true(doc.getElementsByTagNameNS(null, "foo2:test") instanceof nsIDOMNodeList); do_check_eq(doc.getElementsByTagNameNS(null, "foo2:test").length, 0); do_check_eq(doc.getElementsByTagNameNS("foo2", "foo2:test").length, 0); do_check_eq(doc.getElementsByTagNameNS("bar", "foo2:test").length, 0); - /* XXXbz this test is currently failing because getElementsByTagNameNS("*", - "tagname" is actually broken. See bug 343307. do_check_eq(doc.getElementsByTagNameNS("*", "foo2:test").length, 0); - */ do_check_true(doc.getElementsByTagNameNS(null, "bar:test") instanceof nsIDOMNodeList); do_check_eq(doc.getElementsByTagNameNS(null, "bar:test").length, 0); do_check_eq(doc.getElementsByTagNameNS("bar", "bar:test").length, 0); - /* XXXbz this test is currently failing because getElementsByTagNameNS("*", - "tagname" is actually broken. See bug 343307. do_check_eq(doc.getElementsByTagNameNS("*", "bar:test").length, 0); - */ + + // Check that previously-unknown namespaces are handled right. Note that we + // can just hardcode the strings, since we're running only once in XPCshell. + // If someone wants to run these in a browser, some use of Math.random() may + // be in order. + list1 = doc.getElementsByTagNameNS("random-bogus-namespace", "foo"); + list2 = doc.documentElement.getElementsByTagNameNS("random-bogus-namespace2", + "foo"); + do_check_neq(list1, list2); + do_check_eq(list1.length, 0); + do_check_eq(list2.length, 0); + var newNode = doc.createElementNS("random-bogus-namespace", "foo"); + doc.documentElement.appendChild(newNode); + var newNode = doc.createElementNS("random-bogus-namespace2", "foo"); + doc.documentElement.appendChild(newNode); + do_check_eq(list1.length, 1); + do_check_eq(list2.length, 1); } function test_getElementsByAttribute()