diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart index 94124c5bf95..fdf2f8ad991 100644 --- a/sdk_nnbd/lib/collection/list.dart +++ b/sdk_nnbd/lib/collection/list.dart @@ -262,8 +262,7 @@ abstract class ListMixin implements List { int i = this.length; for (E element in iterable) { assert(this.length == i || (throw ConcurrentModificationError(this))); - this.length = i + 1; - this[i] = element; + add(element); i++; } } @@ -424,6 +423,10 @@ abstract class ListMixin implements List { void replaceRange(int start, int end, Iterable newContents) { RangeError.checkValidRange(start, end, this.length); + if (start == this.length) { + addAll(newContents); + return; + } if (newContents is! EfficientLengthIterable) { newContents = newContents.toList(); } @@ -435,12 +438,26 @@ abstract class ListMixin implements List { if (removeLength > insertLength) { _closeGap(insertEnd, end); } + } else if (end == this.length) { + int i = start; + for (E element in newContents) { + if (i < end) { + this[i] = element; + } else { + add(element); + } + i++; + } } else { int delta = insertLength - removeLength; - int newLength = this.length + delta; + int oldLength = this.length; int insertEnd = start + insertLength; // aka. end + delta. - this.length = newLength; - this.setRange(insertEnd, newLength, this, end); + for (int i = oldLength - delta; i < oldLength; ++i) { + add(this[i > 0 ? i : 0]); + } + if (insertEnd < oldLength) { + this.setRange(insertEnd, oldLength, this, end); + } this.setRange(start, insertEnd, newContents); } } @@ -505,21 +522,34 @@ abstract class ListMixin implements List { void insertAll(int index, Iterable iterable) { RangeError.checkValueInInterval(index, 0, length, "index"); + if (index == length) { + addAll(iterable); + return; + } if (iterable is! EfficientLengthIterable || identical(iterable, this)) { iterable = iterable.toList(); } int insertionLength = iterable.length; + if (insertionLength == 0) { + return; + } // There might be errors after the length change, in which case the list // will end up being modified but the operation not complete. Unless we // always go through a "toList" we can't really avoid that. - this.length += insertionLength; + int oldLength = length; + for (int i = oldLength - insertionLength; i < oldLength; ++i) { + add(this[i > 0 ? i : 0]); + } if (iterable.length != insertionLength) { // If the iterable's length is linked to this list's length somehow, // we can't insert one in the other. this.length -= insertionLength; throw ConcurrentModificationError(iterable); } - setRange(index + insertionLength, this.length, this, index); + int oldCopyStart = index + insertionLength; + if (oldCopyStart < oldLength) { + setRange(oldCopyStart, oldLength, this, index); + } setAll(index, iterable); } diff --git a/tests/corelib/error_stack_trace2_test.dart b/tests/corelib/error_stack_trace2_test.dart index 74376513429..47f6a7da201 100644 --- a/tests/corelib/error_stack_trace2_test.dart +++ b/tests/corelib/error_stack_trace2_test.dart @@ -22,8 +22,7 @@ main() { } catch (e2) { var e = e2; hasThrown = true; - Expect.isTrue( - e.stackTrace is StackTrace, "$e doesn't have a non-null stack trace"); + Expect.isTrue(e is StackOverflowError); } Expect.isTrue(hasThrown); } diff --git a/tests/corelib/list_insert_all_test.dart b/tests/corelib/list_insert_all_test.dart index d089dc8ecb8..ea0b61f97f7 100644 --- a/tests/corelib/list_insert_all_test.dart +++ b/tests/corelib/list_insert_all_test.dart @@ -34,6 +34,10 @@ class MyList extends ListBase { list[index] = val; } + void add(T element) { + list.add(element); + } + toString() => list.toString(); } @@ -74,6 +78,11 @@ main() { test(new MyList([1, 2, 3]), 3, [4, 5].map((x) => x)); test(new MyList([1, 2, 3]), 2, [4].map((x) => x)); test(new MyList([1, 2, 3]), 3, [].map((x) => x)); + test(new MyList([]), 0, []); + test(new MyList([]), 0, [4]); + test(new MyList([]), 0, [4, 5]); + test(new MyList([1]), 0, [4, 5]); + test(new MyList([1]), 1, [4, 5]); Expect.throwsRangeError(() => test([1, 2, 3], -1, [4, 5])); Expect.throwsUnsupportedError( diff --git a/tests/corelib/list_replace_range_test.dart b/tests/corelib/list_replace_range_test.dart index 964ed444b91..59baafe9ffa 100644 --- a/tests/corelib/list_replace_range_test.dart +++ b/tests/corelib/list_replace_range_test.dart @@ -35,6 +35,10 @@ class MyList extends ListBase { list[index] = val; } + void add(T element) { + list.add(element); + } + toString() => list.toString(); } @@ -93,6 +97,11 @@ main() { test(new MyList([1, 2, 3]), 3, 3, new Iterable.generate(2, (x) => x + 4)); test(new MyList([1, 2, 3]), 0, 3, new Iterable.generate(2, (x) => x + 4)); test(new MyList([1, 2, 3]), 2, 3, new Iterable.generate(2, (x) => x + 4)); + test(new MyList([]), 0, 0, []); + test(new MyList([]), 0, 0, [4]); + test(new MyList([]), 0, 0, [4, 5]); + test(new MyList([1]), 0, 1, [4, 5]); + test(new MyList([1]), 1, 1, [4, 5]); Expect.throwsRangeError(() => test([1, 2, 3], -1, 0, [])); Expect.throwsRangeError(() => test([1, 2, 3], 2, 1, []));