Index: test/generated_sdk/lib/core/list.dart |
diff --git a/test/generated_sdk/lib/core/list.dart b/test/generated_sdk/lib/core/list.dart |
index 9168fbaef0990de4bf5ed9485fa9c1e40cd97ef4..e87bbcd9031d8cada2f1e5f25864efac2918f249 100644 |
--- a/test/generated_sdk/lib/core/list.dart |
+++ b/test/generated_sdk/lib/core/list.dart |
@@ -76,11 +76,19 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* The [length] must not be negative or null, if it is provided. |
*/ |
- factory List([int length = const _ListConstructorSentinel()]) { |
- if (length == const _ListConstructorSentinel()) { |
- return new JSArray<E>.emptyGrowable(); |
+ factory List([int length]) { |
+ if (length == null) { |
+ return JS('', '[]'); |
} |
- return new JSArray<E>.fixed(length); |
+ // Explicit type test is necessary to guard against JavaScript conversions |
+ // in unchecked mode. |
+ if ((length is !int) || (length < 0)) { |
+ throw new ArgumentError("Length must be a non-negative integer: $length"); |
+ } |
+ var list = JS('', 'new Array(#)', length); |
+ // TODO(jmesserly): consider a fixed array subclass instead. |
+ JS('void', r'#.fixed$length = Array', list); |
+ return list; |
} |
/** |
@@ -143,24 +151,173 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
return result; |
} |
+ checkMutable(reason) { |
+ /* TODO(jacobr): implement. |
+ if (this is !JSMutableArray) { |
+ throw new UnsupportedError(reason); |
+ } |
+ * */ |
+ } |
+ |
+ checkGrowable(reason) { |
+ /* TODO(jacobr): implement |
+ if (this is !JSExtendableArray) { |
+ throw new UnsupportedError(reason); |
+ } |
+ * */ |
+ } |
+ |
+ Iterable<E> where(bool f(E element)) { |
+ return new IterableMixinWorkaround<E>().where(this, f); |
+ } |
+ |
+ Iterable expand(Iterable f(E element)) { |
+ return IterableMixinWorkaround.expand(this, f); |
+ } |
+ |
+ void forEach(void f(E element)) { |
+ int length = this.length; |
+ for (int i = 0; i < length; i++) { |
+ f(JS('', '#[#]', this, i)); |
+ if (length != this.length) { |
+ throw new ConcurrentModificationError(this); |
+ } |
+ } |
+ } |
+ |
+ Iterable map(f(E element)) { |
+ return IterableMixinWorkaround.mapList(this, f); |
+ } |
+ |
+ String join([String separator = ""]) { |
+ var list = new List(this.length); |
+ for (int i = 0; i < this.length; i++) { |
+ list[i] = "${this[i]}"; |
+ } |
+ return JS('String', "#.join(#)", list, separator); |
+ } |
+ |
+ Iterable<E> take(int n) { |
+ return new IterableMixinWorkaround<E>().takeList(this, n); |
+ } |
+ |
+ Iterable<E> takeWhile(bool test(E value)) { |
+ return new IterableMixinWorkaround<E>().takeWhile(this, test); |
+ } |
+ |
+ Iterable<E> skip(int n) { |
+ return new IterableMixinWorkaround<E>().skipList(this, n); |
+ } |
+ |
+ Iterable<E> skipWhile(bool test(E value)) { |
+ return new IterableMixinWorkaround<E>().skipWhile(this, test); |
+ } |
+ |
+ E reduce(E combine(E value, E element)) { |
+ return IterableMixinWorkaround.reduce(this, combine); |
+ } |
+ |
+ fold(initialValue, combine(previousValue, E element)) { |
+ return IterableMixinWorkaround.fold(this, initialValue, combine); |
+ } |
+ |
+ E firstWhere(bool test(E value), {E orElse()}) { |
+ return IterableMixinWorkaround.firstWhere(this, test, orElse); |
+ } |
+ |
+ E lastWhere(bool test(E value), {E orElse()}) { |
+ return IterableMixinWorkaround.lastWhereList(this, test, orElse); |
+ } |
+ |
+ E singleWhere(bool test(E value)) { |
+ return IterableMixinWorkaround.singleWhere(this, test); |
+ } |
+ |
+ E elementAt(int index) { |
+ return this[index]; |
+ } |
+ |
+ E get first { |
+ if (length > 0) return this[0]; |
+ throw new StateError("No elements"); |
+ } |
+ |
+ E get last { |
+ if (length > 0) return this[length - 1]; |
+ throw new StateError("No elements"); |
+ } |
+ |
+ E get single { |
+ if (length == 1) return this[0]; |
+ if (length == 0) throw new StateError("No elements"); |
+ throw new StateError("More than one element"); |
+ } |
+ |
+ bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f); |
+ |
+ bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f); |
+ |
+ void sort([int compare(E a, E b)]) { |
+ checkMutable('sort'); |
+ IterableMixinWorkaround.sortList(this, compare); |
+ } |
+ |
+ bool contains(Object other) { |
+ for (int i = 0; i < length; i++) { |
+ if (this[i] == other) return true; |
+ } |
+ return false; |
+ } |
+ |
+ bool get isEmpty => length == 0; |
+ |
+ bool get isNotEmpty => !isEmpty; |
+ |
+ String toString() => ListBase.listToString(this); |
+ |
+ List<E> toList({ bool growable: true }) { |
+ if (growable) { |
+ return new JSArray<E>.markGrowable(JS('', '#.slice()', this)); |
+ } else { |
+ return new JSArray<E>.markFixed(JS('', '#.slice()', this)); |
+ } |
+ } |
+ |
+ Set<E> toSet() => new Set<E>.from(this); |
+ |
+ Iterator<E> get iterator => new ListIterator<E>(this); |
+ |
+ int get hashCode => Primitives.objectHashCode(this); |
+ |
+ // BORDER XXXX |
+ |
/** |
* Returns the object at the given [index] in the list |
* or throws a [RangeError] if [index] is out of bounds. |
*/ |
- E operator [](int index); |
+ E operator [](int index) { |
+ if (index is !int) throw new ArgumentError(index); |
+ if (index >= length || index < 0) throw new RangeError.value(index); |
+ return JS('var', '#[#]', this, index); |
+ } |
/** |
* Sets the value at the given [index] in the list to [value] |
* or throws a [RangeError] if [index] is out of bounds. |
*/ |
- void operator []=(int index, E value); |
+ void operator []=(int index, E value) { |
+ checkMutable('indexed set'); |
+ if (index is !int) throw new ArgumentError(index); |
+ if (index >= length || index < 0) throw new RangeError.value(index); |
+ JS('void', r'#[#] = #', this, index, value); |
+ } |
/** |
* Returns the number of objects in this list. |
* |
* The valid indices for a list are `0` through `length - 1`. |
*/ |
- int get length; |
+ int get length => JS('JSUInt32', r'#.length', this); |
/** |
* Changes the length of this list. |
@@ -170,7 +327,12 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* Throws an [UnsupportedError] if the list is fixed-length. |
*/ |
- void set length(int newLength); |
+ void set length(int newLength) { |
+ if (newLength is !int) throw new ArgumentError(newLength); |
+ if (newLength < 0) throw new RangeError.value(newLength); |
+ checkGrowable('set length'); |
+ JS('void', r'#.length = #', this, newLength); |
+ } |
/** |
* Adds [value] to the end of this list, |
@@ -178,7 +340,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* Throws an [UnsupportedError] if the list is fixed-length. |
*/ |
- void add(E value); |
+ void add(E value) { |
+ checkGrowable('add'); |
+ JS('void', r'#.push(#)', this, value); |
+ } |
/** |
* Appends all objects of [iterable] to the end of this list. |
@@ -186,12 +351,17 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* Extends the length of the list by the number of objects in [iterable]. |
* Throws an [UnsupportedError] if this list is fixed-length. |
*/ |
- void addAll(Iterable<E> iterable); |
+ void addAll(Iterable<E> iterable) { |
+ for (E e in iterable) { |
+ this.add(e); |
+ } |
+ } |
/** |
* Returns an [Iterable] of the objects in this list in reverse order. |
*/ |
- Iterable<E> get reversed; |
+ Iterable<E> get reversed => |
+ new IterableMixinWorkaround<E>().reversedList(this); |
/** |
* Sorts this list according to the order specified by the [compare] function. |
@@ -210,12 +380,17 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* nums.sort(); |
nums.join(', '); // '-11, 2, 13' |
*/ |
- void sort([int compare(E a, E b)]); |
+ void sort([int compare(E a, E b)]) { |
+ // XXX checkMutable('sort'); |
+ IterableMixinWorkaround.sortList(this, compare); |
+ } |
/** |
* Shuffles the elements of this list randomly. |
*/ |
- void shuffle([Random random]); |
+ void shuffle([Random random]) { |
+ IterableMixinWorkaround.shuffleList(this, random); |
+ } |
/** |
* Returns the first index of [element] in this list. |
@@ -232,7 +407,9 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* notes.indexOf('fa'); // -1 |
*/ |
- int indexOf(E element, [int start = 0]); |
+ int indexOf(E element, [int start = 0]) { |
+ return IterableMixinWorkaround.indexOfList(this, element, start); |
+ } |
/** |
* Returns the last index of [element] in this list. |
@@ -254,7 +431,9 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* notes.lastIndexOf('fa'); // -1 |
*/ |
- int lastIndexOf(E element, [int start]); |
+ int lastIndexOf(E element, [int start]) { |
+ return IterableMixinWorkaround.lastIndexOfList(this, element, start); |
+ } |
/** |
* Removes all objects from this list; |
@@ -263,7 +442,9 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* Throws an [UnsupportedError], and retains all objects, if this |
* is a fixed-length list. |
*/ |
- void clear(); |
+ void clear() { |
+ length = 0; |
+ } |
/** |
* Inserts the object at position [index] in this list. |
@@ -274,7 +455,15 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* An error occurs if the [index] is less than 0 or greater than length. |
* An [UnsupportedError] occurs if the list is fixed-length. |
*/ |
- void insert(int index, E element); |
+ void insert(int index, E element) { |
+ if (index is !int) throw new ArgumentError(index); |
+ if (index < 0 || index > length) { |
+ throw new RangeError.value(index); |
+ } |
+ checkGrowable('insert'); |
+ JS('void', r'#.splice(#, 0, #)', this, index, element); |
+ } |
+ |
/** |
* Inserts all objects of [iterable] at position [index] in this list. |
@@ -285,7 +474,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* An error occurs if the [index] is less than 0 or greater than length. |
* An [UnsupportedError] occurs if the list is fixed-length. |
*/ |
- void insertAll(int index, Iterable<E> iterable); |
+ void insertAll(int index, Iterable<E> iterable) { |
+ checkGrowable('insertAll'); |
+ IterableMixinWorkaround.insertAllList(this, index, iterable); |
+ } |
/** |
* Overwrites objects of `this` with the objects of [iterable], starting |
@@ -305,7 +497,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* If `iterable` is based on this list, its values may change /during/ the |
* `setAll` operation. |
*/ |
- void setAll(int index, Iterable<E> iterable); |
+ void setAll(int index, Iterable<E> iterable) { |
+ checkMutable('setAll'); |
+ IterableMixinWorkaround.setAllList(this, index, iterable); |
+ } |
/** |
* Removes the first occurence of [value] from this list. |
@@ -324,7 +519,16 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* An [UnsupportedError] occurs if the list is fixed-length. |
*/ |
- bool remove(Object value); |
+ bool remove(Object element) { |
+ checkGrowable('remove'); |
+ for (int i = 0; i < this.length; i++) { |
+ if (this[i] == value) { |
+ JS('var', r'#.splice(#, 1)', this, i); |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
/** |
* Removes the object at position [index] from this list. |
@@ -339,14 +543,25 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* Throws an [UnsupportedError] if this is a fixed-length list. In that case |
* the list is not modified. |
*/ |
- E removeAt(int index); |
+ E removeAt(int index) { |
+ if (index is !int) throw new ArgumentError(index); |
+ if (index < 0 || index >= length) { |
+ throw new RangeError.value(index); |
+ } |
+ checkGrowable('removeAt'); |
+ return JS('var', r'#.splice(#, 1)[0]', this, index); |
+ } |
/** |
* Pops and returns the last object in this list. |
* |
* Throws an [UnsupportedError] if this is a fixed-length list. |
*/ |
- E removeLast(); |
+ E removeLast() { |
+ checkGrowable('removeLast'); |
+ if (length == 0) throw new RangeError.value(-1); |
+ return JS('var', r'#.pop()', this); |
+ } |
/** |
* Removes all objects from this list that satisfy [test]. |
@@ -359,7 +574,11 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* Throws an [UnsupportedError] if this is a fixed-length list. |
*/ |
- void removeWhere(bool test(E element)); |
+ void removeWhere(bool test(E element)) { |
+ // This could, and should, be optimized. |
+ IterableMixinWorkaround.removeWhereList(this, test); |
+ } |
+ |
/** |
* Removes all objects from this list that fail to satisfy [test]. |
@@ -372,7 +591,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* Throws an [UnsupportedError] if this is a fixed-length list. |
*/ |
- void retainWhere(bool test(E element)); |
+ void retainWhere(bool test(E element)) { |
+ IterableMixinWorkaround.removeWhereList(this, |
+ (E element) => !test(element)); |
+ } |
/** |
* Returns a new list containing the objects from [start] inclusive to [end] |
@@ -388,7 +610,24 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* An error occurs if [start] is outside the range `0` .. `length` or if |
* [end] is outside the range `start` .. `length`. |
*/ |
- List<E> sublist(int start, [int end]); |
+ List<E> sublist(int start, [int end]) { |
+ checkNull(start); // TODO(ahe): This is not specified but co19 tests it. |
+ if (start is !int) throw new ArgumentError(start); |
+ if (start < 0 || start > length) { |
+ throw new RangeError.range(start, 0, length); |
+ } |
+ if (end == null) { |
+ end = length; |
+ } else { |
+ if (end is !int) throw new ArgumentError(end); |
+ if (end < start || end > length) { |
+ throw new RangeError.range(end, start, length); |
+ } |
+ } |
+ if (start == end) return <E>[]; |
+ return new JSArray<E>.markGrowable( |
+ JS('', r'#.slice(#, #)', this, start, end)); |
+ } |
/** |
* Returns an [Iterable] that iterates over the objects in the range |
@@ -407,7 +646,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* colors.length = 3; |
* range.join(', '); // 'green, blue' |
*/ |
- Iterable<E> getRange(int start, int end); |
+ Iterable<E> getRange(int start, int end) { |
+ return new IterableMixinWorkaround<E>().getRangeList(this, start, end); |
+ } |
+ |
/** |
* Copies the objects of [iterable], skipping [skipCount] objects first, |
@@ -433,7 +675,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* If `iterable` depends on this list in some other way, no guarantees are |
* made. |
*/ |
- void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]); |
+ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
+ checkMutable('set range'); |
+ IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount); |
+ } |
/** |
* Removes the objects in the range [start] inclusive to [end] exclusive. |
@@ -444,7 +689,22 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* Throws an [UnsupportedError] if this is a fixed-length list. In that case |
* the list is not modified. |
*/ |
- void removeRange(int start, int end); |
+ void removeRange(int start, int end) { |
+ checkGrowable('removeRange'); |
+ int receiverLength = this.length; |
+ if (start < 0 || start > receiverLength) { |
+ throw new RangeError.range(start, 0, receiverLength); |
+ } |
+ if (end < start || end > receiverLength) { |
+ throw new RangeError.range(end, start, receiverLength); |
+ } |
+ Lists.copy(this, |
+ end, |
+ this, |
+ start, |
+ receiverLength - end); |
+ this.length = receiverLength - (end - start); |
+ } |
/** |
* Sets the objects in the range [start] inclusive to [end] exclusive |
@@ -452,7 +712,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* An error occurs if [start]..[end] is not a valid range for `this`. |
*/ |
- void fillRange(int start, int end, [E fillValue]); |
+ void fillRange(int start, int end, [E fillValue]) { |
+ checkMutable('fill range'); |
+ IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); |
+ } |
/** |
* Removes the objects in the range [start] inclusive to [end] exclusive |
@@ -464,7 +727,10 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* |
* An error occurs if [start]..[end] is not a valid range for `this`. |
*/ |
- void replaceRange(int start, int end, Iterable<E> replacement); |
+ void replaceRange(int start, int end, Iterable<E> replacement) { |
+ checkGrowable('removeRange'); |
+ IterableMixinWorkaround.replaceRangeList(this, start, end, replacement); |
+ } |
/** |
* Returns an unmodifiable [Map] view of `this`. |
@@ -478,5 +744,7 @@ abstract class List<E> implements Iterable<E>, EfficientLength { |
* map[0] + map[1]; // 'feefi'; |
* map.keys.toList(); // [0, 1, 2, 3] |
*/ |
- Map<int, E> asMap(); |
+ Map<int, E> asMap() { |
+ return new IterableMixinWorkaround<E>().asMapList(this); |
+ } |
} |