Bug 1165851 part 1. Back out bug 1060938 and bug 1075702 pending spec changes because they are implementing a spec that's not web compatible. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 16 Jun 2015 12:17:57 -0400
changeset 249108 03682dcd82bbb2fa45b8592d863343b2cd19f596
parent 249107 67be1324fc240c1a16f2da9743d77f689913dce5
child 249109 9d31854cecef301596a31b3ee34840719c23f9ea
push id61146
push userbzbarsky@mozilla.com
push dateTue, 16 Jun 2015 16:18:31 +0000
treeherdermozilla-inbound@5003110c53bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1165851, 1060938, 1075702
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1165851 part 1. Back out bug 1060938 and bug 1075702 pending spec changes because they are implementing a spec that's not web compatible. r=smaug
dom/base/Attr.cpp
dom/base/Element.cpp
dom/base/nsDOMAttributeMap.cpp
dom/base/nsDOMAttributeMap.h
dom/base/test/mochitest.ini
dom/base/test/test_bug1060938.html
dom/base/test/test_bug1075702.html
dom/base/test/test_bug469304.html
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -179,17 +179,17 @@ Attr::GetNameAtom(nsIContent* aContent)
   return nameAtom.forget();
 }
 
 NS_IMETHODIMP
 Attr::GetValue(nsAString& aValue)
 {
   Element* element = GetElement();
   if (element) {
-    nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
+    nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element);
     element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
   }
   else {
     aValue = mValue;
   }
 
   return NS_OK;
 }
@@ -198,17 +198,17 @@ void
 Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
 {
   Element* element = GetElement();
   if (!element) {
     mValue = aValue;
     return;
   }
 
-  nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom();
+  nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element);
   aRv = element->SetAttr(mNodeInfo->NamespaceID(),
                          nameAtom,
                          mNodeInfo->GetPrefixAtom(),
                          aValue,
                          true);
 }
 
 NS_IMETHODIMP
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1230,19 +1230,17 @@ Element::RemoveAttributeNode(Attr& aAttr
 {
   Element *elem = aAttribute.GetElement();
   if (elem != this) {
     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return nullptr;
   }
 
   OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
-  nsAutoString nameSpaceURI;
-  aAttribute.NodeInfo()->GetNamespaceURI(nameSpaceURI);
-  return Attributes()->RemoveNamedItemNS(nameSpaceURI, aAttribute.NodeInfo()->LocalName(), aError);
+  return Attributes()->RemoveNamedItem(aAttribute.NodeName(), aError);
 }
 
 void
 Element::GetAttributeNS(const nsAString& aNamespaceURI,
                         const nsAString& aLocalName,
                         nsAString& aReturn)
 {
   int32_t nsid =
--- a/dom/base/nsDOMAttributeMap.cpp
+++ b/dom/base/nsDOMAttributeMap.cpp
@@ -295,86 +295,72 @@ nsDOMAttributeMap::SetNamedItemInternal(
     if (aError.Failed()) {
       return nullptr;
     }
 
     NS_ASSERTION(adoptedNode == &aAttr, "Uh, adopt node changed nodes?");
   }
 
   // Get nodeinfo and preexisting attribute (if it exists)
-  nsRefPtr<NodeInfo> oldNi;
-
-  if (!aWithNS) {
-    nsAutoString name;
-    aAttr.GetName(name);
-    oldNi = mContent->GetExistingAttrNameFromQName(name);
-  }
-  else {
-    uint32_t i, count = mContent->GetAttrCount();
-    for (i = 0; i < count; ++i) {
-      const nsAttrName* name = mContent->GetAttrNameAt(i);
-      int32_t attrNS = name->NamespaceID();
-      nsIAtom* nameAtom = name->LocalName();
-
-      // we're purposefully ignoring the prefix.
-      if (aAttr.NodeInfo()->Equals(nameAtom, attrNS)) {
-        oldNi = mContent->NodeInfo()->NodeInfoManager()->
-          GetNodeInfo(nameAtom, name->GetPrefix(), aAttr.NodeInfo()->NamespaceID(),
-                      nsIDOMNode::ATTRIBUTE_NODE);
-        break;
-      }
-    }
-  }
+  nsAutoString name;
+  nsRefPtr<mozilla::dom::NodeInfo> ni;
 
   nsRefPtr<Attr> attr;
+  // SetNamedItemNS()
+  if (aWithNS) {
+    // Return existing attribute, if present
+    ni = aAttr.NodeInfo();
 
-  if (oldNi) {
-    nsRefPtr<Attr> oldAttr = GetAttribute(oldNi, true);
+    if (mContent->HasAttr(ni->NamespaceID(), ni->NameAtom())) {
+      attr = RemoveAttribute(ni);
+    }
+  } else { // SetNamedItem()
+    aAttr.GetName(name);
 
-    if (oldAttr == &aAttr) {
-      return oldAttr.forget();
+    // get node-info of old attribute
+    ni = mContent->GetExistingAttrNameFromQName(name);
+    if (ni) {
+      attr = RemoveAttribute(ni);
     }
+    else {
+      if (mContent->IsInHTMLDocument() &&
+          mContent->IsHTMLElement()) {
+        nsContentUtils::ASCIIToLower(name);
+      }
 
-    if (oldAttr) {
-      attr = RemoveNamedItem(oldNi, aError);
-      NS_ASSERTION(attr->NodeInfo()->NameAndNamespaceEquals(oldNi),
-        "RemoveNamedItem() called, attr->NodeInfo() should be equal to oldNi!");
+      rv = mContent->NodeInfo()->NodeInfoManager()->
+        GetNodeInfo(name, nullptr, kNameSpaceID_None,
+                    nsIDOMNode::ATTRIBUTE_NODE, getter_AddRefs(ni));
+      if (NS_FAILED(rv)) {
+        aError.Throw(rv);
+        return nullptr;
+      }
+      // value is already empty
     }
   }
 
   nsAutoString value;
   aAttr.GetValue(value);
 
-  nsRefPtr<NodeInfo> ni = aAttr.NodeInfo();
-
   // Add the new attribute to the attribute map before updating
   // its value in the element. @see bug 364413.
   nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom());
   mAttributeCache.Put(attrkey, &aAttr);
   aAttr.SetMap(this);
 
   rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(),
                          ni->GetPrefixAtom(), value, true);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     DropAttribute(ni->NamespaceID(), ni->NameAtom());
   }
 
   return attr.forget();
 }
 
-already_AddRefed<Attr>
-nsDOMAttributeMap::RemoveNamedItem(NodeInfo* aNodeInfo, ErrorResult& aError)
-{
-  nsRefPtr<Attr> attribute = GetAttribute(aNodeInfo, true);
-  // This removes the attribute node from the attribute map.
-  aError = mContent->UnsetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), true);
-  return attribute.forget();
-}
-
 NS_IMETHODIMP
 nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName,
                                    nsIDOMAttr** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
 
   ErrorResult rv;
   *aReturn = RemoveNamedItem(aName, rv).take();
@@ -390,17 +376,21 @@ nsDOMAttributeMap::RemoveNamedItem(const
   }
 
   nsRefPtr<mozilla::dom::NodeInfo> ni = mContent->GetExistingAttrNameFromQName(aName);
   if (!ni) {
     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return nullptr;
   }
 
-  return RemoveNamedItem(ni, aError);
+  nsRefPtr<Attr> attribute = GetAttribute(ni, true);
+
+  // This removes the attribute node from the attribute map.
+  aError = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), true);
+  return attribute.forget();
 }
 
 
 Attr*
 nsDOMAttributeMap::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = false;
   NS_ENSURE_TRUE(mContent, nullptr);
@@ -488,17 +478,16 @@ nsDOMAttributeMap::GetAttrNodeInfo(const
   }
 
   uint32_t i, count = mContent->GetAttrCount();
   for (i = 0; i < count; ++i) {
     const nsAttrName* name = mContent->GetAttrNameAt(i);
     int32_t attrNS = name->NamespaceID();
     nsIAtom* nameAtom = name->LocalName();
 
-    // we're purposefully ignoring the prefix.
     if (nameSpaceID == attrNS &&
         nameAtom->Equals(aLocalName)) {
       nsRefPtr<mozilla::dom::NodeInfo> ni;
       ni = mContent->NodeInfo()->NodeInfoManager()->
         GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID,
                     nsIDOMNode::ATTRIBUTE_NODE);
 
       return ni.forget();
@@ -525,17 +514,21 @@ nsDOMAttributeMap::RemoveNamedItemNS(con
                                      ErrorResult& aError)
 {
   nsRefPtr<mozilla::dom::NodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName);
   if (!ni) {
     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return nullptr;
   }
 
-  return RemoveNamedItem(ni, aError);
+  nsRefPtr<Attr> attr = RemoveAttribute(ni);
+  mozilla::dom::NodeInfo* attrNi = attr->NodeInfo();
+  mContent->UnsetAttr(attrNi->NamespaceID(), attrNi->NameAtom(), true);
+
+  return attr.forget();
 }
 
 uint32_t
 nsDOMAttributeMap::Count() const
 {
   return mAttributeCache.Count();
 }
 
--- a/dom/base/nsDOMAttributeMap.h
+++ b/dom/base/nsDOMAttributeMap.h
@@ -147,18 +147,16 @@ public:
   Attr* NamedGetter(const nsAString& aAttrName, bool& aFound);
   bool NameIsEnumerable(const nsAString& aName);
   already_AddRefed<Attr>
   SetNamedItem(Attr& aAttr, ErrorResult& aError)
   {
     return SetNamedItemInternal(aAttr, false, aError);
   }
   already_AddRefed<Attr>
-  RemoveNamedItem(mozilla::dom::NodeInfo* aNodeInfo, ErrorResult& aError);
-  already_AddRefed<Attr>
   RemoveNamedItem(const nsAString& aName, ErrorResult& aError);
  
   Attr* Item(uint32_t aIndex);
   Attr* IndexedGetter(uint32_t aIndex, bool& aFound);
   uint32_t Length() const;
 
   Attr*
   GetNamedItemNS(const nsAString& aNamespaceURI,
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -255,17 +255,16 @@ skip-if = buildapp == 'mulet'
 [test_bug913761.html]
 [test_bug976673.html]
 [test_bug978522.html]
 [test_bug979109.html]
 [test_bug989665.html]
 [test_bug999456.html]
 [test_bug1022229.html]
 [test_bug1043106.html]
-[test_bug1060938.html]
 [test_bug1064481.html]
 [test_clearTimeoutIntervalNoArg.html]
 [test_consoleEmptyStack.html]
 [test_constructor-assignment.html]
 [test_constructor.html]
 [test_dialogArguments.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_document.all_unqualified.html]
@@ -661,17 +660,16 @@ skip-if = buildapp == 'mulet' || buildap
 [test_bug895974.html]
 [test_bug902847.html]
 [test_bug907892.html]
 [test_bug922681.html]
 [test_bug927196.html]
 [test_bug982153.html]
 [test_bug1057176.html]
 [test_bug1070015.html]
-[test_bug1075702.html]
 [test_bug1101364.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
 [test_bug1163743.html]
 support-files = referrerHelper.js
 [test_bug1165501.html]
 support-files = referrerHelper.js
 [test_caretPositionFromPoint.html]
 [test_classList.html]
deleted file mode 100644
--- a/dom/base/test/test_bug1060938.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1060938
--->
-  <head>
-    <meta charset="utf-8">
-    <title> Test for Bug 1060938 </title>
-    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> </script>
-    <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> </script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  </head>
-  <body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1060938"> Mozilla Bug 1060938 </a>
-  <p id="display"></p>
-
-  <pre id="test">
-  <script type="application/javascript">
-
-    /** Test for Bug 1060938 **/
-    // test: Element.removeAttributeNode()
-
-    parent = document.getElementsByTagName("p")[0];
-    parent.setAttributeNS("www.test1.com", "ID", "Test1");
-    parent.setAttributeNS("www.test2.com", "Class", "Test2");
-    parent.setAttribute("id", "www.test3.com");
-    parent.className = "www.test4.com";
-
-    allAttributes = parent.attributes;
-
-    function removeAttr(iter){
-      var removed_attribute = allAttributes[0];
-      is(removed_attribute, parent.removeAttributeNode(removed_attribute),
-          "(" + iter + ")" + " Returned attribute and remove attribute should be same.");
-    }
-
-    removeAttr(1);
-    removeAttr(2);
-    removeAttr(3);
-    removeAttr(4);
-
-  </script>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/base/test/test_bug1075702.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1075702
--->
-<head>
-  <meta charset="utf-8">
-  <title> Test for Bug 1075702 </title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> </script>
-  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"> </script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1075702"> Mozilla Bug 1075702 </a>
-<p id="display"></p>
-
-<pre id="test">
-<script type="application/javascript">
-
-  /** Test for Bug 1075702 **/
-  // test: Element.removeAttributeNode()
-
-  var a1 = document.createAttribute("aa");
-  a1.nodeValue = "lowercase";
-
-  var a2 = document.createAttribute("AA");
-  a2.nodeValue = "UPPERCASE";
-
-  document.documentElement.setAttributeNode(a1);
-  document.documentElement.setAttributeNode(a2);
-
-  is(document.documentElement.getAttributeNS("", "aa"), null, "Should be NULL!");
-  is(document.documentElement.getAttributeNS("", "AA"), "UPPERCASE", "Should be UPPERCASE!");
-
-  var removedNodeAccordingToEvent;
-
-  function mutationHandler(aEvent) {
-    removedNodeAccordingToEvent = aEvent.relatedNode;
-  }
-
-  var test1 = document.createElement("div");
-  test1.setAttribute("x", "y");
-  removedNodeAccordingToEvent = null;
-
-  function testremoveNamedItemNS() {
-    test1.addEventListener("DOMAttrModified", mutationHandler, true);
-    var removedNodeAccordingToRemoveNamedItemNS = test1.attributes.removeNamedItemNS(null, "x");
-    test1.removeEventListener("DOMAttrModified", mutationHandler, true);
-    is(removedNodeAccordingToEvent, removedNodeAccordingToRemoveNamedItemNS, "Node removed according to event is not same as node removed by removeNamedItemNS.");
-  }
-
-  testremoveNamedItemNS();
-
-  var test2 = document.createElement("div");
-  test2.setAttribute("x", "y");
-  removedNodeAccordingToEvent = null;
-
-  function testremoveNamedItem() {
-    test2.addEventListener("DOMAttrModified", mutationHandler, true);
-    var removedNodeAccordingToRemoveNamedItem = test2.attributes.removeNamedItem("x");
-    test2.removeEventListener("DOMAttrModified", mutationHandler, true);
-    is(removedNodeAccordingToEvent, removedNodeAccordingToRemoveNamedItem, "Node removed according to event is not same as node removed by removeNamedItem.");
-  }
-
-  testremoveNamedItem();
-
-</script>
-</body>
-</html>
--- a/dom/base/test/test_bug469304.html
+++ b/dom/base/test/test_bug469304.html
@@ -22,47 +22,47 @@ https://bugzilla.mozilla.org/show_bug.cg
 function testGetAttribute() {
   var a1 = document.createAttribute("aa");
   a1.nodeValue = "lowercase";
   var a2 = document.createAttribute("AA");
   a2.nodeValue = "UPPERCASE";
   document.body.setAttributeNode(a1);
   document.body.setAttributeNode(a2);
   var log = document.getElementById("log");
-  is(document.body.getAttribute('aa'), null, "Attribute has the localName AA and not aa.");
-  is(document.body.getAttribute('AA'), null, "Attribute has the localName AA and not aa.");
-  is(document.body.getAttributeNS("", "aa"), null, "Attribute should have localName AA.");
-  is(document.body.getAttributeNS("", "AA"), "UPPERCASE", "Attribute should have value UPPERCASE!");
+  is(document.body.getAttribute('aa'), "UPPERCASE", "Wrong value (1)");
+  is(document.body.getAttribute('AA'), "UPPERCASE", "Wrong value (2)");
 
   var s = "";
   for (var i = 0; i < document.body.attributes.length; ++i) {
     s += document.body.attributes[i].nodeName + "=" +
          document.body.attributes[i].nodeValue;
   }
   is(s, "AA=UPPERCASE", "Wrong attribute!");
 
   is(document.body.getAttributeNode("aa"), document.body.getAttributeNode("AA"),
      "Wrong node!");
 
-  document.body.getAttributeNodeNS("", "AA").nodeValue = "FOO";
-  is(document.body.getAttributeNS("", "AA"), "FOO", "Wrong value!");
+  document.body.getAttributeNode("AA").nodeValue = "FOO";
+  is(document.body.getAttribute("AA"), "FOO", "Wrong value!");
 
-  document.body.removeAttributeNode(document.body.getAttributeNodeNS("", "AA"));
+  document.body.removeAttributeNode(document.body.getAttributeNode("AA"));
+  ok(!document.body.hasAttribute("AA"), "Should not have attribute!");
   ok(!document.body.getAttributeNode("AA"), "Should not have attribute node!");
+  ok(!document.body.hasAttribute("aa"), "Should not have attribute!");
   ok(!document.body.getAttributeNode("aa"), "Should not have attribute node!");
 
   is(a2.nodeValue, "FOO", "Wrong value!");
   a2.nodeValue = "UPPERCASE";
   is(a2.nodeValue, "UPPERCASE", "Wrong value!");
 
   document.body.setAttributeNode(a2);
-  is(document.body.getAttributeNS("", "AA"), "UPPERCASE", "Wrong value!");
-  ok(document.body.getAttributeNodeNS("", "AA"), "Should have attribute node!");
-  is(document.body.getAttributeNS("", "aa"), null, "No attribute has the localName aa.");
-  ok(!document.body.getAttributeNodeNS("", "aa"), "Should not have attribute node!");
+  is(document.body.getAttribute("AA"), "UPPERCASE", "wrong value!");
+  ok(document.body.getAttributeNode("AA"), "Should have attribute node!");
+  is(document.body.getAttribute("aa"), "UPPERCASE", "wrong value!");
+  ok(document.body.getAttributeNode("aa"), "Should have attribute node!");
 }
 testGetAttribute();
 
 // A bit modified testcases from WebKit.
 function testGetAttributeCaseInsensitive() {
   var div = document.createElement('div');
   div.setAttribute("mixedCaseAttrib", "x");
   // Do original case lookup, and lowercase lookup.
@@ -70,17 +70,17 @@ function testGetAttributeCaseInsensitive
 }
 is(testGetAttributeCaseInsensitive(), "x", "(1)");
 
 function testGetAttributeNodeMixedCase() {
   var div = document.createElement('div');
   var a = div.ownerDocument.createAttribute("mixedCaseAttrib");
   a.nodeValue = "x";
   div.setAttributeNode(a);
-  return div.getAttributeNS("", "mixedCaseAttrib");
+  return div.getAttribute("mixedCaseAttrib");
 }
 is(testGetAttributeNodeMixedCase(), "x", "(2)");
 
 function testGetAttributeNodeLowerCase(div) {
   var div = document.createElement('div');
   var a = div.ownerDocument.createAttribute("lowercaseattrib");
   a.nodeValue = "x";
   div.setAttributeNode(a);
@@ -109,37 +109,37 @@ function testAttribNodeNamePreservesCase
 }
 is(testAttribNodeNamePreservesCase(), "A,A", "(5)");
 
 function testAttribNodeNamePreservesCaseGetNode() {
   var body = document.body;
   var a = body.ownerDocument.createAttribute("A");
   a.nodeValue = "x";
   body.setAttributeNode(a);
-  a = document.body.getAttributeNodeNS("", "A");
+  a = document.body.getAttributeNode("A");
   if (!a)
       return "FAIL";
   var result = [ a.name, a.nodeName ];
   return result.join(",");
 }
 is(testAttribNodeNamePreservesCaseGetNode(), "A,A", "(6)");
 
 function testAttribNodeNamePreservesCaseGetNode2() {
   var body = document.body;
   var a = body.ownerDocument.createAttribute("B");
   a.nodeValue = "x";
   body.setAttributeNode(a);
-  a = document.body.getAttributeNodeNS("", "B");
+  a = document.body.getAttributeNode("B");
   if (!a)
       return "FAIL";
   // Now create node second time
   a = body.ownerDocument.createAttribute("B");
   a.nodeValue = "x";
   body.setAttributeNode(a);
-  a = document.body.getAttributeNodeNS("", "B");
+  a = document.body.getAttributeNode("B");
   var result = [ a.name, a.nodeName ];
   return result.join(",");
 }
 is(testAttribNodeNamePreservesCaseGetNode2(), "B,B", "(7)");
 
 function testAttribNodeNameGetMutate() {
   var body = document.body;
   var a = body.ownerDocument.createAttribute("c");
@@ -153,19 +153,19 @@ function testAttribNodeNameGetMutate() {
 is(testAttribNodeNameGetMutate(), "1", "(8)");
 
 var node = document.createElement("div");
 var attrib = document.createAttribute("myAttrib");
 attrib.nodeValue = "XXX";
 node.setAttributeNode(attrib);
 // Note, this is different to what WebKit does
 is((new XMLSerializer).serializeToString(node),
-   "<div xmlns=\"http://www.w3.org/1999/xhtml\" myAttrib=\"XXX\"></div>", "(9)");
-is(node.getAttributeNodeNS("", "myAttrib").name, "myAttrib", "(10)");
-is(node.getAttributeNodeNS("", "myattrib"), null, "(11)");
+   "<div xmlns=\"http://www.w3.org/1999/xhtml\" myattrib=\"XXX\"></div>", "(9)");
+is(node.getAttributeNode('myAttrib').name, "myAttrib", "(10)");
+is(node.getAttributeNode('myattrib').name, "myAttrib", "(11)");
 is(attrib.name, "myAttrib", "(12)");
 
 var o = document.createElement("div");
 o.setAttribute("myAttrib","htmlattr");
 o.setAttributeNS("","myAttrib","123");
 is(o.getAttributeNodeNS("","myAttrib").nodeName, "myAttrib", "nodeName should be case-sensitive.");
 is(o.getAttributeNode("myAttrib").nodeName, "myattrib", "nodeName shouldn't be case-sensitive.");
 is(o.getAttributeNodeNS("","myAttrib").value, "123", "Should have got the case-sensitive attribute.");