Merge remote-tracking branch 'origin/master' into queue
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fdc728..7edf873 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
   `Queue` and `List` with a highly-efficient typed-data-backed implementation.
   Their `sublist()` methods also return typed data classes.
 
+* Update min Dart SDK to `2.4.0`.
+
 ## 1.1.6
 
 * Set max SDK version to `<3.0.0`, and adjust other dependencies.
diff --git a/lib/typed_buffers.dart b/lib/typed_buffers.dart
index f2e407d..17964c2 100644
--- a/lib/typed_buffers.dart
+++ b/lib/typed_buffers.dart
@@ -13,8 +13,8 @@
 /// be larger than what the list is using.
 library typed_data.typed_buffers;
 
-import "dart:collection" show ListBase;
-import "dart:typed_data";
+import 'dart:collection' show ListBase;
+import 'dart:typed_data';
 
 abstract class _TypedDataBuffer<E> extends ListBase<E> {
   static const int _initialLength = 8;
@@ -35,22 +35,26 @@
       : _buffer = buffer,
         _length = buffer.length;
 
+  @override
   int get length => _length;
 
+  @override
   E operator [](int index) {
     if (index >= length) throw RangeError.index(index, this);
     return _buffer[index];
   }
 
+  @override
   void operator []=(int index, E value) {
     if (index >= length) throw RangeError.index(index, this);
     _buffer[index] = value;
   }
 
+  @override
   set length(int newLength) {
     if (newLength < _length) {
-      E defaultValue = _defaultValue;
-      for (int i = newLength; i < _length; i++) {
+      var defaultValue = _defaultValue;
+      for (var i = newLength; i < _length; i++) {
         _buffer[i] = defaultValue;
       }
     } else if (newLength > _buffer.length) {
@@ -74,6 +78,7 @@
   // We override the default implementation of `add` because it grows the list
   // by setting the length in increments of one. We want to grow by doubling
   // capacity in most cases.
+  @override
   void add(E value) {
     _add(value);
   }
@@ -87,10 +92,11 @@
   /// The [start] value must be non-negative. The [values] iterable must have at
   /// least [start] elements, and if [end] is specified, it must be greater than
   /// or equal to [start] and [values] must have at least [end] elements.
+  @override
   void addAll(Iterable<E> values, [int start = 0, int end]) {
-    RangeError.checkNotNegative(start, "start");
+    RangeError.checkNotNegative(start, 'start');
     if (end != null && start > end) {
-      throw RangeError.range(end, start, null, "end");
+      throw RangeError.range(end, start, null, 'end');
     }
 
     _addAll(values, start, end);
@@ -105,12 +111,13 @@
   /// The [start] value must be non-negative. The [values] iterable must have at
   /// least [start] elements, and if [end] is specified, it must be greater than
   /// or equal to [start] and [values] must have at least [end] elements.
+  @override
   void insertAll(int index, Iterable<E> values, [int start = 0, int end]) {
-    RangeError.checkValidIndex(index, this, "index", _length + 1);
-    RangeError.checkNotNegative(start, "start");
+    RangeError.checkValidIndex(index, this, 'index', _length + 1);
+    RangeError.checkNotNegative(start, 'start');
     if (end != null) {
       if (start > end) {
-        throw RangeError.range(end, start, null, "end");
+        throw RangeError.range(end, start, null, 'end');
       }
       if (start == end) return;
     }
@@ -148,10 +155,10 @@
     }
 
     if (skipCount > 0) {
-      throw StateError("Too few elements");
+      throw StateError('Too few elements');
     }
     if (end != null && writeIndex < end) {
-      throw RangeError.range(end, start, writeIndex, "end");
+      throw RangeError.range(end, start, writeIndex, 'end');
     }
 
     // Swap [index.._length) and [_length..writeIndex) by double-reversing.
@@ -197,7 +204,7 @@
       if (i >= start) add(value);
       i++;
     }
-    if (i < start) throw StateError("Too few elements");
+    if (i < start) throw StateError('Too few elements');
   }
 
   /// Like [insertAll], but with a guaranteed non-`null` [start] and [end].
@@ -205,7 +212,7 @@
     if (values is List) {
       end ??= values.length;
       if (start > values.length || end > values.length) {
-        throw StateError("Too few elements");
+        throw StateError('Too few elements');
       }
     } else {
       assert(end != null);
@@ -221,6 +228,7 @@
     _length = newLength;
   }
 
+  @override
   void insert(int index, E element) {
     if (index < 0 || index > _length) {
       throw RangeError.range(index, 0, _length);
@@ -231,7 +239,7 @@
       _length++;
       return;
     }
-    List<E> newBuffer = _createBiggerBuffer(null);
+    var newBuffer = _createBiggerBuffer(null);
     newBuffer.setRange(0, index, _buffer);
     newBuffer.setRange(index + 1, _length + 1, _buffer, index);
     newBuffer[index] = element;
@@ -256,7 +264,7 @@
   /// size. It will always have at least have double the capacity of
   /// the current buffer.
   List<E> _createBiggerBuffer(int requiredCapacity) {
-    int newLength = _buffer.length * 2;
+    var newLength = _buffer.length * 2;
     if (requiredCapacity != null && newLength < requiredCapacity) {
       newLength = requiredCapacity;
     } else if (newLength < _initialLength) {
@@ -272,6 +280,7 @@
     _buffer = _createBiggerBuffer(null)..setRange(0, length, _buffer);
   }
 
+  @override
   void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
     if (end > _length) throw RangeError.range(end, 0, _length);
     _setRange(start, end, source, skipCount);
@@ -315,24 +324,28 @@
 abstract class _IntBuffer extends _TypedDataBuffer<int> {
   _IntBuffer(List<int> buffer) : super(buffer);
 
+  @override
   int get _defaultValue => 0;
 }
 
 abstract class _FloatBuffer extends _TypedDataBuffer<double> {
   _FloatBuffer(List<double> buffer) : super(buffer);
 
+  @override
   double get _defaultValue => 0.0;
 }
 
 class Uint8Buffer extends _IntBuffer {
   Uint8Buffer([int initialLength = 0]) : super(Uint8List(initialLength));
 
+  @override
   Uint8List _createBuffer(int size) => Uint8List(size);
 }
 
 class Int8Buffer extends _IntBuffer {
   Int8Buffer([int initialLength = 0]) : super(Int8List(initialLength));
 
+  @override
   Int8List _createBuffer(int size) => Int8List(size);
 }
 
@@ -340,54 +353,63 @@
   Uint8ClampedBuffer([int initialLength = 0])
       : super(Uint8ClampedList(initialLength));
 
+  @override
   Uint8ClampedList _createBuffer(int size) => Uint8ClampedList(size);
 }
 
 class Uint16Buffer extends _IntBuffer {
   Uint16Buffer([int initialLength = 0]) : super(Uint16List(initialLength));
 
+  @override
   Uint16List _createBuffer(int size) => Uint16List(size);
 }
 
 class Int16Buffer extends _IntBuffer {
   Int16Buffer([int initialLength = 0]) : super(Int16List(initialLength));
 
+  @override
   Int16List _createBuffer(int size) => Int16List(size);
 }
 
 class Uint32Buffer extends _IntBuffer {
   Uint32Buffer([int initialLength = 0]) : super(Uint32List(initialLength));
 
+  @override
   Uint32List _createBuffer(int size) => Uint32List(size);
 }
 
 class Int32Buffer extends _IntBuffer {
   Int32Buffer([int initialLength = 0]) : super(Int32List(initialLength));
 
+  @override
   Int32List _createBuffer(int size) => Int32List(size);
 }
 
 class Uint64Buffer extends _IntBuffer {
   Uint64Buffer([int initialLength = 0]) : super(Uint64List(initialLength));
 
+  @override
   Uint64List _createBuffer(int size) => Uint64List(size);
 }
 
 class Int64Buffer extends _IntBuffer {
   Int64Buffer([int initialLength = 0]) : super(Int64List(initialLength));
 
+  @override
   Int64List _createBuffer(int size) => Int64List(size);
 }
 
 class Float32Buffer extends _FloatBuffer {
   Float32Buffer([int initialLength = 0]) : super(Float32List(initialLength));
 
+  @override
   Float32List _createBuffer(int size) => Float32List(size);
 }
 
 class Float64Buffer extends _FloatBuffer {
   Float64Buffer([int initialLength = 0]) : super(Float64List(initialLength));
 
+  @override
   Float64List _createBuffer(int size) => Float64List(size);
 }
 
@@ -396,8 +418,10 @@
 
   Int32x4Buffer([int initialLength = 0]) : super(Int32x4List(initialLength));
 
+  @override
   Int32x4 get _defaultValue => _zero;
 
+  @override
   Int32x4List _createBuffer(int size) => Int32x4List(size);
 }
 
@@ -405,7 +429,9 @@
   Float32x4Buffer([int initialLength = 0])
       : super(Float32x4List(initialLength));
 
+  @override
   Float32x4 get _defaultValue => Float32x4.zero();
 
+  @override
   Float32x4List _createBuffer(int size) => Float32x4List(size);
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index fecb4ef..7f2a21d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,7 +7,7 @@
 homepage: https://github.com/dart-lang/typed_data
 
 environment:
-  sdk: '>=2.2.2 <3.0.0'
+  sdk: '>=2.4.0 <3.0.0'
 
 dependencies:
   collection: ^1.1.0
diff --git a/test/typed_buffers_test.dart b/test/typed_buffers_test.dart
index 10a148b..3f682b1 100644
--- a/test/typed_buffers_test.dart
+++ b/test/typed_buffers_test.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('!vm')
-import "dart:typed_data";
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:typed_data/typed_buffers.dart";
+import 'package:test/test.dart';
+import 'package:typed_data/typed_buffers.dart';
 
 const List<int> browserSafeIntSamples = [
   0x8000000000000000, // 2^63
@@ -46,7 +46,7 @@
 void initTests(List<int> intSamples) {
   testUint(intSamples, 8, (l) => Uint8Buffer(l));
   testInt(intSamples, 8, (l) => Int8Buffer(l));
-  test("Uint8ClampedBuffer", () {
+  test('Uint8ClampedBuffer', () {
     testIntBuffer(
         intSamples, 8, 0, 255, (l) => Uint8ClampedBuffer(l), clampUint8);
   });
@@ -58,10 +58,10 @@
 
   testUint(intSamples, 64, (l) => Uint64Buffer(l),
       // JS doesn't support 64-bit ints, so only test this on the VM.
-      testOn: "dart-vm");
+      testOn: 'dart-vm');
   testInt(intSamples, 64, (l) => Int64Buffer(l),
       // JS doesn't support 64-bit ints, so only test this on the VM.
-      testOn: "dart-vm");
+      testOn: 'dart-vm');
 
   testInt32x4Buffer(intSamples);
 
@@ -71,9 +71,9 @@
 
   testFloat32x4Buffer(roundedFloatSamples);
 
-  group("addAll", () {
+  group('addAll', () {
     for (var type in ['a list', 'an iterable']) {
-      group("with $type", () {
+      group('with $type', () {
         Iterable<int> source;
         Uint8Buffer buffer;
         setUp(() {
@@ -84,7 +84,7 @@
           buffer = Uint8Buffer();
         });
 
-        test("adds values to the buffer", () {
+        test('adds values to the buffer', () {
           buffer.addAll(source, 1, 4);
           expect(buffer, equals([2, 3, 4]));
 
@@ -95,7 +95,7 @@
           expect(buffer, equals([2, 3, 4, 5, 1]));
         });
 
-        test("does nothing for empty slices", () {
+        test('does nothing for empty slices', () {
           buffer.addAll([6, 7, 8, 9, 10]);
 
           buffer.addAll(source, 0, 0);
@@ -111,7 +111,7 @@
           expect(buffer, equals([6, 7, 8, 9, 10]));
         });
 
-        test("throws errors for invalid start and end", () {
+        test('throws errors for invalid start and end', () {
           expect(() => buffer.addAll(source, -1), throwsRangeError);
           expect(() => buffer.addAll(source, -1, 2), throwsRangeError);
           expect(() => buffer.addAll(source, 10), throwsStateError);
@@ -124,9 +124,9 @@
     }
   });
 
-  group("insertAll", () {
+  group('insertAll', () {
     for (var type in ['a list', 'an iterable']) {
-      group("with $type", () {
+      group('with $type', () {
         Iterable<int> source;
         Uint8Buffer buffer;
         setUp(() {
@@ -137,7 +137,7 @@
           buffer = Uint8Buffer()..addAll([6, 7, 8, 9, 10]);
         });
 
-        test("inserts values into the buffer", () {
+        test('inserts values into the buffer', () {
           buffer.insertAll(0, source, 1, 4);
           expect(buffer, equals([2, 3, 4, 6, 7, 8, 9, 10]));
 
@@ -149,13 +149,13 @@
         });
 
         // Regression test for #1.
-        test("inserts values into the buffer after removeRange()", () {
+        test('inserts values into the buffer after removeRange()', () {
           buffer.removeRange(1, 4);
           buffer.insertAll(1, source);
           expect(buffer, equals([6, 1, 2, 3, 4, 5, 10]));
         });
 
-        test("does nothing for empty slices", () {
+        test('does nothing for empty slices', () {
           buffer.insertAll(1, source, 0, 0);
           expect(buffer, equals([6, 7, 8, 9, 10]));
 
@@ -169,7 +169,7 @@
           expect(buffer, equals([6, 7, 8, 9, 10]));
         });
 
-        test("throws errors for invalid start and end", () {
+        test('throws errors for invalid start and end', () {
           expect(() => buffer.insertAll(-1, source), throwsRangeError);
           expect(() => buffer.insertAll(6, source), throwsRangeError);
           expect(() => buffer.insertAll(1, source, -1), throwsRangeError);
@@ -234,8 +234,8 @@
 }
 
 Rounder intRounder(bits) {
-  int highBit = 1 << (bits - 1);
-  int mask = highBit - 1;
+  var highBit = 1 << (bits - 1);
+  var mask = highBit - 1;
   return (int x) => (x & mask) - (x & highBit);
 }
 
@@ -243,9 +243,9 @@
   return (Float32List(1)..[0] = value)[0];
 }
 
-testFloat32x4Buffer(List floatSamples) {
+void testFloat32x4Buffer(List floatSamples) {
   var float4Samples = <Float32x4>[];
-  for (int i = 0; i < floatSamples.length - 3; i++) {
+  for (var i = 0; i < floatSamples.length - 3; i++) {
     float4Samples.add(Float32x4(floatSamples[i], floatSamples[i + 1],
         floatSamples[i + 2], floatSamples[i + 3]));
   }
@@ -265,7 +265,7 @@
     floatEquals(x.w, y.w);
   }
 
-  test("Float32x4Buffer", () {
+  test('Float32x4Buffer', () {
     var buffer = Float32x4Buffer(5);
     expect(buffer, const TypeMatcher<List<Float32x4>>());
 
@@ -286,12 +286,12 @@
 
     buffer.addAll(float4Samples);
     expect(buffer.length, equals(float4Samples.length * 2));
-    for (int i = 0; i < float4Samples.length; i++) {
+    for (var i = 0; i < float4Samples.length; i++) {
       x4Equals(buffer[i], buffer[float4Samples.length + i]);
     }
 
     buffer.removeRange(4, 4 + float4Samples.length);
-    for (int i = 0; i < float4Samples.length; i++) {
+    for (var i = 0; i < float4Samples.length; i++) {
       x4Equals(buffer[i], float4Samples[i]);
     }
 
@@ -299,7 +299,7 @@
     buffer.length = 1;
     buffer[0] = float4Samples[0]; // Does not contain NaN.
 
-    Float32List floats = Float32List.view(buffer.buffer);
+    var floats = Float32List.view(buffer.buffer);
     expect(floats[0], equals(buffer[0].x));
     expect(floats[1], equals(buffer[0].y));
     expect(floats[2], equals(buffer[0].z));
@@ -311,11 +311,15 @@
 // the rounding that is applied when storing values outside the valid range
 // into the buffer.
 void testFloatBuffer(
-    int bitSize, List<double> samples, create(), double round(double v)) {
-  test("Float${bitSize}Buffer", () {
+  int bitSize,
+  List<double> samples,
+  Function() create,
+  double Function(double v) round,
+) {
+  test('Float${bitSize}Buffer', () {
     var buffer = create();
     expect(buffer, const TypeMatcher<List<double>>());
-    int byteSize = bitSize ~/ 8;
+    var byteSize = bitSize ~/ 8;
 
     expect(buffer.length, equals(0));
     buffer.add(0.0);
@@ -323,7 +327,7 @@
     expect(buffer.removeLast(), equals(0.0));
     expect(buffer.length, equals(0));
 
-    for (double value in samples) {
+    for (var value in samples) {
       buffer.add(value);
       doubleEqual(buffer[buffer.length - 1], round(value));
     }
@@ -331,7 +335,7 @@
 
     buffer.addAll(samples);
     expect(buffer.length, equals(samples.length * 2));
-    for (int i = 0; i < samples.length; i++) {
+    for (var i = 0; i < samples.length; i++) {
       doubleEqual(buffer[i], buffer[samples.length + i]);
     }
 
@@ -340,7 +344,7 @@
 
     buffer.insertAll(0, samples);
     expect(buffer.length, equals(samples.length * 2));
-    for (int i = 0; i < samples.length; i++) {
+    for (var i = 0; i < samples.length; i++) {
       doubleEqual(buffer[i], buffer[samples.length + i]);
     }
 
@@ -358,8 +362,8 @@
     buffer[0] = samples[0];
     buffer[1] = samples[1];
     var bytes = Uint8List.view(buffer.buffer);
-    for (int i = 0; i < byteSize; i++) {
-      int tmp = bytes[i];
+    for (var i = 0; i < byteSize; i++) {
+      var tmp = bytes[i];
       bytes[i] = bytes[byteSize + i];
       bytes[byteSize + i] = tmp;
     }
@@ -368,18 +372,18 @@
   });
 }
 
-void testInt(List<int> intSamples, int bits, buffer(int length),
+void testInt(List<int> intSamples, int bits, void Function(int length) buffer,
     {String testOn}) {
-  int min = -(1 << (bits - 1));
-  int max = -(min + 1);
-  test("Int${bits}Buffer", () {
+  var min = -(1 << (bits - 1));
+  var max = -(min + 1);
+  test('Int${bits}Buffer', () {
     testIntBuffer(intSamples, bits, min, max, buffer, intRounder(bits));
   }, testOn: testOn);
 }
 
 void testInt32x4Buffer(List<int> intSamples) {
-  test("Int32x4Buffer", () {
-    int bytes = 128 ~/ 8;
+  test('Int32x4Buffer', () {
+    var bytes = 128 ~/ 8;
     Matcher equals32x4(Int32x4 expected) => MatchesInt32x4(expected);
 
     var buffer = Int32x4Buffer(0);
@@ -390,7 +394,7 @@
     expect(buffer.lengthInBytes, equals(0));
     expect(buffer.offsetInBytes, equals(0));
 
-    Int32x4 sample = Int32x4(-0x80000000, -1, 0, 0x7fffffff);
+    var sample = Int32x4(-0x80000000, -1, 0, 0x7fffffff);
     buffer.add(sample);
     expect(buffer.length, equals(1));
     expect(buffer[0], equals32x4(sample));
@@ -405,15 +409,15 @@
     var samples = intSamples
         .map((value) => Int32x4(value, -value, ~value, ~ -value))
         .toList();
-    for (Int32x4 value in samples) {
-      int length = buffer.length;
+    for (var value in samples) {
+      var length = buffer.length;
       buffer.add(value);
       expect(buffer.length, equals(length + 1));
       expect(buffer[length], equals32x4(value));
     }
 
     buffer.addAll(samples); // Add all the values at once.
-    for (int i = 0; i < samples.length; i++) {
+    for (var i = 0; i < samples.length; i++) {
       expect(buffer[samples.length + i], equals32x4(buffer[i]));
     }
 
@@ -425,9 +429,9 @@
     buffer.length = 2;
     buffer[0] = Int32x4(-80000000, 0x7fffffff, 0, -1);
     var byteBuffer = Uint8List.view(buffer.buffer);
-    int halfBytes = bytes ~/ 2;
-    for (int i = 0; i < halfBytes; i++) {
-      int tmp = byteBuffer[i];
+    var halfBytes = bytes ~/ 2;
+    for (var i = 0; i < halfBytes; i++) {
+      var tmp = byteBuffer[i];
       byteBuffer[i] = byteBuffer[halfBytes + i];
       byteBuffer[halfBytes + i] = tmp;
     }
@@ -437,7 +441,7 @@
 }
 
 void testIntBuffer(List<int> intSamples, int bits, int min, int max,
-    create(int length), int round(int val)) {
+    Function(int length) create, int Function(int val) round) {
   assert(round(min) == min);
   assert(round(max) == max);
   // All int buffers default to the value 0.
@@ -462,14 +466,14 @@
   expect(buffer.length, equals(0));
 
   List samples = intSamples.toList()..addAll(intSamples.map((x) => -x));
-  for (int value in samples) {
+  for (var value in samples) {
     int length = buffer.length;
     buffer.add(value);
     expect(buffer.length, equals(length + 1));
     expect(buffer[length], equals(round(value)));
   }
   buffer.addAll(samples); // Add all the values at once.
-  for (int i = 0; i < samples.length; i++) {
+  for (var i = 0; i < samples.length; i++) {
     expect(buffer[samples.length + i], equals(buffer[i]));
   }
 
@@ -497,9 +501,9 @@
   buffer[0] = min;
   buffer[1] = max;
   var byteBuffer = Uint8List.view(buffer.buffer);
-  int byteSize = buffer.elementSizeInBytes;
-  for (int i = 0; i < byteSize; i++) {
-    int tmp = byteBuffer[i];
+  var byteSize = buffer.elementSizeInBytes;
+  for (var i = 0; i < byteSize; i++) {
+    var tmp = byteBuffer[i];
     byteBuffer[i] = byteBuffer[byteSize + i];
     byteBuffer[byteSize + i] = tmp;
   }
@@ -507,19 +511,19 @@
   expect(buffer[1], equals(min));
 }
 
-void testUint(List<int> intSamples, int bits, buffer(int length),
+void testUint(List<int> intSamples, int bits, void Function(int length) buffer,
     {String testOn}) {
-  int min = 0;
+  var min = 0;
   var rounder = uintRounder(bits);
-  int max = rounder(-1);
-  test("Uint${bits}Buffer", () {
+  var max = rounder(-1);
+  test('Uint${bits}Buffer', () {
     testIntBuffer(intSamples, bits, min, max, buffer, rounder);
   }, testOn: testOn);
 }
 
 Rounder uintRounder(bits) {
-  int halfbits = (1 << (bits ~/ 2)) - 1;
-  int mask = halfbits | (halfbits << (bits ~/ 2));
+  var halfbits = (1 << (bits ~/ 2)) - 1;
+  var mask = halfbits | (halfbits << (bits ~/ 2));
   return (int x) => x & mask;
 }
 
@@ -530,9 +534,11 @@
 
   MatchesInt32x4(this.result);
 
+  @override
   Description describe(Description description) =>
       description.add('Int32x4.==');
 
+  @override
   bool matches(item, Map matchState) {
     if (item is! Int32x4) return false;
     Int32x4 value = item;
diff --git a/test/typed_buffers_vm_test.dart b/test/typed_buffers_vm_test.dart
index ad3100c..44a66bf 100644
--- a/test/typed_buffers_vm_test.dart
+++ b/test/typed_buffers_vm_test.dart
@@ -15,5 +15,8 @@
     0x7fffffffffffffff,
     0x5555555555555555,
   ];
-  initTests(<int>[]..addAll(browserSafeIntSamples)..addAll(browserUnsafe));
+  initTests(<int>[
+    ...browserSafeIntSamples,
+    ...browserUnsafe,
+  ]);
 }