Bug 1224186: Implement DOMTokenlist.replace r=baku r=Ms2ger
☠☠ backed out by 98048beb73c9 ☠ ☠
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Mon, 21 Mar 2016 06:10:00 +0100
changeset 330879 92a78fabeb8d727258cb5313bbc394f3e3786c09
parent 330878 f88bfa3062821076a4aabef319422ce705d9715c
child 330880 d1d120b8dbb2c815928155279034c82592a0daf3
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, Ms2ger
bugs1224186
milestone48.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 1224186: Implement DOMTokenlist.replace r=baku r=Ms2ger
dom/base/nsDOMTokenList.cpp
dom/base/nsDOMTokenList.h
dom/webidl/DOMTokenList.webidl
testing/web-platform/tests/dom/nodes/Element-classlist.html
--- a/dom/base/nsDOMTokenList.cpp
+++ b/dom/base/nsDOMTokenList.cpp
@@ -69,17 +69,17 @@ nsDOMTokenList::IndexedGetter(uint32_t a
     aFound = true;
     attr->AtomAt(aIndex)->ToString(aResult);
   } else {
     aFound = false;
   }
 }
 
 void
-nsDOMTokenList::SetValue(const nsAString& aValue, mozilla::ErrorResult& rv)
+nsDOMTokenList::SetValue(const nsAString& aValue, ErrorResult& rv)
 {
   if (!mElement) {
     return;
   }
 
   rv = mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true);
 }
 
@@ -177,17 +177,17 @@ nsDOMTokenList::Add(const nsTArray<nsStr
     return;
   }
 
   const nsAttrValue* attr = GetParsedAttr();
   AddInternal(attr, aTokens);
 }
 
 void
-nsDOMTokenList::Add(const nsAString& aToken, mozilla::ErrorResult& aError)
+nsDOMTokenList::Add(const nsAString& aToken, ErrorResult& aError)
 {
   AutoTArray<nsString, 1> tokens;
   tokens.AppendElement(aToken);
   Add(tokens, aError);
 }
 
 void
 nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
@@ -263,17 +263,17 @@ nsDOMTokenList::Remove(const nsTArray<ns
   if (!attr) {
     return;
   }
 
   RemoveInternal(attr, aTokens);
 }
 
 void
-nsDOMTokenList::Remove(const nsAString& aToken, mozilla::ErrorResult& aError)
+nsDOMTokenList::Remove(const nsAString& aToken, ErrorResult& aError)
 {
   AutoTArray<nsString, 1> tokens;
   tokens.AppendElement(aToken);
   Remove(tokens, aError);
 }
 
 bool
 nsDOMTokenList::Toggle(const nsAString& aToken,
@@ -304,16 +304,53 @@ nsDOMTokenList::Toggle(const nsAString& 
       isPresent = true;
     }
   }
 
   return isPresent;
 }
 
 void
+nsDOMTokenList::Replace(const nsAString& aToken,
+                        const nsAString& aNewToken,
+                        ErrorResult& aError)
+{
+  // Doing this here instead of using `CheckToken` because if aToken had invalid
+  // characters, and aNewToken is empty, the returned error should be a
+  // SyntaxError, not an InvalidCharacterError.
+  if (aNewToken.IsEmpty()) {
+    aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    return;
+  }
+
+  aError = CheckToken(aToken);
+  if (aError.Failed()) {
+    return;
+  }
+
+  aError = CheckToken(aNewToken);
+  if (aError.Failed()) {
+    return;
+  }
+
+  const nsAttrValue* attr = GetParsedAttr();
+  if (!attr || !attr->Contains(aToken)) {
+    return;
+  }
+
+  AutoTArray<nsString, 1> tokens;
+
+  tokens.AppendElement(aToken);
+  RemoveInternal(attr, tokens);
+
+  tokens[0] = aNewToken;
+  AddInternal(attr, tokens);
+}
+
+void
 nsDOMTokenList::Stringify(nsAString& aResult)
 {
   if (!mElement) {
     aResult.Truncate();
     return;
   }
 
   mElement->GetAttr(kNameSpaceID_None, mAttrAtom, aResult);
--- a/dom/base/nsDOMTokenList.h
+++ b/dom/base/nsDOMTokenList.h
@@ -58,20 +58,23 @@ public:
   void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult);
   bool Contains(const nsAString& aToken, mozilla::ErrorResult& aError);
   void Add(const nsAString& aToken, mozilla::ErrorResult& aError);
   void Add(const nsTArray<nsString>& aTokens,
            mozilla::ErrorResult& aError);
   void Remove(const nsAString& aToken, mozilla::ErrorResult& aError);
   void Remove(const nsTArray<nsString>& aTokens,
               mozilla::ErrorResult& aError);
+  void Replace(const nsAString& aToken,
+               const nsAString& aNewToken,
+               mozilla::ErrorResult& aError);
   bool Toggle(const nsAString& aToken,
               const mozilla::dom::Optional<bool>& force,
               mozilla::ErrorResult& aError);
-  
+
   void GetValue(nsAString& aResult) { Stringify(aResult); }
   void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv);
   void Stringify(nsAString& aResult);
 
 protected:
   virtual ~nsDOMTokenList();
 
   nsresult CheckToken(const nsAString& aStr);
--- a/dom/webidl/DOMTokenList.webidl
+++ b/dom/webidl/DOMTokenList.webidl
@@ -15,13 +15,15 @@ interface DOMTokenList {
   getter DOMString? item(unsigned long index);
   [Throws]
   boolean contains(DOMString token);
   [Throws]
   void add(DOMString... tokens);
   [Throws]
   void remove(DOMString... tokens);
   [Throws]
+  void replace(DOMString token, DOMString newToken);
+  [Throws]
   boolean toggle(DOMString token, optional boolean force);
   [SetterThrows]
   attribute DOMString value;
   stringifier DOMString ();
 };
--- a/testing/web-platform/tests/dom/nodes/Element-classlist.html
+++ b/testing/web-platform/tests/dom/nodes/Element-classlist.html
@@ -372,16 +372,30 @@ test(function () {
 test(function () {
   var realList = secondelem.classList;
   secondelem.classList = 'foo bar';
   assert_equals(secondelem.classList,realList);
   assert_equals(secondelem.classList.length,2);
   assert_equals(secondelem.classList[0],'foo');
   assert_equals(secondelem.classList[1],'bar');
 }, 'classList must have [PutForwards=value]');
+test(function () {
+  var foo = document.createElement('div');
+  foo.className = 'a';
+  foo.classList.replace('token1', 'token2');
+
+  assert_equals(foo.className, 'a');
+
+  foo.classList.replace('a', 'b');
+  assert_equals(foo.className, 'b');
+
+  assert_throws('SYNTAX_ERR', function () { foo.classList.replace('t with space', '') });
+  assert_throws('INVALID_CHARACTER_ERR', function () { foo.classList.replace('t with space', 'foo') });
+  assert_throws('SYNTAX_ERR', function () { foo.classList.replace('', 'foo') });
+}, 'classList.replace should work');
     </script>
   </head>
   <body>
 
     <div id="log"></div>
 
   </body>
 </html>