Bug 1293563: Simplify DOMTokenlist.remove using a tokenizer. r=baku
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Fri, 26 Aug 2016 22:27:14 -0700
changeset 352796 e8ada2555f8372df966719bb42f32bf5cbe93761
parent 352795 3faaecb8dfcbc05a7b65ac9f0ff11955ec1b4829
child 352797 854dbb84bdbb40dda07dca93698f53ab3f1ddf72
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1293563
milestone51.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 1293563: Simplify DOMTokenlist.remove using a tokenizer. r=baku MozReview-Commit-ID: 4TTprZaZg8l
dom/base/nsDOMTokenList.cpp
dom/base/nsDOMTokenList.h
testing/web-platform/meta/dom/nodes/Element-classlist.html.ini
--- a/dom/base/nsDOMTokenList.cpp
+++ b/dom/base/nsDOMTokenList.cpp
@@ -5,21 +5,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
  * Implementation of DOMTokenList specified by HTML5.
  */
 
 #include "nsDOMTokenList.h"
 #include "nsAttrValue.h"
-#include "nsContentUtils.h"
 #include "nsError.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/DOMTokenListBinding.h"
-#include "nsWhitespaceTokenizer.h"
 #include "mozilla/ErrorResult.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsDOMTokenList::nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
                                const DOMTokenListSupportedTokenArray aSupportedTokens)
   : mElement(aElement),
@@ -191,63 +189,26 @@ void
 nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
                                const nsTArray<nsString>& aTokens)
 {
   MOZ_ASSERT(aAttr, "Need an attribute");
 
   nsAutoString input;
   aAttr->ToString(input);
 
-  nsAString::const_iterator copyStart, tokenStart, iter, end;
-  input.BeginReading(iter);
-  input.EndReading(end);
-  copyStart = iter;
-
+  WhitespaceTokenizer tokenizer(input);
   nsAutoString output;
-  bool lastTokenRemoved = false;
-
-  while (iter != end) {
-    // skip whitespace.
-    while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
-      ++iter;
-    }
-
-    if (iter == end) {
-      // At this point we're sure the last seen token (if any) wasn't to be
-      // removed. So the trailing spaces will need to be kept.
-      MOZ_ASSERT(!lastTokenRemoved, "How did this happen?");
 
-      output.Append(Substring(copyStart, end));
-      break;
-    }
-
-    tokenStart = iter;
-    do {
-      ++iter;
-    } while (iter != end && !nsContentUtils::IsHTMLWhitespace(*iter));
-
-    if (aTokens.Contains(Substring(tokenStart, iter))) {
-
-      // Skip whitespace after the token, it will be collapsed.
-      while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
-        ++iter;
-      }
-      copyStart = iter;
-      lastTokenRemoved = true;
-
-    } else {
-
-      if (lastTokenRemoved && !output.IsEmpty()) {
-        MOZ_ASSERT(!nsContentUtils::IsHTMLWhitespace(output.Last()),
-                   "Invalid last output token");
+  while (tokenizer.hasMoreTokens()) {
+    auto& currentToken = tokenizer.nextToken();
+    if (!aTokens.Contains(currentToken)) {
+      if (!output.IsEmpty()) {
         output.Append(char16_t(' '));
       }
-      lastTokenRemoved = false;
-      output.Append(Substring(copyStart, iter));
-      copyStart = iter;
+      output.Append(currentToken);
     }
   }
 
   mElement->SetAttr(kNameSpaceID_None, mAttrAtom, output, true);
 }
 
 void
 nsDOMTokenList::Remove(const nsTArray<nsString>& aTokens, ErrorResult& aError)
@@ -341,19 +302,17 @@ void
 nsDOMTokenList::ReplaceInternal(const nsAttrValue* aAttr,
                                 const nsAString& aToken,
                                 const nsAString& aNewToken)
 {
   nsAutoString attribute;
   aAttr->ToString(attribute);
 
   nsAutoString result;
-
-  nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
-    tokenizer(attribute);
+  WhitespaceTokenizer tokenizer(attribute);
 
   bool sawIt = false;
   while (tokenizer.hasMoreTokens()) {
     auto currentToken = tokenizer.nextToken();
     if (currentToken.Equals(aToken) || currentToken.Equals(aNewToken)) {
       if (!sawIt) {
         sawIt = true;
         if (!result.IsEmpty()) {
--- a/dom/base/nsDOMTokenList.h
+++ b/dom/base/nsDOMTokenList.h
@@ -7,17 +7,19 @@
 /*
  * Implementation of DOMTokenList specified by HTML5.
  */
 
 #ifndef nsDOMTokenList_h___
 #define nsDOMTokenList_h___
 
 #include "nsCOMPtr.h"
+#include "nsContentUtils.h"
 #include "nsDOMString.h"
+#include "nsWhitespaceTokenizer.h"
 #include "nsWrapperCache.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/DOMTokenListSupportedTokens.h"
 
 namespace mozilla {
 class ErrorResult;
 
@@ -28,16 +30,18 @@ class nsIAtom;
 
 // nsISupports must be on the primary inheritance chain
 
 class nsDOMTokenList : public nsISupports,
                        public nsWrapperCache
 {
 protected:
   typedef mozilla::dom::Element Element;
+  typedef nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
+    WhitespaceTokenizer;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMTokenList)
 
   nsDOMTokenList(Element* aElement, nsIAtom* aAttrAtom,
                  const mozilla::dom::DOMTokenListSupportedTokenArray = nullptr);
 
--- a/testing/web-platform/meta/dom/nodes/Element-classlist.html.ini
+++ b/testing/web-platform/meta/dom/nodes/Element-classlist.html.ini
@@ -1,19 +1,16 @@
 [Element-classlist.html]
   type: testharness
   [classList must be correct for an element that has classes]
     expected: FAIL
 
   [empty classList should return the empty string since the ordered set parser skip the whitespaces]
     expected: FAIL
 
-  [classList.remove must collapse whitespaces around each token]
-    expected: FAIL
-
   [classList.remove must collapse whitespaces around each token and remove duplicates]
     expected: FAIL
 
   [classList.add must collapse whitespaces and remove duplicates when adding a token that already exists]
     expected: FAIL
 
   [classList.add should treat \\t as a space]
     expected: FAIL