Index: pkg/dev_compiler/tool/input_sdk/private/js_array.dart |
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart |
index 2a3cfe7ee29c999f38bbc7e81d7c56a3c7ce9d13..44b6271471c15b0ddd33591c0be69cd0dfd45f84 100644 |
--- a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart |
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart |
@@ -64,30 +64,29 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
JS('void', r'#.push(#)', this, value); |
} |
- E removeAt(int index) { |
+ E removeAt(@nullCheck int index) { |
checkGrowable('removeAt'); |
- if (index is! int) throw argumentErrorValue(index); |
if (index < 0 || index >= length) { |
throw new RangeError.value(index); |
} |
return JS('-dynamic', r'#.splice(#, 1)[0]', this, index); |
} |
- void insert(int index, E value) { |
+ void insert(@nullCheck int index, E value) { |
checkGrowable('insert'); |
- if (index is! int) throw argumentErrorValue(index); |
if (index < 0 || index > length) { |
throw new RangeError.value(index); |
} |
JS('void', r'#.splice(#, 0, #)', this, index, value); |
} |
- void insertAll(int index, Iterable<E> iterable) { |
+ void insertAll(@nullCheck int index, Iterable<E> iterable) { |
checkGrowable('insertAll'); |
RangeError.checkValueInInterval(index, 0, this.length, "index"); |
if (iterable is! EfficientLengthIterable) { |
iterable = iterable.toList(); |
} |
+ @nullCheck |
int insertionLength = iterable.length; |
this.length += insertionLength; |
int end = index + insertionLength; |
@@ -95,7 +94,7 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
this.setRange(index, end, iterable); |
} |
- void setAll(int index, Iterable<E> iterable) { |
+ void setAll(@nullCheck int index, Iterable<E> iterable) { |
checkMutable('setAll'); |
RangeError.checkValueInInterval(index, 0, this.length, "index"); |
for (var element in iterable) { |
@@ -111,7 +110,8 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
bool remove(Object element) { |
checkGrowable('remove'); |
- for (int i = 0; i < this.length; i++) { |
+ var length = this.length; |
+ for (int i = 0; i < length; i++) { |
if (this[i] == element) { |
JS('var', r'#.splice(#, 1)', this, i); |
return true; |
@@ -146,7 +146,7 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
for (int i = 0; i < end; i++) { |
// TODO(22407): Improve bounds check elimination to allow this JS code to |
// be replaced by indexing. |
- var element = JS('', '#[#]', this, i); |
+ E element = JS('-dynamic', '#[#]', this, i); |
// !test() ensures bool conversion in checked mode. |
if (!test(element) == removeMatching) { |
retained.add(element); |
@@ -155,8 +155,10 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
if (retained.length == end) return; |
this.length = retained.length; |
- for (int i = 0; i < retained.length; i++) { |
- this[i] = retained[i]; |
+ @nullCheck |
+ var length = retained.length; |
+ for (int i = 0; i < length; i++) { |
+ JS('', '#[#] = #[#]', this, i, retained, i); |
} |
} |
@@ -198,8 +200,9 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
String join([String separator = ""]) { |
- var list = new List(this.length); |
- for (int i = 0; i < this.length; i++) { |
+ var length = this.length; |
+ var list = new List(length); |
+ for (int i = 0; i < length; i++) { |
list[i] = "${this[i]}"; |
} |
return JS('String', "#.join(#)", list, separator); |
@@ -285,7 +288,7 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
for (int i = 0; i < length; i++) { |
// TODO(22407): Improve bounds check elimination to allow this JS code to |
// be replaced by indexing. |
- var element = JS('', '#[#]', this, i); |
+ E element = JS('-dynamic', '#[#]', this, i); |
if (test(element)) { |
if (matchFound) { |
throw IterableElementError.tooMany(); |
@@ -305,17 +308,16 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
return this[index]; |
} |
- List<E> sublist(int start, [int end]) { |
- checkNull(start); // TODO(ahe): This is not specified but co19 tests it. |
- if (start is! int) throw argumentErrorValue(start); |
+ List<E> sublist(@nullCheck int start, [int end]) { |
if (start < 0 || start > length) { |
throw new RangeError.range(start, 0, length, "start"); |
} |
if (end == null) { |
end = length; |
} else { |
- if (end is! int) throw argumentErrorValue(end); |
- if (end < start || end > length) { |
+ @notNull |
+ var _end = end; |
+ if (_end < start || _end > length) { |
throw new RangeError.range(end, start, length, "end"); |
} |
} |
@@ -344,14 +346,15 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
throw IterableElementError.tooMany(); |
} |
- void removeRange(int start, int end) { |
+ void removeRange(@nullCheck int start, @nullCheck int end) { |
checkGrowable('removeRange'); |
RangeError.checkValidRange(start, end, this.length); |
int deleteCount = end - start; |
JS('', '#.splice(#, #)', this, start, deleteCount); |
} |
- void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
+ void setRange(@nullCheck int start, @nullCheck int end, Iterable<E> iterable, |
+ [@nullCheck int skipCount = 0]) { |
checkMutable('set range'); |
RangeError.checkValidRange(start, end, this.length); |
@@ -359,10 +362,10 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
if (length == 0) return; |
RangeError.checkNotNegative(skipCount, "skipCount"); |
- List/*<E>*/ otherList; |
- int otherStart; |
+ List<E> otherList; |
+ int otherStart = 0; |
// TODO(floitsch): Make this accept more. |
- if (iterable is List) { |
+ if (iterable is List<E>) { |
otherList = iterable; |
otherStart = skipCount; |
} else { |
@@ -391,7 +394,7 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
} |
- void fillRange(int start, int end, [E fillValue]) { |
+ void fillRange(@nullCheck int start, @nullCheck int end, [E fillValue]) { |
checkMutable('fill range'); |
RangeError.checkValidRange(start, end, this.length); |
for (int i = start; i < end; i++) { |
@@ -400,13 +403,15 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
} |
- void replaceRange(int start, int end, Iterable<E> replacement) { |
+ void replaceRange( |
+ @nullCheck int start, @nullCheck int end, Iterable<E> replacement) { |
checkGrowable('replace range'); |
RangeError.checkValidRange(start, end, this.length); |
if (replacement is! EfficientLengthIterable) { |
replacement = replacement.toList(); |
} |
int removeLength = end - start; |
+ @nullCheck |
int insertLength = replacement.length; |
if (removeLength >= insertLength) { |
int delta = removeLength - insertLength; |
@@ -444,7 +449,7 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
for (int i = 0; i < end; i++) { |
// TODO(22407): Improve bounds check elimination to allow this JS code to |
// be replaced by indexing. |
- var/*=E*/ element = JS('', '#[#]', this, i); |
+ E element = JS('-dynamic', '#[#]', this, i); |
if (!test(element)) return false; |
if (this.length != end) throw new ConcurrentModificationError(this); |
} |
@@ -475,14 +480,15 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
} |
- int indexOf(Object element, [int start = 0]) { |
- if (start >= this.length) { |
+ int indexOf(Object element, [@nullCheck int start = 0]) { |
+ int length = this.length; |
+ if (start >= length) { |
return -1; |
} |
if (start < 0) { |
start = 0; |
} |
- for (int i = start; i < this.length; i++) { |
+ for (int i = start; i < length; i++) { |
if (this[i] == element) { |
return i; |
} |
@@ -490,16 +496,13 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
return -1; |
} |
- int lastIndexOf(Object element, [int startIndex]) { |
- if (startIndex == null) { |
+ int lastIndexOf(Object element, [int _startIndex]) { |
+ @notNull |
+ int startIndex = _startIndex ?? this.length - 1; |
+ if (startIndex >= this.length) { |
startIndex = this.length - 1; |
- } else { |
- if (startIndex < 0) { |
- return -1; |
- } |
- if (startIndex >= this.length) { |
- startIndex = this.length - 1; |
- } |
+ } else if (startIndex < 0) { |
+ return -1; |
} |
for (int i = startIndex; i >= 0; i--) { |
if (this[i] == element) { |
@@ -510,19 +513,23 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
} |
bool contains(Object other) { |
+ var length = this.length; |
for (int i = 0; i < length; i++) { |
- if (this[i] == other) return true; |
+ E element = JS('-dynamic | Null', '#[#]', this, i); |
+ if (element == other) return true; |
} |
return false; |
} |
+ @notNull |
bool get isEmpty => length == 0; |
+ @notNull |
bool get isNotEmpty => !isEmpty; |
String toString() => ListBase.listToString(this); |
- List<E> toList({bool growable: true}) { |
+ List<E> toList({@nullCheck bool growable: true}) { |
var list = JS('', '#.slice()', this); |
if (!growable) markFixedList(list); |
return new JSArray<E>.of(list); |
@@ -534,15 +541,14 @@ class JSArray<E> implements List<E>, JSIndexable<E> { |
int get hashCode => Primitives.objectHashCode(this); |
+ @notNull |
bool operator ==(other) => identical(this, other); |
+ @notNull |
int get length => JS('int', r'#.length', this); |
- void set length(int newLength) { |
+ void set length(@nullCheck int newLength) { |
checkGrowable('set length'); |
- if (newLength is! int) { |
- throw new ArgumentError.value(newLength, 'newLength'); |
- } |
// TODO(sra): Remove this test and let JavaScript throw an error. |
if (newLength < 0) { |
throw new RangeError.range(newLength, 0, null, 'newLength'); |
@@ -603,7 +609,9 @@ class JSUnmodifiableArray<E> extends JSArray<E> {} // Already is JSIndexable. |
/// |
class ArrayIterator<E> implements Iterator<E> { |
final JSArray<E> _iterable; |
+ @notNull |
final int _length; |
+ @notNull |
int _index; |
E _current; |
@@ -615,6 +623,7 @@ class ArrayIterator<E> implements Iterator<E> { |
E get current => _current; |
bool moveNext() { |
+ @notNull |
int length = _iterable.length; |
// We have to do the length check even on fixed length Arrays. If we can |