Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Unified Diff: third_party/WebKit/Source/core/dom/DOMTokenList.cpp

Issue 2895903002: DOMTokenList: Update serialization algorithm on add()/remove() (Closed)
Patch Set: Remove one -expected.txt Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/dom/DOMTokenList.cpp
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
index e7d658e2a95146c7b8e8692f64b1320db8fa6b13..9c2ff7c0c1b3a8139733ed502ed5d6b36221152b 100644
--- a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
+++ b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
@@ -85,20 +85,15 @@ void DOMTokenList::add(const AtomicString& token,
// the bindings generator does not handle that.
void DOMTokenList::add(const Vector<String>& tokens,
ExceptionState& exception_state) {
- Vector<String> filtered_tokens;
- filtered_tokens.ReserveCapacity(tokens.size());
- for (const auto& token : tokens) {
- if (!ValidateToken(token, exception_state))
- return;
- if (ContainsInternal(AtomicString(token)))
- continue;
- if (filtered_tokens.Contains(token))
- continue;
- filtered_tokens.push_back(token);
- }
+ // https://dom.spec.whatwg.org/#dom-domtokenlist-add
+ // 1. For each token in tokens:
+ // 1. If token is the empty string, then throw a SyntaxError.
+ // 2. If token contains any ASCII whitespace, then throw an
+ // InvalidCharacterError.
kochi 2017/05/24 05:46:00 This comment is identical to line 111-, and the al
tkent 2017/05/24 06:05:34 Done.
+ if (!ValidateTokens(tokens, exception_state))
+ return;
- if (!filtered_tokens.IsEmpty())
- setValue(AddTokens(value(), filtered_tokens));
+ setValue(AddTokens(tokens));
}
void DOMTokenList::remove(const AtomicString& token,
@@ -112,20 +107,18 @@ void DOMTokenList::remove(const AtomicString& token,
// the bindings generator does not handle that.
void DOMTokenList::remove(const Vector<String>& tokens,
ExceptionState& exception_state) {
+ // https://dom.spec.whatwg.org/#dom-domtokenlist-remove
+ // 1. For each token in tokens:
+ // 1. If token is the empty string, then throw a SyntaxError.
+ // 2. If token contains any ASCII whitespace, then throw an
+ // InvalidCharacterError.
if (!ValidateTokens(tokens, exception_state))
return;
- // Check using containsInternal first since it is a lot faster than going
- // through the string character by character.
- bool found = false;
- for (const auto& token : tokens) {
- if (ContainsInternal(AtomicString(token))) {
- found = true;
- break;
- }
- }
-
- setValue(found ? RemoveTokens(value(), tokens) : value());
+ // https://github.com/whatwg/dom/issues/462
kochi 2017/05/24 05:46:00 This comment is ambiguous - how about being more s
tkent 2017/05/24 06:05:34 Done.
+ if (value().IsNull())
+ return;
+ setValue(RemoveTokens(tokens));
}
bool DOMTokenList::toggle(const AtomicString& token,
@@ -162,7 +155,7 @@ bool DOMTokenList::supports(const AtomicString& token,
void DOMTokenList::AddInternal(const AtomicString& token) {
if (!ContainsInternal(token))
- setValue(AddToken(value(), token));
+ setValue(AddToken(token));
}
void DOMTokenList::RemoveInternal(const AtomicString& token) {
@@ -170,95 +163,62 @@ void DOMTokenList::RemoveInternal(const AtomicString& token) {
// of character by character testing.
if (!ContainsInternal(token))
return;
- setValue(RemoveToken(value(), token));
+ setValue(RemoveToken(token));
}
-AtomicString DOMTokenList::AddToken(const AtomicString& input,
- const AtomicString& token) {
+AtomicString DOMTokenList::AddToken(const AtomicString& token) {
Vector<String> tokens;
tokens.push_back(token.GetString());
- return AddTokens(input, tokens);
+ return AddTokens(tokens);
}
// This returns an AtomicString because it is always passed as argument to
// setValue() and setValue() takes an AtomicString in argument.
-AtomicString DOMTokenList::AddTokens(const AtomicString& input,
- const Vector<String>& tokens) {
- bool needs_space = false;
-
- StringBuilder builder;
- if (!input.IsEmpty()) {
- builder.Append(input);
- needs_space = !IsHTMLSpace<UChar>(input[input.length() - 1]);
- }
-
- for (const auto& token : tokens) {
- if (needs_space)
- builder.Append(' ');
- builder.Append(token);
- needs_space = true;
- }
-
- return builder.ToAtomicString();
+AtomicString DOMTokenList::AddTokens(const Vector<String>& tokens) {
+ // https://dom.spec.whatwg.org/#dom-domtokenlist-add
+ SpaceSplitString& token_set = MutableSet();
+ // 2. For each token in tokens, append token to context object’s token set.
+ for (const auto& token : tokens)
+ token_set.Add(AtomicString(token));
+ // 3. Run the update steps.
+ return SerializeSet(token_set);
}
-AtomicString DOMTokenList::RemoveToken(const AtomicString& input,
- const AtomicString& token) {
+AtomicString DOMTokenList::RemoveToken(const AtomicString& token) {
Vector<String> tokens;
tokens.push_back(token.GetString());
- return RemoveTokens(input, tokens);
+ return RemoveTokens(tokens);
}
// This returns an AtomicString because it is always passed as argument to
// setValue() and setValue() takes an AtomicString in argument.
-AtomicString DOMTokenList::RemoveTokens(const AtomicString& input,
- const Vector<String>& tokens) {
- // Algorithm defined at
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#remove-a-token-from-a-string
- // New spec is at https://dom.spec.whatwg.org/#remove-a-token-from-a-string
-
- unsigned input_length = input.length();
- StringBuilder output; // 3
- output.ReserveCapacity(input_length);
- unsigned position = 0; // 4
-
- // Step 5
- while (position < input_length) {
- if (IsHTMLSpace<UChar>(input[position])) { // 6
- position++;
- continue; // 6.3
- }
-
- // Step 7
- StringBuilder token_builder;
- while (position < input_length && IsNotHTMLSpace<UChar>(input[position]))
- token_builder.Append(input[position++]);
-
- // Step 8
- String token = token_builder.ToString();
- if (tokens.Contains(token)) {
- // Step 8.1
- while (position < input_length && IsHTMLSpace<UChar>(input[position]))
- ++position;
-
- // Step 8.2
- size_t j = output.length();
- while (j > 0 && IsHTMLSpace<UChar>(output[j - 1]))
- --j;
- output.Resize(j);
- } else {
- output.Append(token); // Step 9
- }
-
- if (position < input_length && !output.IsEmpty())
- output.Append(' ');
+AtomicString DOMTokenList::RemoveTokens(const Vector<String>& tokens) {
+ // https://dom.spec.whatwg.org/#dom-domtokenlist-remove
+ SpaceSplitString& token_set = MutableSet();
+ // 2. For each token in tokens, remove token from context object’s token set.
+ for (const auto& token : tokens)
+ token_set.Remove(AtomicString(token));
+ // 3. Run the update steps.
+ return SerializeSet(token_set);
+}
+
+AtomicString DOMTokenList::SerializeSet(const SpaceSplitString& token_set) {
+ // https://dom.spec.whatwg.org/#concept-ordered-set-serializer
+ // The ordered set serializer takes a set and returns the concatenation of the
+ // strings in set, separated from each other by U+0020, if set is non-empty,
+ // and the empty string otherwise.
+ size_t size = token_set.size();
+ if (size == 0)
+ return g_empty_atom;
+ if (size == 1)
+ return token_set[0];
+ StringBuilder builder;
+ builder.Append(token_set[0]);
+ for (size_t i = 1; i < size; ++i) {
+ builder.Append(' ');
+ builder.Append(token_set[i]);
}
-
- size_t j = output.length();
- if (j > 0 && IsHTMLSpace<UChar>(output[j - 1]))
- output.Resize(j - 1);
-
- return output.ToAtomicString();
+ return builder.ToAtomicString();
}
void DOMTokenList::setValue(const AtomicString& value) {

Powered by Google App Engine
This is Rietveld 408576698