Version 1.10.0-dev.1.9
svn merge -c 45307 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@45311 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index e780d2e..b767c0b 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -36383,6 +36383,10 @@
* operation.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To toggle multiple classes, use
+ * [toggleAll].
*/
bool toggle(String value, [bool shouldAdd]);
@@ -36397,19 +36401,26 @@
*
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace.
*/
bool contains(String value);
/**
* Add the class [value] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
*
- * If this corresponds to one element. Returns true if [value] was added to
- * the set, otherwise false.
+ * If this CssClassSet corresponds to one element. Returns true if [value] was
+ * added to the set, otherwise false.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To add multiple classes use
+ * [addAll].
*/
bool add(String value);
@@ -36417,24 +36428,34 @@
* Remove the class [value] from element, and return true on successful
* removal.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To remove multiple classes, use
+ * [removeAll].
*/
bool remove(Object value);
/**
* Add all classes specified in [iterable] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void addAll(Iterable<String> iterable);
/**
* Remove all classes specified in [iterable] from element.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void removeAll(Iterable<String> iterable);
@@ -36447,6 +36468,9 @@
* If [shouldAdd] is true, then we always add all the classes in [iterable]
* element. If [shouldAdd] is false then we always remove all the classes in
* [iterable] from the element.
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
}
@@ -36812,7 +36836,7 @@
_element.className = '';
}
- bool contains(String value) {
+ bool contains(Object value) {
return _contains(_element, value);
}
@@ -36848,8 +36872,8 @@
_removeWhere(_element, test, false);
}
- static bool _contains(Element _element, String value) {
- return _classListContains(_classListOf(_element), value);
+ static bool _contains(Element _element, Object value) {
+ return value is String && _classListContains(_classListOf(_element), value);
}
static bool _add(Element _element, String value) {
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 63e26ae..50ce4bb 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -37305,6 +37305,10 @@
* operation.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To toggle multiple classes, use
+ * [toggleAll].
*/
bool toggle(String value, [bool shouldAdd]);
@@ -37319,19 +37323,26 @@
*
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace.
*/
bool contains(String value);
/**
* Add the class [value] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
*
- * If this corresponds to one element. Returns true if [value] was added to
- * the set, otherwise false.
+ * If this CssClassSet corresponds to one element. Returns true if [value] was
+ * added to the set, otherwise false.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To add multiple classes use
+ * [addAll].
*/
bool add(String value);
@@ -37339,24 +37350,34 @@
* Remove the class [value] from element, and return true on successful
* removal.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To remove multiple classes, use
+ * [removeAll].
*/
bool remove(Object value);
/**
* Add all classes specified in [iterable] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void addAll(Iterable<String> iterable);
/**
* Remove all classes specified in [iterable] from element.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void removeAll(Iterable<String> iterable);
@@ -37369,6 +37390,9 @@
* If [shouldAdd] is true, then we always add all the classes in [iterable]
* element. If [shouldAdd] is false then we always remove all the classes in
* [iterable] from the element.
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
}
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 0380d2d..9c4b443 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -6,6 +6,13 @@
abstract class CssClassSetImpl implements CssClassSet {
+ static final RegExp _validTokenRE = new RegExp(r'^\S+$');
+
+ String _validateToken(String value) {
+ if (_validTokenRE.hasMatch(value)) return value;
+ throw new ArgumentError.value(value, 'value', 'Not a valid class token');
+ }
+
String toString() {
return readClasses().join(' ');
}
@@ -18,6 +25,7 @@
* [shouldAdd] is false then we always remove [value] from the element.
*/
bool toggle(String value, [bool shouldAdd]) {
+ _validateToken(value);
Set<String> s = readClasses();
bool result = false;
if (shouldAdd == null) shouldAdd = !s.contains(value);
@@ -81,7 +89,11 @@
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
*/
- bool contains(Object value) => readClasses().contains(value);
+ bool contains(Object value) {
+ if (value is! String) return false;
+ _validateToken(value);
+ return readClasses().contains(value);
+ }
/** Lookup from the Set interface. Not interesting for a String set. */
String lookup(Object value) => contains(value) ? value : null;
@@ -93,6 +105,7 @@
* [addClass](http://api.jquery.com/addClass/).
*/
bool add(String value) {
+ _validateToken(value);
// TODO - figure out if we need to do any validation here
// or if the browser natively does enough.
return modify((s) => s.add(value));
@@ -106,6 +119,7 @@
* [removeClass](http://api.jquery.com/removeClass/).
*/
bool remove(Object value) {
+ _validateToken(value);
if (value is! String) return false;
Set<String> s = readClasses();
bool result = s.remove(value);
@@ -121,7 +135,7 @@
*/
void addAll(Iterable<String> iterable) {
// TODO - see comment above about validation.
- modify((s) => s.addAll(iterable));
+ modify((s) => s.addAll(iterable.map(_validateToken)));
}
/**
@@ -131,7 +145,7 @@
* [removeClass](http://api.jquery.com/removeClass/).
*/
void removeAll(Iterable<Object> iterable) {
- modify((s) => s.removeAll(iterable));
+ modify((s) => s.removeAll(iterable.map(_validateToken)));
}
/**
diff --git a/tests/html/element_classes_test.dart b/tests/html/element_classes_test.dart
index 14af4bd..2846d0d 100644
--- a/tests/html/element_classes_test.dart
+++ b/tests/html/element_classes_test.dart
@@ -129,6 +129,15 @@
expect(makeClassSet().contains('qux'), isFalse);
});
+ test('contains-bad', () {
+ // Non-strings return `false`.
+ // Strings need to be valid tokens.
+ final classes = makeClassSet();
+ expect(classes.contains(1), isFalse);
+ expect(() => classes.contains(''), throws);
+ expect(() => classes.contains('foo bar'), throws);
+ });
+
test('add', () {
final classes = makeClassSet();
var added = classes.add('qux');
@@ -143,6 +152,12 @@
reason: "The class set shouldn't have duplicate elements.");
});
+ test('add-bad', () {
+ final classes = makeClassSet();
+ expect(() => classes.add(''), throws);
+ expect(() => classes.add('foo bar'), throws);
+ });
+
test('remove', () {
final classes = makeClassSet();
classes.remove('bar');
@@ -151,6 +166,12 @@
expect(classes, orderedEquals(['foo', 'baz']));
});
+ test('remove-bad', () {
+ final classes = makeClassSet();
+ expect(() => classes.remove(''), throws);
+ expect(() => classes.remove('foo bar'), throws);
+ });
+
test('toggle', () {
final classes = makeClassSet();
classes.toggle('bar');
@@ -168,6 +189,16 @@
expect(classes, orderedEquals(['foo', 'baz', 'qux']));
});
+ test('toggle-bad', () {
+ final classes = makeClassSet();
+ expect(() => classes.toggle(''), throws);
+ expect(() => classes.toggle('', true), throws);
+ expect(() => classes.toggle('', false), throws);
+ expect(() => classes.toggle('foo bar'), throws);
+ expect(() => classes.toggle('foo bar', true), throws);
+ expect(() => classes.toggle('foo bar', false), throws);
+ });
+
test('addAll', () {
final classes = makeClassSet();
classes.addAll(['bar', 'qux', 'bip']);
diff --git a/tests/html/svgelement_test.dart b/tests/html/svgelement_test.dart
index 7ab3d5138..dcfeb4c 100644
--- a/tests/html/svgelement_test.dart
+++ b/tests/html/svgelement_test.dart
@@ -423,6 +423,33 @@
classes.toggle('foo');
expect(el.classes.length, 0);
});
+
+ test('classes-add-bad', () {
+ var el = new svg.CircleElement();
+ expect(() => el.classes.add(''), throws);
+ expect(() => el.classes.add('foo bar'), throws);
+ });
+ test('classes-remove-bad', () {
+ var el = new svg.CircleElement();
+ expect(() => el.classes.remove(''), throws);
+ expect(() => el.classes.remove('foo bar'), throws);
+ });
+ test('classes-toggle-token', () {
+ var el = new svg.CircleElement();
+ expect(() => el.classes.toggle(''), throws);
+ expect(() => el.classes.toggle('', true), throws);
+ expect(() => el.classes.toggle('', false), throws);
+ expect(() => el.classes.toggle('foo bar'), throws);
+ expect(() => el.classes.toggle('foo bar', true), throws);
+ expect(() => el.classes.toggle('foo bar', false), throws);
+ });
+ test('classes-contains-bad', () {
+ var el = new svg.CircleElement();
+ // Non-strings => false, strings must be valid tokens.
+ expect(el.classes.contains(1), isFalse);
+ expect(() => el.classes.contains(''), throws);
+ expect(() => el.classes.contains('foo bar'), throws);
+ });
});
group('getBoundingClientRect', () {
diff --git a/tools/VERSION b/tools/VERSION
index 031f2b2..6359d8e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 10
PATCH 0
PRERELEASE 1
-PRERELEASE_PATCH 8
+PRERELEASE_PATCH 9
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 0c405e4..8224b77 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -19,6 +19,10 @@
* operation.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To toggle multiple classes, use
+ * [toggleAll].
*/
bool toggle(String value, [bool shouldAdd]);
@@ -33,19 +37,26 @@
*
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace.
*/
bool contains(String value);
/**
* Add the class [value] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
*
- * If this corresponds to one element. Returns true if [value] was added to
- * the set, otherwise false.
+ * If this CssClassSet corresponds to one element. Returns true if [value] was
+ * added to the set, otherwise false.
*
* If this corresponds to many elements, `null` is always returned.
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To add multiple classes use
+ * [addAll].
*/
bool add(String value);
@@ -53,24 +64,34 @@
* Remove the class [value] from element, and return true on successful
* removal.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * [value] must be a valid 'token' representing a single class, i.e. a
+ * non-empty string containing no whitespace. To remove multiple classes, use
+ * [removeAll].
*/
bool remove(Object value);
/**
* Add all classes specified in [iterable] to element.
*
- * This is the Dart equivalent of jQuery's
+ * [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void addAll(Iterable<String> iterable);
/**
* Remove all classes specified in [iterable] from element.
*
- * This is the Dart equivalent of jQuery's
+ * [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void removeAll(Iterable<String> iterable);
@@ -83,6 +104,9 @@
* If [shouldAdd] is true, then we always add all the classes in [iterable]
* element. If [shouldAdd] is false then we always remove all the classes in
* [iterable] from the element.
+ *
+ * Each element of [iterable] must be a valid 'token' representing a single
+ * class, i.e. a non-empty string containing no whitespace.
*/
void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
}
diff --git a/tools/dom/src/dart2js_CssClassSet.dart b/tools/dom/src/dart2js_CssClassSet.dart
index 783828b..cf5fa33 100644
--- a/tools/dom/src/dart2js_CssClassSet.dart
+++ b/tools/dom/src/dart2js_CssClassSet.dart
@@ -100,7 +100,7 @@
_element.className = '';
}
- bool contains(String value) {
+ bool contains(Object value) {
return _contains(_element, value);
}
@@ -136,8 +136,8 @@
_removeWhere(_element, test, false);
}
- static bool _contains(Element _element, String value) {
- return _classListContains(_classListOf(_element), value);
+ static bool _contains(Element _element, Object value) {
+ return value is String && _classListContains(_classListOf(_element), value);
}
static bool _add(Element _element, String value) {